//
// useful_stuff.js
//
// All sorts of useful javascript functions.
//
// Feel free to use as you please, but please retain this
// copyright notice.
//
// 2005-02-10 MGrill Version 1.00
//
// see http://www.dcs.lancs.ac.uk/~grill/mgbox/
//

// an exception object, 
// see http://www.webreference.com/js/column38/usererror.html
function createException(msgNum, msgText) {
  this.messageNumber = msgNum;
  this.messageText = msgText;
}


// show the <span> element with the given text id
// hide the <span> element with id <asabove>_unfold
// Useful for "more >>" info texts.
// 2005-01-28 MGrill
function unfoldinfotext(id) {
  if(document.getElementById) {
    document.getElementById(id).style.display = "";
    document.getElementById(id+'_unfold').style.display = "none";
  }
}

// inverse function to "unfoldinfotext()" (see above)
function foldinfotext(id) {
  if(document.getElementById) {
    document.getElementById(id).style.display = "none";
    document.getElementById(id+'_unfold').style.display = "";
  }
}

// make an element invisible
function hideElement(id) {
  getElem("id",id).style.display="none";
}

// return the right n characters of string s
function xxxright(n) {
  if(n<this.length) {
    return this.substring(this.length-n);
  } else {
    return this;
  }
}
String.prototype.right = xxxright;

// return the left n characters of string s
function xxxleft(n) {
  if(n<this.length) {
    return this.substring(0,n);
  } else {
    return this;
  }
}
String.prototype.left = xxxleft;

// remove any trailing digits if present
function xxxremoveTrailingDigitsIfPresent() {
  var s=this;
  while( isNum(s.charAt(s.length-1)) ) {
    s = s.substr(0,s.length-1);
  }
  return s;
}
String.prototype.removeTrailingDigitsIfPresent = xxxremoveTrailingDigitsIfPresent;

// remove superfluous spaces
// "__Hargreaves,__John_K_" will become
// "Hargreaves,John_K"
function xxxclean() {
  var s=this;
  
  // delete leading, then trailing, white-space
  s = s.replace(/^\s+/, '');
  s = s.replace(/\s+$/, '');
  
  // replace multiple whitespaces with one space character
  s = s.replace(/\s+/g,' ');
  
  // replace ', ' with just ','
  s = s.replace(/, /g,',');
  
  // replace ' ,' with just ','
  s = s.replace(/ ,/g,',');
 
  return s;
}
String.prototype.clean = xxxclean;

// turn 1 into "1st", 2 into "2nd", etc.
function nthString(nr) {
  if(nr<10 || nr>20) {
    if( (nr%10)==1 ) {
      return nr+"st";
    }
    if( (nr%10)==2 ) {
      return nr+"nd";
    }
    if( (nr%10)==3 ) {
      return nr+"rd";
    }
  }
  return nr+"th";
}

// replace strings in ids of given DOM node and all subnodes
// also replace strings in attribute.value[] of given DOM node and all subnodes
function deepNodeIdReplace( startingNode, from_regexp, to ) {
  // replace this node's id (if it exists)
  if(startingNode.id!=undefined) {
    startingNode.id = startingNode.id.replace(from_regexp,to);
  }
  //iterate through attributes
  //alert(startingNode.attributes[1].value);
  if(startingNode.attributes) {
    for( var i=0; i<startingNode.attributes.length; i++ ) {
      if(typeof (startingNode.attributes[i].nodeValue) == 'string') {
        //alert(startingNode.attributes[i].value);
        var s=startingNode.attributes[i].nodeValue;
        if(s=='null') continue;
        if(s=='') continue;
        //if(s.length<6) continue;
        //alert(typeof s);
        startingNode.attributes[i].nodeValue = 
            s.replace(from_regexp,to);
      }
    }
  }
  //alert("hi");
  //iterate through all children
  for(var i=0; i<startingNode.childNodes.length; i++) {
    deepNodeIdReplace(startingNode.childNodes[i], from_regexp, to);
  }
}

// For the following two functions, see
// http://www.quirksmode.org/js/findpos.html

function findPosX(obj)
{
	var curleft = 0;
	if (obj.offsetParent)
	{
		while (obj.offsetParent)
		{
			curleft += obj.offsetLeft
			obj = obj.offsetParent;
		}
	}
	else if (obj.x)
		curleft += obj.x;
	return curleft;
}

function findPosY(obj)
{
	var curtop = 0;
	if (obj.offsetParent)
	{
		while (obj.offsetParent)
		{
			curtop += obj.offsetTop
			obj = obj.offsetParent;
		}
	}
	else if (obj.y)
		curtop += obj.y;
	return curtop;
}

// ====================================================================
//       URLEncode and URLDecode functions
//
// modified to take parameter by MGrill 2005-01-31
//
// Copyright Albion Research Ltd. 2002
// http://www.albionresearch.com/
//
// You may copy these functions providing that 
// (a) you leave this copyright notice intact, and 
// (b) if you use these functions on a publicly accessible
//     web site you include a credit somewhere on the web site 
//     with a link back to http://www.albionresarch.com/
//
// If you find or fix any bugs, please let us know at albionresearch.com
//
// SpecialThanks to Neelesh Thakur for being the first to
// report a bug in URLDecode() - now fixed 2003-02-19.
// ====================================================================
function URLEncode(plaintext)
{
	// The Javascript escape and unescape functions do not correspond
	// with what browsers actually do...
	var SAFECHARS = "0123456789" +					// Numeric
					"ABCDEFGHIJKLMNOPQRSTUVWXYZ" +	// Alphabetic
					"abcdefghijklmnopqrstuvwxyz" +
					"-_.!~*'()";					// RFC2396 Mark characters
	var HEX = "0123456789ABCDEF";

	var encoded = "";
	for (var i = 0; i < plaintext.length; i++ ) {
		var ch = plaintext.charAt(i);
	    if (ch == " ") {
		    encoded += "+";				// x-www-urlencoded, rather than %20
		} else if (SAFECHARS.indexOf(ch) != -1) {
		    encoded += ch;
		} else {
		    var charCode = ch.charCodeAt(0);
			if (charCode > 255) {
			    alert( "Unicode Character '" 
                        + ch 
                        + "' cannot be encoded using standard URL encoding.\n" +
				          "(URL encoding only supports 8-bit characters.)\n" +
						  "A space (+) will be substituted." );
				encoded += "+";
			} else {
				encoded += "%";
				encoded += HEX.charAt((charCode >> 4) & 0xF);
				encoded += HEX.charAt(charCode & 0xF);
			}
		}
	} // for

	return encoded;
};

function URLDecode(encoded)
{
   // Replace + with ' '
   // Replace %xx with equivalent character
   // Put [ERROR] in output if %xx is invalid.
   var HEXCHARS = "0123456789ABCDEFabcdef"; 
   var plaintext = "";
   var i = 0;
   while (i < encoded.length) {
       var ch = encoded.charAt(i);
	   if (ch == "+") {
	       plaintext += " ";
		   i++;
	   } else if (ch == "%") {
			if (i < (encoded.length-2) 
					&& HEXCHARS.indexOf(encoded.charAt(i+1)) != -1 
					&& HEXCHARS.indexOf(encoded.charAt(i+2)) != -1 ) {
				plaintext += unescape( encoded.substr(i,3) );
				i += 3;
			} else {
				alert( 'Bad escape combination near ...' + encoded.substr(i) );
				plaintext += "%[ERROR]";
				i++;
			}
		} else {
		   plaintext += ch;
		   i++;
		}
	} // while
   return plaintext;
};

// browser-independent way of requesting a XML HTTP Request object
// adapted from http://jibbering.com/2002/4/httprequest.html
// 2005-01-27 MGrill
function createXMLHttpRequest() {
  var xmlhttp=false;
  /*@cc_on @*/
  /*@if (@_jscript_version >= 5)
  // JScript gives us Conditional compilation, we can cope with old IE versions.
  // and security blocked creation of the objects.
  try {
    xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
  } catch (e) {
    try {
      xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
    } catch (E) {
      xmlhttp = false;
    }
  }
  @end @*/
  if (!xmlhttp && typeof XMLHttpRequest!='undefined') {
    xmlhttp = new XMLHttpRequest();
  }
  return xmlhttp;
}

// from http://javascript.about.com/library/blvalid02.htm
var numb = '0123456789';
var lwr = 'abcdefghijklmnopqrstuvwxyz';
var upr = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';

function isValid(parm,val) {
  if (parm == "") return true;
  for (i=0; i<parm.length; i++) {
    if (val.indexOf(parm.charAt(i),0) == -1) return false;
  }
  return true;
}
 
function isNum(parm) {return isValid(parm,numb);}
function isLower(parm) {return isValid(parm,lwr);}
function isUpper(parm) {return isValid(parm,upr);}
function isAlpha(parm) {return isValid(parm,lwr+upr);}
function isAlphanum(parm) {return isValid(parm,lwr+upr+numb);}

