<!--

var SU = {
    //Attach to onkeypress to check if 'Enter' key pressed
    cfe: function(e)
    {
        var code;
        if (!e) var e = window.event;
        if (e.keyCode) code = e.keyCode;
        else if (e.which) code = e.which;
        if(code == 13)  return true;
        else return false;
    },

    getKC: function(e)
    {
        if (e.keyCode) return(e.keyCode);
        else return(e.which);
    },
    isEmail: function(s)
    {
	   var filter  = /^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/;
	   if (filter.test(s)) return true;
	   else return false;
    },
    sfcca:function (cca)
    {
        var s = "";
        for(var i=0;i<cca.length;i++){s += String.fromCharCode(cca[i]);}
        return s;
    },
    ea:function(ta)
    {
        for(var i=0;i<ta.length;i++)
        {
            if(i%2 == 0) ta[i]++;
            else ta[i]--;
        }
    },
    da:function(ta)
    {
        for(var i=0;i<ta.length;i++)
        {
            if(i%2 == 0) ta[i]--;
            else ta[i]++;
        }
    },
    dhs:function(ta,cs)
    {
        var na = new Array();
        $.merge(na,ta);
        SU.da(na);
        var s = SU.sfcca(na);
        if(cs.toLowerCase().indexOf(s) == -1) return false;
        else return true;
    }
}

Array.prototype.contains = function (element)
{
    for (var i = 0; i < this.length; i++)
    {
        if (this[i] == element)
        {return true;}
    }          
    return false;
};
Array.prototype.intArrayToString = function() {
    var a = new String();
    for (var i = 0; i < this.length; i++) {
        if(typeof this[i] != "number") {
            throw new Error("Array must be all numbers");
        } else if (this[i] < 0) {
            throw new Error("Numbers must be 0 and up");
        }
        a += String.fromCharCode(this[i]);
    }
    return a;
}

if(!document.all && (navigator.userAgent.toLowerCase().indexOf('safari')==-1))
{
    // add outerHTML for Firefox
    var _emptyTags = {
        "IMG":   true,
        "BR":    true,
        "INPUT": true,
        "META":  true,
        "LINK":  true,
        "PARAM": true,
        "HR":    true
    };

    HTMLElement.prototype.__defineGetter__("outerHTML", function () {
        var attrs = this.attributes;
        var str = "<" + this.tagName;
        for (var i = 0; i < attrs.length; i++)
        str += " " + attrs[i].name + "=\"" + attrs[i].value + "\"";

        if (_emptyTags[this.tagName])
           return str + ">";

        return str + ">" + this.innerHTML + "</" + this.tagName + ">";
        });
}    

/*
 * Color manipulation functions
 */
 
function toHex(c) {
  var r, g, b;
  r = c[0].toString(16);
  if (c[0] < 0x10) {
    r = "0" + r;
  }
  g = c[1].toString(16);
  if (c[1] < 0x10) {
    g = "0" + g;
  }
  b = c[2].toString(16);
  if (c[2] < 0x10) {
    b = "0" + b;
  }
  return (r + g + b).toUpperCase();
}

function toColor(h) 
{
  return [ parseInt(h.substring(0, 2), 16),
           parseInt(h.substring(2, 4), 16),
           parseInt(h.substring(4, 6), 16) ];
}


/*
 * new focus field - elements need to just share className
 * startFrom is optional element in DOM - improves performance
 */
function ff(elem,startFrom)
{
    var cn = elem.className;
    var v = document.getElementsByClassName(cn,startFrom); // fn from prototype
    //alert("got to ff, elem.nodeName: "+elem.nodeName+" cn: "+cn+" startFrom: "+startFrom+" v.length: "+v.length+" document.getElementsByClassName: "+document.getElementsByClassName );
    for (var i = 0; i < v.length; i++)
    {
        if(v[i].type =="radio") try{v[i].checked = true}catch(err){};
        if(v[i].type =="text") try{v[i].focus()}catch(err){};
        if(v[i].type =="text") try{v[i].select()}catch(err){};
    }
}



/*
 *   Image Scaling & Manipulation Methods
 */

function getNaturalHeight(img)
{
    if( img.naturalHeight )
    {
        return img.naturalHeight;
    } else
    {
        lgi = new Image();
        lgi.src = img.src;
        return lgi.height;
    }
}

function getNaturalWidth(img)
{
    if( img.naturalWidth )
    {
        return img.naturalWidth;
    } else 
    {
        lgi = new Image();
        lgi.src = img.src;
        return lgi.width;
    }
}

// this does not work yet.  Supposed to work in conjunction with a center image
// function which still needs to be developed

function scaleNatural(img, box)
{
    return;
    var w = box.offsetWidth;
    var h = box.offsetHeight;
    
    img.nw = getNaturalWidth(img);
    img.nh = getNaturalHeight(img);
    
    //alert("scaleNatural box w,h  :"+w+","+h+"  image nw,nh  :"+img.nw+","+img.nh);

    var scaleH = box.clientHeight / img.clientHeight;
    var scaleW = box.clientWidth / img.clientWidth;

    if(img.nw > w)
    {
        img.style.width = (w-10)+"px";
    } else
    {
        img.style.width = img.nw+"px";
    }

    if(img.nh > h)
    {
        img.style.height = h+"px";
        var mt = 0;
        img.style.marginTop = mt+"px";
    } else
    {
        img.style.height = img.nh+"px";
          //var mt = (((h-40)-postings[i].nh)/2);
          //postings[i].theElem.style.marginTop = mt+"px";
    }
}
function centerItem()
{
    var theItem = $("xitm");

    iw = theItem.offsetWidth;
    ih = theItem.offsetHeight;

    pw = theItem.parentNode.offsetWidth;
    ph = theItem.parentNode.offsetHeight;

    //alert("iw,ih is: "+iw+","+ih+"\npw,ph is: "+pw+","+ph+"  $(\"dgbiw\").offsetHeight is: "+$("dgbiw").offsetHeight);

    var topPos = Math.round((ph-ih)/2);
    var leftPos = Math.round((pw-iw)/2);

    //alert("topPos,leftPos is: "+topPos+","+leftPos);

    theItem.style.top = topPos+"px"
    //theItem.style.top = "-7px";
    theItem.style.left = leftPos+"px"
    //theItem.parentNode.style.border = "1px solid #fff";
}

// this function sort of works - but poorly
// needs research but is best we have for now (Nov. 06)

function isImageOk(img)
{
    try {if (!img.complete) return false;} // IE
    catch (err){ return false; }
    if (typeof img.naturalWidth != "undefined" && img.naturalWidth == 0) return false; // Moz
    return true;
}

/****************************************************************/

// extension to js String Object to allow trim
// usage:  string.trim()

String.prototype.trim = function() 
{
    a = this.replace(/^\s+/, '');
    return a.replace(/\s+$/, '');
};

String.prototype.equalsIgnoreCase=myEqualsIgnoreCase;
String.prototype.equals=myEquals;
String.prototype.isEmpty=myIsEmpty;
String.prototype.isWhitespace=myIsWhitespace;

function myEquals(arg)
{
    return (this.toString()==arg.toString());
}

function myEqualsIgnoreCase(arg)
{
    return (new String(this.toLowerCase())==(new String(arg)).toLowerCase());
}


String.prototype.capitalize = function(){
    return this.replace(/\w+/g, function(a){
        return a.charAt(0).toUpperCase() + a.substr(1).toLowerCase();
    });
};
String.prototype.toInt = function() {
    var a = new Array();
    for (var i = 0; i < this.length; i++) {
        a[i] = this.charCodeAt(i);
    }
    return a;
}


// Check whether string s is empty.

function myIsEmpty()
{
    return ((this == null) || (this.length == 0))
}

/****************************************************************/

// whitespace characters
var whitespace = " \t\n\r";

// Returns true if string s is empty or
// whitespace characters only.

function myIsWhitespace()
{   
    var i;
    // Is s empty?
    if (this.isEmpty()) return true;

    // Search through string's characters one by one
    // until we find a non-whitespace character.
    // When we do, return false; if we don't, return true.

    for (i = 0; i < this.length; i++)
    {   
	// Check that current character isn't whitespace.
	var c = this.charAt(i);

	if (whitespace.indexOf(c) == -1) return false;
    }

    // All characters are whitespace.
    return true;
}



// generate a random string supplying length
function randomString(len)
{
	var chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz";
	var randomstring = '';
	for (var i=0; i<len; i++) 
     {
		var rnum = Math.floor(Math.random() * chars.length);
		randomstring += chars.substring(rnum,rnum+1);
	}
	return randomstring;
}



/**
 *  Basic cookie functions
 */
function createCookie(name,value,days)
{
	if (days)
	{
		var date = new Date();
		date.setTime(date.getTime()+(days*24*60*60*1000));
		var expires = "; expires="+date.toGMTString();
	}
	else var expires = "";
	document.cookie = name+"="+value+expires+"; path=/";
}

function readCookie(name)
{
	var nameEQ = name + "=";
	var ca = document.cookie.split(';');
	for(var i=0;i < ca.length;i++)
	{
		var c = ca[i];
		while (c.charAt(0)==' ') c = c.substring(1,c.length);
		if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
	}
	return null;
}

function eraseCookie(name)
{
	createCookie(name,"",-1);
}




/*
 *  CSS Stylesheet Manipulation Functions
 *
 * first code is inline to "initialize" cssRules variable
 * to normalize between IE and Firefox - also functions need to use
 * String extension equalsIgnoreCase - as element selectors are held as
 * uppercase by browser in memory - even if entered in lowercase in the
 * stylesheet itself.
 */
 
var cssRules;
if (document.all)
{
    cssRules = 'rules';
} else if (document.getElementById)
{
    cssRules = 'cssRules';
}


/* function to change definition of a CSS Style dynamically */
function changecss(theClass,property,value,theSheet)
{
    if(theSheet != null)
    {
        var theSS = getSheetByTitle(theSheet)
        for (var R = 0; R < theSS[cssRules].length; R++)
        {
            if (theSS[cssRules][R].selectorText.equalsIgnoreCase(theClass) )
            {
                //alert("got here theClass:"+theClass+" theSS[cssRules]["+R+"].selectorText: "+theSS[cssRules][R].selectorText );
                theSS[cssRules][R].style[property] = value;
            }
        }
    } else
    {
        for (var S = 0; S < document.styleSheets.length; S++)
        {
            for (var R = 0; R < document.styleSheets[S][cssRules].length; R++)
            {
                if (document.styleSheets[S][cssRules][R].selectorText.equalsIgnoreCase(theClass) )
                {
                    document.styleSheets[S][cssRules][R].style[property] = value;
                }
            }
        }
    }
}


/* get CSS style object for a given selector */
function getStyle(theSelector, theSheet)
{
    // if a specific stylesheet name is supplied use it - if not
    if(theSheet != null)
    {

        var theSS = getSheetByTitle(theSheet)
        //alert("theSheet is: "+theSheet+" theSS is: "+theSS);
        for (var R = 0; R < theSS[cssRules].length; R++)
        {
            if (theSS[cssRules][R].selectorText.equalsIgnoreCase(theSelector) )
            {
                return theSS[cssRules][R].style;
            }
        }
    } else
    {
        for (var S = 0; S < document.styleSheets.length; S++)
        {
            for (var R = 0; R < document.styleSheets[S][cssRules].length; R++)
            {
                if (document.styleSheets[S][cssRules][R].selectorText.equalsIgnoreCase(theSelector) )
                {
                    return document.styleSheets[S][cssRules][R].style;
                }
            }
        }
    }
}

function hasCSSRule(theSelector, theSheet)
{
    if (getStyle(theSelector, theSheet)) return true;
    else return false;
}

function getSheetByTitle(theTitle)
{
    for (var i=0;i<document.styleSheets.length;i++)
    {
        if (document.styleSheets[i].title.equalsIgnoreCase(theTitle) )
        {
            return document.styleSheets[i];
        }
    }
}


function getStyleProperty (theSelector, propertyName, theSheet)
{
    var styleForSelector = getStyle(theSelector, theSheet);
    if (styleForSelector) return styleForSelector[propertyName];

    return null;
}

function setActiveStyleSheet(title)
{
   var i, a, main;
   for(i=0; (a = document.getElementsByTagName("link")[i]); i++) {
     if(a.getAttribute("rel").indexOf("style") != -1
        && a.getAttribute("title")) {
       a.disabled = true;
       if(a.getAttribute("title") == title) a.disabled = false;
     }
   }
}

/*
 *cross browser function to transfer all rules from one
 * stylesheet fromSS to another toSS - can call clearSS()
 *   to empty a stylesheet before copying styles into it.
 *
 * pass titles (as strings) of each stylesheet to the function
 * different methods for IE and Firefox to add rules
 */

function transferRules(fromSSTitle, toSSTitle)
{
    var fromSS = getSheetByTitle(fromSSTitle);  // stylesheet to copy styles from
    var toSS = getSheetByTitle(toSSTitle);      // stylesheet to copy styles to

    for (var R = 0; R < fromSS[cssRules].length; R++)
    {
        if(document.all)
        {
            // IE
            toSS.addRule(fromSS[cssRules][R].selectorText,fromSS[cssRules][R].style.cssText,R);
        } else if (document.getElementById)
        {
            //FF
            //toSS.insertRule(fromSS[cssRules][R].cssText,R); // this does seem to transfer the rules - but they then don't get applied to elements

            //toSS[cssRules][R].style[property] = value;
            toSS[cssRules][R].style.cssText = fromSS[cssRules][R].style.cssText;  // this works

        }
    }

}

function getCSS(fromSSTitle)
{
    var fromSS = getSheetByTitle(fromSSTitle);
    var s = "";
    for (var R = 0; R < fromSS[cssRules].length; R++)
    {
        s += fromSS[cssRules][R].selectorText;
        s += " {\n";
        s += normalizeStylePropery(fromSS[cssRules][R].style.cssText.toLowerCase());
        s += "\n}\n";
    }
    return s;
}



/*
 * adds the rule specified by ruleText
 * to the style sheet with title ssTitle
 * normalizes FF and IE
 *
 *  RULE TEXT MUST BE PASSED BY CALLER WITHOUT {}
 * as it would normally be passed - with the selector separate - to the
 * IE function addRule
 */
function addCSSRule(selector, ruleText, ssTitle)
{
    var theSS = getSheetByTitle(ssTitle);
    
    if(document.all)
    {
        // IE
        theSS.addRule(selector,ruleText);
    } else if (document.getElementById)
    {
        //FF
        //theSS[cssRules][cssRules.length].style.cssText = selector+"{"+ruleText+"}";  // this works
        fullText = selector+"{"+ruleText+"}";
        theSS.insertRule(fullText, cssRules.length);
        //alert("rule: "+theSS[cssRules][cssRules.length].cssText);
        //theSS[cssRules][cssRules.length].cssText = selector+"{"+ruleText+"}";
    }
}



/*
 * Clears all styles from the stylesheet with title passed to function
 */
function clearSS(ssTitle)
{
    var theSS = getSheetByTitle(ssTitle);

    if(document.all)
    {
        // IE
        theSS.cssText = "";
        return;
    }

    // FF
    theSS.cssText = "";
    return;
    for (var R = 0; R < theSS[cssRules].length; R++)
    {
        //toSS.deleteRule(R);  this totally destroys the SS in FF
    }
}

function disableSS(ssTitle)
{
    var theSS = getSheetByTitle(ssTitle);
    theSS.disabled = true;
}

function enableSS(ssTitle)
{
    var theSS = getSheetByTitle(ssTitle);
    theSS.disabled = false;
}


/* normalizes the returned style property between IE and Firefox 
 * specifically firefox stores colors internally as rgb(number, number, number)
 * IE stores as HEX - this normalizes the FF format to HEX for consistent storage in
 * the DB - note this is regardless of how the designer writes the styles in the CSS
 */
function normalizeStylePropery(prop)
{
    var newProp = prop;
    var rgbRE = /rgb\((\d|,| )*\)/g;
    var m;
    while( (m = rgbRE.exec(prop)) != null)
    {
        newProp =  newProp.replace(m[0], ffRGBtoHex(m[0]) );
    }
    return newProp;
}

/**
 *  Takes a single string of form rgb(121, 244, 255) - how firefox returns
 *  color values from style sheets - and converts to #ffab6d format HEX
 */

function ffRGBtoHex(rgbString)
{
    //rgbString = "rgb(112, 155, 255)";
    var r = parseInt( rgbString.substring( rgbString.indexOf('(')+1,rgbString.indexOf(',',rgbString.indexOf('(')) ).trim() );
    var b = parseInt( rgbString.substring( rgbString.indexOf(',')+1, rgbString.lastIndexOf(',') ).trim() );
    var g = parseInt( rgbString.substring( rgbString.lastIndexOf(',')+1, rgbString.indexOf(')') ).trim() );
    //alert("r: "+r+" b: "+b+" g: "+g);
    var c = [r,b,g];
    var hexc = "#"+toHex(c);
    return hexc;
}



// debugging function to see all style selctor texts
function showSelectorTexts()
{
    var s = ""
    for (var S = 0; S < document.styleSheets.length; S++)
    {
        for (var R = 0; R < document.styleSheets[S][cssRules].length; R++) 
        {
            s += document.styleSheets[S][cssRules][R].selectorText+" , ";
        }
    }
    alert(s);
}


/*
 *
 *  TJ Common Library Functions - across pages
 *
 *  3/29/05 - updates to tj_getELEM in all files
 */

 function object2String(obj) {
    var val, output = "";
    if (obj) {
        output += "{";
        for (var i in obj) {
            val = obj[i];
            switch (typeof val) {
                case ("object"):
                    if (val[0]) {
                        output += i + ":" + array2String(val) + ",";
                    } else {
                        output += i + ":" + object2String(val) + ",";
                    }
                    break;
                case ("string"):
                    output += i + ":'" +(val) + "',";
                    output += i + ":'" +escape(val) + "',"; // causes problems with escape characters
                    break;
                default:
                    output += i + ":" + val + ",";
            }
        }
        output = output.substring(0, output.length-1) + "}";
    }
    return output;
}

function array2String(array) {
    var output = "";
    if (array) {
        output += "[";
        for (var i in array) {
            val = array[i];
            switch (typeof val) {
                case ("object"):
                    if (val[0]) {
                        output += array2String(val) + ",";
                    } else {
                        output += object2String(val) + ",";
                    }
                    break;
                case ("string"):
                    output += "'" + escape(val) + "',";
                    break;
                default:
                    output += val + ",";
            }
        }
        output = output.substring(0, output.length-1) + "]";
    }
    return output;
}


function string2Object(string) {
    if(string == "") return;
    eval("var result = " + string);
    return result;
}

function string2Array(string) {
    	if(string == "") return;
	eval("var result = " + string);
    	return result;
}


/*
 * utility function - returns the index value from a select drop
 * down which matches the string passed in.  Returns -1 if no
 * items in the drop down match the string
 *  select should be passed in as an object
 */
function getIndexMatchingValue(selectObj, item)
{
	for(var i=0; i<selectObj.options.length; i++)
	{
		if(selectObj.options[i].value == item) return i;
	}
	return -1; // no match
}

/*
 *  Returns the index of selected item in a Radio Button Group
 *  Pass in the Radio Button element as an object to the function
 */

function indexSelectedRadio(radioGroup)
{
	for(var i=0; i<radioGroup.length; i++)
	{
		if(radioGroup[i].checked) return i;
	}
	return -1;
}

/*
 *  Returns the value of selected item in a Radio Button Group
 *  Pass in the Radio Button element as an object to the function
 */

function valueSelectedRadio(radioGroup)
{
	var n = indexSelectedRadio(radioGroup);

	if(n != -1)
	{
		return radioGroup[n].value;
	} else {
		return "no item selected";
	}
}


/*
 * debug function - shows all the properties of an object
 */

function showObjProps(obj)
{
    var output = '';
    for (var i in obj)
    {
        output += i+ ' :: ';
    }
    alert(output);
}


/* cleans out bad escape sequences added for single
 * and double quotes in text input fields - created by c:out
 * 
 * turning off escapeXML in c:out does not solve problem
 * because you still can't asign to a string.
 */

function cleanQuotes(s)
{
	s = s.replace(/&#034;/g, '"');
	s = s.replace(/&#039;/g, "'");
	return s;
}

function cleanAndAmp(s)
{
	s = s.replace(/&amp;/g, '&');
	return s;
}

function getObjInnerText(obj)
{
    if (document.all) 
    { 
        // IE;
        return obj.innerText;
    } else
    {
        if (obj.text)
        {
            return obj.textContent;
        } else
        {
            return obj.innerText;
        }
    } 
}


function setObjInnerText(obj, txt)
{
    if (document.all) 
    { 
        // IE;
        obj.innerText = txt;
    } else
    {
        if (obj.text)
        {
            obj.textContent = txt;
        } else
        {
            obj.innerHTML = txt;
        }
    } 
}




/* use for err Display instead of alert in timer loops */

function errD(s)
{
	if ($("#errJSHolder") == null)
	{
		alert("no errJSHolder.  s is: "+s);
		return;
	}
	$("#errJSHolder").style.visibility = "visible";
	$("#errJS").innerHTML = s;
	return;
}

/* used to supress scrolling behavior in IE  */

function supressScroll()
{
	var pos = new Array();
	pos = getXYoff();
	myXoff = pos[0];
	myYoff = pos[1];
	//alert("got here myXoff: "+myXoff+" myYoff: "+myYoff);
	setTimeout('window.scrollTo(myXoff, myYoff)',100);
}

// code added to get scrolling offsets

function getXYoff() 
{ 
	var scrOfX = 0, scrOfY = 0; 
	if( typeof( window.pageYOffset ) == 'number' )
	{ 
		//Netscape compliant 
		scrOfY = window.pageYOffset; 
		scrOfX = window.pageXOffset; 
	} else if ( document.body && ( document.body.scrollLeft || document.body.scrollTop ) ) 
	{ 
		//DOM compliant
		 scrOfY = document.body.scrollTop;
		 scrOfX = document.body.scrollLeft; 
	} else if( document.documentElement && ( document.documentElement.scrollLeft || document.documentElement.scrollTop ) )
	{ 
		//IE6 standards compliant mode 
		scrOfY = document.documentElement.scrollTop; 
		scrOfX = document.documentElement.scrollLeft; 
	} 
	return [ scrOfX, scrOfY ]; 
}




/* Some General Array Functions */

function hasInArray(theArray, theItem)
{
	for(var i=0; i<theArray.length; i++)
	{
		if(theArray[i] == theItem) return true;
	}
	return false;
}


/* removed item at index position 'theIndex' in array 'theArray' 
    returns a new array with indexes shifted down one above
    the removed element 
*/
function removeItemAtIndex(theIndex, theArray)
{
	var r = new Array();
	var newindex = 0;
	//alert("got to removeItemAtIndex. index is:"+theIndex+" theArray[0]:"+theArray[0].ingredient+" theArray[1]:"+theArray[1].ingredient+" theArray[2]:"+theArray[2].ingredient );

	for(var i=0; i<theArray.length; i++)
	{
		//alert("got in to loop in remove item. newindex is: "+newindex);
		if (i == theIndex)
		{
			// ignore - don't copy to the new array
			// don't increment the new index
			//alert(" index matches: i is: "+i);
		} else {
			r[newindex] = theArray[i];
			newindex++;
		}
	}
	//alert("newArray. r[0]:"+r[0].ingredient+" r[1]:"+r[1].ingredient );	
	return r;
}


/* insert item 'theItem' at index position 'index' in array 'theArray' 
    returns a new array 
*/
function insertIntoArrayAtPosition(theItem, theArray, index)
{
	var r = new Array();
	r = theArray; // copy the array to r
	
	//alert("got to insertIntoArrayAtPostiong. index is: "+index+"  theArray.length is:"+theArray.length);
	
	// copy all items above 'index' to one higher position in array
	// starting from end (top) of array down to index to not destroy any items
	for(var i=theArray.length; i>=index; i--)
	{
		r[i] = r[i-1];
	}
	// next set r[index] to the new item
	r[index] = theItem;
	
	return r;
	
}

// returens index of theValue in theArray or -1 if value not in Array
function indexInArray(theArray, theValue)
{
	var arLength = theArray.length;
	for(var i=0; i<arLength; i++)
	{
		if (theArray[i] == theValue)  return i;
	}
	return -1;
} 


/*
  **  Remove all occurrences of a token in a string
  **    s  string to be processed
  **    t  token to be removed
  **  returns new string
  */ 
function removeTokenInString(s, t) {

  	i = s.indexOf(t);
  	r = "";
  	if (i == -1) return s;
  	r += s.substring(0,i) + removeTokenInString(s.substring(i + t.length), t);
  	return r;
}



function nthIndexOf(theString, token, n)
{
	var pos = 0;
	var newPos = 0;
	for(var i=0; i<n; i++)
	{
		newPos = theString.indexOf(token, pos+1)
		if(newPos == -1)
		{
			// did not find token in pass = i
			return -1;
		} else {
			//alert("got in loop once pos: "+pos+" newPos: "+newPos);
			pos = newPos;
		}
	}
	//alert("got here returning pos: "+pos);
	return pos;
}



/* returns a comma separated string of the array items from theArray */
function makeCSLFromArray(theArray)
{
	var csl = "";
	
	for(var i=0; i<theArray.length; i++)
	{
		csl += theArray[i]+",";
	}
	csl = csl.substring(0,csl.length-1);
	return csl;
}

function makeArrayFromCSL(csl)
{
	var returnArray = new Array();
	if(csl == "") return returnArray;
	
	//remove a trailing comma if it is last character
	if (csl.charAt(csl.length-1) == ",") csl = csl.substring( 0,csl.length-1);
	//alert("got here csl is "+csl+" index of , is "+csl.indexOf(",") );
	
	while(csl.indexOf(",") != -1)
	{
		returnArray[returnArray.length] = csl.substring( 0,csl.indexOf(",") );
		csl = csl.substring( csl.indexOf(",")+1, csl.length );
		//alert("got here csl is "+csl+" index of , is "+csl.indexOf(",")+"reutrnArray.length is "+returnArray.length );
	}
	//pick up the last token - while loop wont catch it
	// or if there was no comma at all?
	returnArray[returnArray.length] = csl;
	
	return returnArray;
}

/****************** end general array functions ***************/

//-->