/********************************/
//	Dynamic Dependant Project
/********************************/

// first, declare the two namespaces if they do not already exist

var ddp;
if(!ddp) ddp = {};
ddp.f = {};

/********************************/
//	DDP
/********************************/

	/*
	augment: function (oSelf) 
	{
	  if (oSelf == null) {
	    oSelf = {};
	  }
	  for (var i = 1; i < arguments.length; i++) {
	    var o = arguments[i];
	    if (typeof(o) != 'undefined' && o != null) {
	      for (var j in o) {
	        oSelf[j] = o[j];
	      }
	    }
	  }
	  return oSelf;
	}
	*/
	

	
(function() {


	//Replaces: document.getElementById() 
	//Takes strings and objects
	//var elements = ddp.f.$('id',objname);
	function $() 
	{
	  var elements = [];
	
	  for(var i=0, l=arguments.length; i<l; i++)
	    elements.push(isString(arguments[i]) ? document.getElementById(arguments[i]) : arguments[i]);

	  return (elements.length==1) ? elements[0] : elements;
	}
	
	
  /***************************************************************/	
	function addLoadEvent(fnFuntionToAdd){
		addEvent(window, 'load', fnFuntionToAdd);
	}
  
  /***************************************************************/
  //makeRealArray 
  //takes an object with 'length' property and returns an actual array
  //(useful for 'arguments' and objects returned from getElementsByTagName(), etc..)
  function makeRealArray(objObject){
    //return Array.prototype.slice.call(objObject, 0); //can't get this to work in ie
    var arReturn = [];
    for(var i=0, l=objObject.length; i<l; i++)
      arReturn[i]=objObject[i];
    return arReturn;
  }


  /***************************************************************/
  //isArray 
  //tests for arrays
  function isArray(varTest){
    if(varTest === null)
      return false;
    if(typeof varTest == 'object' && typeof varTest.constructor == 'function')
      return (varTest.constructor.toString().match(/array/i) != null);

    return false;
  }
    
  
  /***************************************************************/
  //isString 
  //tests for strings and string objects
  function isString(varTest){
    if(varTest === null)
      return false;
    if(typeof varTest == 'string')
      return true;
    if(typeof varTest == 'object' && typeof varTest.constructor == 'function')
      return (varTest.constructor.toString().match(/string/i) != null);

    return false;
  }
  
  
  /***************************************************************/
	if(!Array.prototype.forEach) //Needed for IE
	{
		Array.prototype.forEach = function(fn, thisObj) 
		{
		    var scope = thisObj || window;
		    for ( var i=0, j=this.length; i < j; ++i ) 
			{
		        fn.call(scope, this[i], i, this);
		    }
		};
	}
	if(!Array.prototype.filter) //Needed for IE
	{
		Array.prototype.filter = function(fn, thisObj) 
		{
		    var scope = thisObj || window;
		    var a = [];
		    for ( var i=0, j=this.length; i < j; ++i ) 
			{
		        if ( !fn.call(scope, this[i], i, this) ) 
				{
		            continue;
		        }
		        a.push(this[i]);
		    }
		    return a;
		};
	}
/***************************************************************/
 
	function obsEvent() 
	{
		this.fns = [];
	}
	obsEvent.prototype = 
	{
		subscribe : function(fn) 
		{
			this.fns.push(fn);
		},
		unsubscribe : function(fn) 
		{
			this.fns = this.fns.filter(
				function(el) 
				{
					if ( el !== fn ) 
					{
						return el;
					}
				}
			);
		},
		fire : function(o, thisObj) 
		{
			var scope = thisObj || window;
			this.fns.forEach(
				function(el) 
				{
					el.call(scope, o);
				}
				
			);
		}
	};


/***************************************************************/

	function mousePosition(objEvent){
    //make sure we have the event object
    objEvent = objEvent || window.event;
		try{
    	if(objEvent.pageX || objEvent.pageY){
    		return {x:objEvent.pageX, y:objEvent.pageY};
    	}
    	return {
    		x:objEvent.clientX + document.body.scrollLeft - document.body.clientLeft,
    		y:objEvent.clientY + document.body.scrollTop  - document.body.clientTop
    	};
		}
		catch(e){
			//in IE6 if this method is executed before the page fully loads, it throws an error...
			return {x:0,y:0};
		}
	}

/***************************************************************/	
	
//replace anything other than a numerical digit with nothing	
function removeAlpha(torem) 
{
	return result = torem.replace(/\D/g,''); 	
}

/***************************************************************/	

//replace anything other than an ASCII word character with nothing
function removeNonAsciiWord(torem) 
{
	return result = torem.replace(/\W/g,''); 	
}
 
/***************************************************************/	 


//verify a valid phone number 
function checkValidPhoneNumber(phoneNo) 
{
 var phoneRE = /^(\(?[0-9]{3}\)?)?\-?[0-9]{3}\-?[0-9]{4}$/;
 if (phoneNo.match(phoneRE)) 
 {
   return true;
 } 
 else 
 {
   return false;
 }
}

/***************************************************************/

//verify a valid email address where the address is not an IP address
function checkValidEmailAddress(emailAddress){
 var emailRE = /^[A-Za-z0-9_\-\.]+@(([A-Za-z0-9\-])+\.)+([A-Za-z\-])+$/;
 return emailAddress.match(emailRE) ? true : false;
}

/***************************************************************/

function getBrowserGeometry(){
	var windowSizeWidth = 0;
	var windowSizeHeight = 0;
	var horizontalScroll = 0;
	var verticalScroll = 0;
	var documentWidth = 0;
	var documentHeight = 0;
	
	if( typeof( window.innerWidth ) == 'number' ){
		//Non-IE
		windowSizeWidth = window.innerWidth;
		windowSizeHeight = window.innerHeight;
		horizontalScroll = window.pageXOffset;
		verticalScroll = window.pageYOffset;	
  }
	else if( document.documentElement && ( document.documentElement.clientWidth || document.documentElement.clientHeight ) ){
    //IE 6+ in 'standards compliant mode'
    windowSizeWidth = document.documentElement.clientWidth;
    windowSizeHeight = document.documentElement.clientHeight;
    horizontalScroll = document.documentElement.scrollLeft;
    verticalScroll = document.documentElement.scrollTop;
  }
  else if( document.body && ( document.body.clientWidth || document.body.clientHeight ) ){
    //IE 4 compatible
    windowSizeWidth = document.body.clientWidth;
    windowSizeHeight = document.body.clientHeight;
    horizontalScroll = document.body.scrollLeft;
    verticalScroll = document.body.scrollTop;
	}
	
	if( window.innerHeight && window.scrollMaxY ) // Firefox 
	{
		documentWidth = window.innerWidth + window.scrollMaxX;
		documentHeight = window.innerHeight + window.scrollMaxY;
	}
	else if( document.body && document.body.scrollHeight > document.body.offsetHeight ) // all but Explorer Mac
	{
		documentWidth = document.body.scrollWidth;
		documentHeight = document.body.scrollHeight;
	}
	else if( document.body )// works in Explorer 6 Strict, Mozilla (not FF) and Safari
	{ 
		documentWidth = document.body.offsetWidth + document.body.offsetLeft; 
		documentHeight = document.body.offsetHeight + document.body.offsetTop; 
	}
	
	windowSizeWidth = parseInt(windowSizeWidth);
	windowSizeHeight = parseInt(windowSizeHeight);
	horizontalScroll = parseInt(horizontalScroll);
	verticalScroll = parseInt(verticalScroll);
	documentWidth = parseInt(documentWidth);
	documentHeight = parseInt(documentHeight);
	
	if(isNaN(windowSizeWidth)) windowSizeWidth = null;
	if(isNaN(windowSizeHeight)) windowSizeHeight = null;
	if(isNaN(horizontalScroll)) horizontalScroll = null;
	if(isNaN(verticalScroll)) verticalScroll = null;
	if(isNaN(documentWidth)) documentWidth = null;
	if(isNaN(documentHeight)) documentHeight = null;
	
	return {viewportWidth:windowSizeWidth,viewportHeight:windowSizeHeight,horizontalScroll:horizontalScroll,verticalScroll:verticalScroll,documentWidth:documentWidth,documentHeight:documentHeight};
}


/***************************************************************/
function returnMaxZindex()
{
	var allElems = document.getElementsByTagName ? 	document.getElementsByTagName("*") : document.all; // or test for that too
	var maxZIndex = 0;
	for(var i=0, l=allElems.length;i<l;i++) 
	{
		var elem = allElems[i];
		var cStyle = null;
		if (elem.currentStyle) {cStyle = elem.currentStyle;}
		else if (document.defaultView && document.defaultView.getComputedStyle)
		{
			cStyle = document.defaultView.getComputedStyle(elem,"");
		}
		var sNum;
		if (cStyle) 
		{
			sNum = Number(cStyle.zIndex);
		} 
		else 
		{
			sNum = Number(elem.style.zIndex);
		}
		if (!isNaN(sNum)) 
		{
			maxZIndex = Math.max(maxZIndex,sNum);
		}
	
	}
	return maxZIndex;
}


//detects what DOCTYPE this document uses. returns an object.
//accessable properties are:
//detectDoctype.xhtml - XHTML, HTML
//detectDoctype.version - 1.1, 4.0 
//detectDoctype.importance - Strict, Transitional
function detectDoctype(){
  var re=/\s+(X?HTML)\s+([\d\.]+)\s*([^\/]+)*\//gi;
  var res=false;
  if(typeof document.namespaces != "undefined")
    res=document.all[0].nodeType==8 ? re.test(document.all[0].nodeValue) : false;
  else
    res=document.doctype != null ? re.test(document.doctype.publicId) : false;
  if(res){
    res=new Object();
    res['xhtml']=RegExp.$1.toUpperCase();
    res['version']=RegExp.$2.toUpperCase();
    res['importance']=RegExp.$3.toUpperCase();
    return res;
  }else{
    return null;
  }
}


//browser detection class
//accessable properties are:
//BrowserDetect.browser - Explorer, Mozilla, Chrome, etc.
//BrowserDetect.version - 1, 2, 3, 4, etc.
//BrowserDetect.OS - Windows, Linux, Mac, iPhone, etc.
function BrowserDetect(){
	this.init = function () {
		this.browser = this.searchString(this.dataBrowser) || "An unknown browser";
		this.version = this.searchVersion(navigator.userAgent)
			|| this.searchVersion(navigator.appVersion)
			|| "an unknown version";
		this.OS = this.searchString(this.dataOS) || "an unknown OS";
	};
	
	this.searchString = function (data){
		for(var i=0, l=data.length;i<l;i++){
			var dataString = data[i].string;
			var dataProp = data[i].prop;
			this.versionSearchString = data[i].versionSearch || data[i].identity;
			if(dataString){
				if(dataString.indexOf(data[i].subString) != -1)
					return data[i].identity;
			}
			else if(dataProp)
				return data[i].identity;
		}
	};
	
	this.searchVersion = function(dataString){
		var index = dataString.indexOf(this.versionSearchString);
		if(index == -1) return;
		return parseFloat(dataString.substring(index+this.versionSearchString.length+1));
	};
	
	this.dataBrowser = [
		{
			string: navigator.userAgent,
			subString: "Chrome",
			identity: "Chrome"
		},
		{ 	string: navigator.userAgent,
			subString: "OmniWeb",
			versionSearch: "OmniWeb/",
			identity: "OmniWeb"
		},
		{
			string: navigator.vendor,
			subString: "Apple",
			identity: "Safari",
			versionSearch: "Version"
		},
		{
			prop: window.opera,
			identity: "Opera"
		},
		{
			string: navigator.vendor,
			subString: "iCab",
			identity: "iCab"
		},
		{
			string: navigator.vendor,
			subString: "KDE",
			identity: "Konqueror"
		},
		{
			string: navigator.userAgent,
			subString: "Firefox",
			identity: "Firefox"
		},
		{
			string: navigator.vendor,
			subString: "Camino",
			identity: "Camino"
		},
		{		// for newer Netscapes (6+)
			string: navigator.userAgent,
			subString: "Netscape",
			identity: "Netscape"
		},
		{
			string: navigator.userAgent,
			subString: "MSIE",
			identity: "Explorer",
			versionSearch: "MSIE"
		},
		{
			string: navigator.userAgent,
			subString: "Gecko",
			identity: "Mozilla",
			versionSearch: "rv"
		},
		{ 		// for older Netscapes (4-)
			string: navigator.userAgent,
			subString: "Mozilla",
			identity: "Netscape",
			versionSearch: "Mozilla"
		}
	];
	
	this.dataOS = [
		{
			string: navigator.platform,
			subString: "Win",
			identity: "Windows"
		},
		{
			string: navigator.platform,
			subString: "Mac",
			identity: "Mac"
		},
		{
			string: navigator.userAgent,
			subString: "iPhone",
			identity: "iPhone/iPod"
		},
		{
			string: navigator.platform,
			subString: "Linux",
			identity: "Linux"
		}
	];

	this.init();
}




/***************************************************************/
function isIE()
{
	return new BrowserDetect().browser == 'Explorer';
	/*
	check for Opera first, since some versions of Opera defaulted to pretending to be IE
  var isOpera = (navigator.userAgent.indexOf('Opera') != -1);
  return (!isOpera && navigator.userAgent.indexOf('MSIE') != -1)
	*/
}


/***************************************************************/
//used in the three event methods (add, remove, and fire) to format the event type string
//removes "on" from the start of the event string and changes it to lower case
function _toLowerWithNoOn(strEventType){
  if(!isString(strEventType))
    return null;
  var strReturn = strEventType.toLowerCase(); //make sure the event type is in lower case
  if(strReturn.substr(0,2) == 'on')				    //and if it has 'on' at the beginning, 
  	strReturn = strReturn.substr(2);		      //take it off.
  return strReturn;
}


/***************************************************************/
function addEvent( elEventTarget, strEventType, fnEventListener ){
  //check that the arguments were passed with the proper types
  if(typeof elEventTarget != 'object' || elEventTarget === null)
    throw new Error('ddp.f.addEvent: Parameter "elEventTarget" was not an object');
  if(!isString(strEventType))
    throw new Error('ddp.f.addEvent: Parameter "strEventType" was not a string');
  if(typeof fnEventListener != 'function')
    throw new Error('ddp.f.addEvent: Parameter "fnEventListener" was not a function');
  //make sure the event type is in lower case and if it has 'on' at the beginning, take it off.
  strEventType = _toLowerWithNoOn(strEventType);

  //w3c standard browsers
	if(elEventTarget.addEventListener)
    //add the event listener. specify false to use bubbling (to mirror IE's limitation to only bubble)
		return elEventTarget.addEventListener( strEventType, fnEventListener, false );
  // Internet Explorer (use old school approach for resize and scroll)
	else if(elEventTarget.attachEvent && strEventType!='resize' && strEventType!='scroll'){
    //grab the array stored in the element (if it exists) 
    var arListeners = elEventTarget['arEventListeners_' + strEventType];
    
    //the function that will be called when the actual event is fired.
		var fireEvents = function(e){
      //make sure the event object has been passed properly
			var objEvent = (typeof e == 'object') ? e : window.event;
      //cycle through the listeners in the order they were added 
      for(var i=0, l=arListeners.length; i<l; i++){
        //execute the listeners with "call" so that their "this" will be the element
        //and if any return false or the event.returnValue property is set to false, then
      	if(arListeners[i].call(elEventTarget, objEvent) == false || objEvent.returnValue == false)
					return; //cancel the execution of the rest of the listeners (but don't return false or IE will cancel the default action)
      }
      return true;
    }
    
		if(typeof arListeners != 'object'){	//if the array of listeners is not already created,
      //create a new array within the target element
			arListeners = elEventTarget['arEventListeners_' + strEventType] = new Array();	
      //and attach the handler that fires all the events of this type 
      elEventTarget.attachEvent('on' + strEventType, fireEvents); 
      //add a listener on window unload event that removes fireEvents() and empties the array of added listeners (older versions of IE have issues with memory leaks)  
      window.attachEvent('onunload', function(){ elEventTarget['arEventListeners_' + strEventType] = null; elEventTarget.detachEvent('on' + strEventType, fireEvents); });
    }
    //add the new function to the array of functions to be fired 
    arListeners.push(fnEventListener);
    return true;
	}
  else //if all else fails, use the old school approach
    return AERM_addListener(elEventTarget, strEventType, fnEventListener);
}



/***************************************************************/
function removeEvent(elEventTarget, strEventType, fnEventListener){
  //check that the arguments were passed with the proper types
  if(typeof elEventTarget != 'object' || elEventTarget === null)
    throw new Error('ddp.f.removeEvent: Parameter "elEventTarget" was not an object');
  if(!isString(strEventType))
    throw new Error('ddp.f.removeEvent: Parameter "strEventType" was not a string');
  if(typeof fnEventListener != 'function')
    throw new Error('ddp.f.removeEvent: Parameter "fnEventListener" was not a function');
  
  //make sure the event type is in lower case and if it has 'on' at the beginning, take it off.
  strEventType = _toLowerWithNoOn(strEventType);
    
	//w3c compliant browsers
	if(elEventTarget.removeEventListener)
		elEventTarget.removeEventListener( strEventType, fnEventListener, false );
  // Internet Explorer (but use old school approach for resize and scroll)
	else if(elEventTarget.detachEvent && strEventType!='resize' && strEventType!='scroll'){
    //grab the array stored in the element (if it exists)
		var arListeners = elEventTarget['arEventListeners_' + strEventType];
		
		if(typeof arListeners == 'object'){
  		for(var i=0, l=arListeners.length; i<l; i++){
  			if(arListeners[i] == fnEventListener){ //if the listener is in the array
					arListeners.splice(i,1); //splice the listener out
					return true;	//return true on success
				}
  		}
		}
    return false;
	}
  else //if all else fails, use the old school approach
    return AERM_removeListener(elEventTarget, strEventType, fnEventListener);
}



/***************************************************************/
function _getEventModule(strEventType){
  var arEventModule = ['HTMLEvents', 'UIEvents', 'MouseEvents', 'MutationEvents'];
  var objEventTypes = {
    //HTMLEvents
    'abort': 0,
    'blur': 0,
    'change': 0,
    'error': 0,
    'focus': 0,
    'load': 0,
    'reset': 0,
    'resize': 0,
    'scroll': 0,
    'select': 0,
    'submit': 0,
    'unload': 0,
    
    //UIEvents
    'DOMActivate': 1,
    'DOMFocusIn': 1,
    'DOMFocusOut': 1,
    'keydown': 1,
    'keypress': 1,
    'keyup': 1,
    
    //MouseEvents
    'click': 2,
    'dblclick': 2,
    'mousedown': 2,
    'mousemove': 2,
    'mouseout': 2,
    'mouseover': 2,
    'mouseup': 2,
    
    //MutationEvents
    'DOMAttrModified': 3,
    'DOMNodeInserted': 3,
    'DOMNodeRemoved': 3,
    'DOMCharacterDataModified': 3,
    'DOMNodeInsertedIntoDocument': 3,
    'DOMNodeRemovedFromDocument': 3,
    'DOMSubtreeModified': 3
  };
  
  if(objEventTypes[strEventType])
    return arEventModule[objEventTypes[strEventType]];
  else
    return arEventModule[0];
}



/***************************************************************/
function fireEvent(elEventTarget, strEventType, objEventProperties){
  //check that the arguments were passed with the proper types
  if(typeof elEventTarget != 'object' || elEventTarget === null)
    throw new Error('ddp.f.fireEvent: Parameter "elEventTarget" was not an object');
  if(!isString(strEventType))
    throw new Error('ddp.f.fireEvent: Parameter "strEventType" was not a string');
  
  //make sure the event type is in lower case and if it has 'on' at the beginning, take it off.
  strEventType = _toLowerWithNoOn(strEventType);
  
  //will hold our new event object
  var objEvent = null;
  //if the objEventProperties object was passed and contains a "cancelable" property which is false, then be false, otherwise true. 
  var blnCancelable = !(objEventProperties && objEventProperties.cancelable===false);
  
  //IE
  if(document.createEventObject){
    objEvent = document.createEventObject();  //create an event object
    objEvent.type = strEventType; //set the proper event type
    objEvent.cancelable = blnCancelable; //set the cancelable property of the event object
  }
  //w3c standard browsers
  else{
    objEvent = document.createEvent(_getEventModule(strEventType)); //create an event object using the proper event module (for FF anyway..)
    objEvent.initEvent(strEventType, true, blnCancelable); // areguments are type, bubbling, cancelable respectively
  }
  
  //if the event object was created successfuly
  if(objEvent){
    //if there was an object passed with properties that should be set on the event object
    if(typeof objEventProperties == 'object'){
      //iterate through the obejct's properties (no particular order)
      for(var key in objEventProperties){
        if(key != 'type' && key != 'cancelable')
          objEvent[key] = objEventProperties[key]; //set the event object's property from the passed object's
      }
    }
    
    //now go and fire the event with our new event object
    //for IE
    if(elEventTarget.fireEvent)
      return elEventTarget.fireEvent('on' + strEventType, objEvent) //fire the event
    //w3c compliant browsers
    else if(elEventTarget.dispatchEvent)
      return !elEventTarget.dispatchEvent(objEvent);  //fire the event
    //if elEventTarget isn't a DOM element (or the browser has a wierd event model implementation)
    else
      return AERM_fireListener(elEventTarget, strEventType, objEvent);  //fire the event using the AERM
  }

  //return false to indicate 'failure to fire'
  return false;
}


/***************************************************************/
//cancelEvent
//cancels bubbling and propagation of an event
//----Arguments----
//objEvent: object  -the event object to be stopped
//cancelBubble is supported by IE - this will kill the bubbling process.
function cancelEvent(objEvent){
  objEvent.cancelBubble = true;
  objEvent.returnValue = false;
  //stopPropagation works only in Firefox.
  if(objEvent.stopPropagation){
  	objEvent.stopPropagation();
  	objEvent.preventDefault();
  }
  return false;
};



/***************************************************************/
//getEventTarget
//returns the element that fired the event
//(cross-browser compatible) 
function getEventTarget(objEvent){
	var elTarget = null;
  
  if(objEvent && objEvent.srcElement)
    elTarget = objEvent.srcElement
  else if(objEvent && objEvent.target)
    elTarget = objEvent.target;
    
  if(elTarget && elTarget.nodeType == 3 && elTarget.parentNode) //safari bug
    elTarget = elTarget.parentNode;

	return elTarget;
}


/***************************************************************/
//getEventKey
//tries to return the character code of the key that was pressed to fire the event (cross-browser compatible)
//VERY UNRELIABLE! avoid if at all possible!
//if you have to, only use on 'onkeypress' event (the order in which
//the properties are checked _should_ result in proper char codes)
function getEventKey(objEvent){
  if(objEvent.charCode)
    return objEvent.charCode;
  else if(objEvent.which)
    return objEvent.which;
  else if(objEvent.keyCode)
    return objEvent.keyCode;
  return false;
}


/***************************************************************/
//Alternate Event Registration Model - Add an event listener
//HAS NOT BEEN EXPORTED TO DDP NAMESPACE
function AERM_addListener(elEventTarget, strEventType, fnEventListener){
	//make sure all the arguments are of the proper type
	if(typeof elEventTarget == 'object' && elEventTarget !== null && isString(strEventType) && typeof fnEventListener == 'function'){
		
    //make sure the event type is in lower case and if it has 'on' at the beginning, take it off.
    strEventType = _toLowerWithNoOn(strEventType);

    var arListeners = elEventTarget['AERM_arEventListeners_' + strEventType];
    
		if(typeof arListeners != 'object')	//if the array of listeners is not already created,
			arListeners = elEventTarget['AERM_arEventListeners_' + strEventType] = new Array();	//create a new array
      
    //the function that will be called when the actual event is fired.
		var fireEvents = function(objEvent){
			if(typeof objEvent == 'undefined' && event)
				objEvent = event;
      for(var i=0, l=arListeners.length; i<l; i++){
      	if(arListeners[i].call(elEventTarget, objEvent) === false)	//if any of the listeners return false then
					return false;												                    //cancel the execution of the rest of the listeners
      }
      return true;
    }
    
		if(typeof elEventTarget['on' + strEventType] != 'function')
			elEventTarget['on' + strEventType] = fireEvents;

		//compare the string value of the methods because every "fireEvents" method exists in it's own namespace
		else if(elEventTarget['on' + strEventType].toString() != fireEvents.toString()){
			fnOldStyleFunction = elEventTarget['on' + strEventType];
			var blnAlreadyInArray = false;
  		for(var i=0, l=arListeners.length; i<l; i++){		//look throught the listeners already attached 
  			if(arListeners[i].toString() == fnOldStyleFunction.toString())	//and if the old style one we're about to add is already added,
  				blnAlreadyInArray = true;								//don't add it again.
  		}
			if(!blnAlreadyInArray)
  			arListeners[arListeners.length] = fnOldStyleFunction;
  		elEventTarget['on' + strEventType] = fireEvents;
		}
		
		for(var i=0, l=arListeners.length; i<l; i++){	//look throught the listeners already attached 
			if(arListeners[i] === fnEventListener)	//and if the one we're about to add is already added,
				return false;													//don't add it again.
		}
		
		arListeners[arListeners.length] = fnEventListener; //add the new listener to the array.
		return true;	//return true on success
	}
	
	return false;	//return false on failure
}


/***************************************************************/
//Alternate Event Registration Model - Remove an event listener
//HAS NOT BEEN EXPORTED TO DDP NAMESPACE 
function AERM_removeListener(elEventTarget, strEventType, fnEventListener){
	//make sure all the argumants are of the proper type
	if(typeof elEventTarget == 'object' && elEventTarget !== null && isString(strEventType) && typeof fnEventListener == 'function'){
		
    //make sure the event type is in lower case and if it has 'on' at the beginning, take it off.
    strEventType = _toLowerWithNoOn(strEventType);

		var arListeners = elEventTarget['AERM_arEventListeners_' + strEventType];
		
		if(typeof arListeners == 'object'){
  		for(var i=0, l=arListeners.length; i<l; i++){
  			if(arListeners[i] == fnEventListener){
					arListeners.splice(i,1); //splice the listener out of the array 
					return true;	//return true on success
				}
  		}
		}
	}
	return false;	//return false on failure
}


/***************************************************************/
//Alternate Event Registration Model - Fire an event listener
//HAS NOT BEEN EXPORTED TO DDP NAMESPACE
function AERM_fireListener(elEventTarget, strEventType, objEvent){
  //make sure the event type is in lower case and if it has 'on' at the beginning, take it off.
  strEventType = _toLowerWithNoOn(strEventType);
  
  //make sure the arguments are all of the appropriate type
  if(typeof elEventTarget['on' + strEventType] == 'function' && typeof objEvent == 'object' && objEvent !== null){
    //fire the event
    return elEventTarget['on' + strEventType](objEvent);
  }
  return -1; //if there were no events to fire return -1;
}


/***************************************************************/
//addClass
//adds a CSS class to the element's className attribute (if it's not already there)
//accepts a reference to an element and a string containing the class name
function addClass(el, classToAdd){
  if(el){
		var classRegExp = new RegExp('\\b' + classToAdd + '\\b', 'g');
		
		if(!classRegExp.test(el.className)){
		
  		if(el.className.length != 0)
  			classToAdd += ' ';
  		
  		el.className=classToAdd + el.className;
  	}
  }
}


/***************************************************************/
//removeClass
//removes a CSS class from the element's className attribute
//accepts a reference to an element and a string containing the class name
function removeClass(el, classToRemove){
  if(el){
		var classRegExp = new RegExp('\\b' + classToRemove + '\\b', 'g');
		el.className = el.className.replace(classRegExp, '');  //remove the css class
	}
}


/***************************************************************/
//hasClass
//accepts a reference to an element and string containing the class name to search for.
//returns true if the element has the specified class name, otherwise returns false.
function hasClass(el, classToCheck){
  if(el && el.className){
    var re = new RegExp('\\b' + classToCheck + '\\b', 'gi');
		if(re.test(el.className))
			return true;
	}
	return false;
}

/***************************************************************/
//setClass
//sets an objects class (css) since IE and the Others work differently
function setClass(el,theClass)
{
	if(ddp.f.isIE())
		el.setAttribute('className', theClass);	
	else
		el.setAttribute('class', theClass);
}

/***************************************************************/
//_styleToProperty
//used internally to translate the css style to a DOM property 
function _styleToProperty(strStyle){
  var strResult = '';
  
  var arExceptions = [];
  //if(typeof window.document.style.styleFloat)
    //arExceptions.push(["float","styleFloat"]);
  //else
    arExceptions.push(["float","cssFloat"]);
  //add any other exceptions in the format below 
  //arExceptions.push(["css-style-string","DOMPropertyString"]);
  
  strStyle = strStyle.toLowerCase();
  
  //see if it's one of the exceptions
  for(var i=0, l=arExceptions.length; i<l; i++){
    if(strStyle == arExceptions[i][0])
      return arExceptions[i][1];
  }
  
  //if it's not an exception do the replace operation on it and return the result
  return strStyle.replace(/-([a-z])/g, function (_, ltr) { return ltr.toUpperCase(); });
}

/***************************************************************/
//getEffectiveStyle
//returns the effective CSS style on an element
function getEffectiveStyle(elElement, strStyle) {
  if(typeof elElement == 'string')
    elElement = document.getElementById(elElement);

  if(typeof elElement == 'object'){
    if(window.getComputedStyle){
      var computedStyle = window.getComputedStyle(elElement, '');
      return computedStyle.getPropertyValue(strStyle);
    }
    else if(elElement.currentStyle){ //IE
      var strProperty = _styleToProperty(strStyle);
      if(strProperty=='cssFloat') strProperty = 'styleFloat';
      var strResult = elElement.currentStyle[strProperty];
      if(typeof strResult == 'string')
        return strResult;
    }
  }
  
  return '';
}


/***************************************************************/
//getAncestorByClassName
//climbs up the DOM tree from the startElement supplied until an element with
//the className supplied is found or until there aren't any more elements. it might
//return startElement.parentNode.parentNode.parentNode.parentNode for example.
function getAncestorByClassName(strClassName, startElement){
  if(typeof startElement == 'object'){
  	strClassName = strClassName.toLowerCase();
  
  	for(var currentElement = startElement; currentElement; currentElement = currentElement.parentNode){
			if(currentElement.className)
  			if(currentElement.className.toLowerCase().indexOf(strClassName) != -1)
  				return currentElement;
  	}
  }
	return null;
}


/***************************************************************/
//getElementsByClassName
//find elements underneath a parent element by their
//classname and return them in an array 
function getElementsByClassName(strClassName, elStartElement) {
	if(!elStartElement)
    elStartElement = document.getElementsByTagName('body')[0];
	
	if(elStartElement){
    var a = [];
  	var els = elStartElement.getElementsByTagName('*');
  
  	for(var i=0,j=els.length; i<j; i++)
  		if(hasClass(els[i], strClassName))
  			a.push(els[i]);
    
    return a;
	}
  
  return null;
}


/***************************************************************/
//getChildElementById 
//find an element by it's id, which is a sub element of "fromElement"
//returns the element's reference, or null if the element id can't be found 
function getChildElementById(fromElement, findId){
	if(fromElement){
		findId = String(findId);
		var elChildren = fromElement.getElementsByTagName('*');
		if(elChildren){
    	for(var x=0, l=elChildren.length; x<l; x++){
    		if(elChildren[x].id == findId){
    			return elChildren[x];
  			}
    	}
		}
	}
	return null;
}


/***************************************************************/
//getElementForm 
//climbs up the node tree until it finds a <FORM> element or
//there are no more nodes (in which case null is returned) 
function getElementForm(el){
	var moreParents = true;
	var currentNode = el;
	while(moreParents == true){
		if(currentNode.nodeName.toLowerCase() == 'form')
			return currentNode;
		else{
			if(currentNode.parentNode)
				currentNode = currentNode.parentNode;
			else
				moreParents = false;
		}
	}
	return null;
}


/***************************************************************/
//getRadioValueByName
//returns the value of a radio group when supplied with the name
//if no options in the rradio group have been selected, returns null.
function getRadioValueByName(strRadioName){
	var elRadioGroup = document.getElementsByName(strRadioName);
	for(var i=0, l=elRadioGroup.length; i<l; i++){
		if(elRadioGroup[i].checked)
			return elRadioGroup[i].value;
	}
	return null;
}


/***************************************************************/
function getElementLeft(elObject) {
  var x = 0;
  var elm;
  if(typeof(elObject) == "object"){
    elm = elObject;
  } else {
    elm = document.getElementById(elObject);
  }
  while (elm != null) {
    x+= elm.offsetLeft;
    elm = elm.offsetParent;
  }
  return parseInt(x);
}


/***************************************************************/
function getElementWidth(elObject){
  var elm;
  if(typeof(elObject) == "object")
    elm = elObject;
	else
    elm = document.getElementById(elObject);

  return parseInt(elm.offsetWidth);
}


/***************************************************************/
function getElementRight(elObject){
  return getElementLeft(elObject) + getElementWidth(elObject);
}


/***************************************************************/
function getElementTop(elObject) {
  var y = 0;
  var elm;
  if(typeof(elObject) == "object"){
    elm = elObject;
  } else {
    elm = document.getElementById(elObject);
  }
  while (elm != null) {
    y+= elm.offsetTop;
    elm = elm.offsetParent;
  }
  return parseInt(y);
}


/***************************************************************/
function getElementHeight(elObject){
  var elm;
  if(typeof(elObject) == "object")
    elm = elObject;
	else
    elm = document.getElementById(elObject);
	
  return parseInt(elm.offsetHeight);
}


/***************************************************************/
function getElementBottom(elObject){
	return getElementTop(elObject) + getElementHeight(elObject);
}


/***************************************************************/
//addStyleSheet
//adds an inline stylesheet to the document header
//objProperties is an object with properties which are identical to
//the attributes in the style tag you want to create eg. var objProperties = {type:'text/css',rel:'screen'}
//elDocument is optional
function addStyleSheet(objProperties, strCSSText, elDocument){
  if(typeof elDocument != 'object') elDocument = window.document;

  	var elHead = elDocument.getElementsByTagName('head')[0];
  	var elStyle = elDocument.createElement('style');
  	
  	if (typeof objProperties == 'object') {
  		for (var key in objProperties) {
  			try {
  				elStyle.setAttribute(key, objProperties[key]);
  			} 
  			catch (e) {
  			}
  		}
  	}
  	elStyle.setAttribute('type', 'text/css');
  	
  	if (elStyle.styleSheet) 
  		elStyle.styleSheet.cssText = strCSSText;
  	else 
  		elStyle.appendChild(elDocument.createTextNode(strCSSText));
  	
  	elHead.appendChild(elStyle);
}

/***************************************************************/
//Add a link to a style sheet
function addLinkStyleSheet(strCSSFile, elDocument){
  if(typeof elDocument != 'object') elDocument = window.document;
  
  //check to see if the style has already been added.
  var elLinks = elDocument.getElementsByTagName('LINK');
  var blnCSSLinked = false;
  
  for(var i=0, l=elLinks.length; i<l;i++){
			if (elLinks[i].href.toLowerCase().indexOf(strCSSFile) > -1) {
				blnCSSLinked = true;
			}
		}
  
  if (!blnCSSLinked) {
  
  	var objLinkedCSS = elDocument.createElement('LINK');
      var elHead = elDocument.getElementsByTagName('head')[0];
  		objLinkedCSS.type='text/css';
  		objLinkedCSS.rel='stylesheet';
  		objLinkedCSS.media='screen';
  		objLinkedCSS.href=strCSSFile;
	 if(elHead.firstChild)
        elHead.insertBefore(objLinkedCSS, elHead.firstChild);
      else
  		  elHead.appendChild(objLinkedCSS);
		
		
	 return true;
  }
  else
  return false;
}


/***************************************************************/
//addScriptToHeader
//adds a script tag to the document header
//objProperties is an object with properties which are identical to
//the attributes in the script tag you want to create eg. var objProperties = {type:'text/javascript',language:'javascript'}
//elDocument is optional
function addScriptToHeader(objProperties, strScriptText, elDocument){
  if(typeof elDocument != 'object') elDocument = window.document;
  
  var elHead = elDocument.getElementsByTagName('head')[0];
  var elScript = elDocument.createElement('script');
  
  if(typeof objProperties == 'object'){
    for(var key in objProperties){
      try{
        elScript.setAttribute(key, objProperties[key]);
      }
      catch(e){}
    }
  }
  
  elScript.setAttribute('defer', 'defer');
  
  if(elScript.canHaveChildren || elScript.canHaveChildren == null)
    elScript.appendChild(document.createTextNode(strScriptText));
  else
    elScript.text = strScriptText;
  
  elHead.appendChild(elScript);
}


/***************************************************************/
//removeElement
//Removes an element with the supplied element ID 
function removeElement(elementId){
	if(document.getElementById(elementId)){
		var el = document.getElementById(elementId);
		try{
			el.parentNode.removeChild(el);
			return true;
		}
		catch(e){
			//alert(e.number);
		}
	}
	return false;
}


/***************************************************************/
//insertElementAfter
//inserts an element into the DOM tree after the supplied element.
//
function insertElementAfter(elementToInsert, elementToInsertAfter){
	elementToInsertAfter.parentNode.insertBefore(elementToInsert, elementToInsertAfter.nextSibling);
}


/***************************************************************/
//setOpacity 
//sets the percent opacity of an element using IE and FF/NS CSS opacity 
//
function setOpacity(elObjId, opacityPercentage){
	elObj = document.getElementById(elObjId);
	opacityPercentage = parseInt(opacityPercentage);
	if(elObj){
		elObj.style.opacity = opacityPercentage/100;
		elObj.style.filter = 'alpha(opacity=' + opacityPercentage + ')';
	}
}


/***************************************************************/
//toCamelCase (proper case)
//converts the value of textObj to camel case/title case
//(eg. "First Letter Of Every Word Capitalized") 
function toCamelCase(textObj){
	var resultStr = '';
  var strText = textObj.value;
  var intLength = strText.length;
	if(intLength > 0){
  	resultStr = strText.substr(0,1).toUpperCase();
  	for(x=1; x<intLength; x++){
  		if(strText.substr(x-1,1)==' ')
  			resultStr+=strText.substr(x,1).toUpperCase();
  		else
  			resultStr+=strText.substr(x,1)//.toLowerCase();
  	}
	}
	return resultStr;
}


/***************************************************************/
//countOccurances
//counts the number of times 'charToCheckFor' is in 'stringToCheck' 
function countOccurances(stringToCheck, charToCheckFor){
	var count = 0;
	var strToCheck = new String(stringToCheck);
	var chrToCheckFor = new String(charToCheckFor);
	for(var i=0, l=strToCheck.length; i<l; i++){
		if(strToCheck.substr(i,1) == chrToCheckFor){
			count++;
		}
	}
	return count;
}


/***************************************************************/
//removeInvalidChars
//removes invalid characters from a string or element, based on the data type supplied 
function removeInvalidChars(strDataType, strOrEl){
	var reDataType = null;
  var strReturn = null;
  
	switch(strDataType.toLowerCase()){
  	case 'date':
  		reDataType = /[^0-9/\-janfebmryulgspoctvd,\. ]/gi;
  		break;
		case 'number':
  		reDataType = /[^0-9\.]/g;
  		break;
		case 'postalcode', 'coursecode':
  		reDataType = /[^0-9a-z]/gi;
  		break;
		case 'phonenumber':
			reDataType = /[^0-9]/g;
  		break;
		case 'email':
  		reDataType = /[^0-9a-z@\._]/gi;
			break;
		case 'filename':
  		reDataType = /[^0-9a-zA-Z\._\(\)\+\-\!@#\$%\^&,`~\[\]{} ']/g;
  		break;
		case 'text':
  		reDataType = /[^0-9a-z\._\(\)\+\-\!@#\$%\^&,`~\[\]{} ':;\|\*<>\\/\?]/gi;
  		break;
	}
  
  if(reDataType){
    if(!isString(strOrEl) && typeof strOrEl == 'object'){
      strReturn = strOrEl.value.replace(reDataType, '');
      strOrEl.value = strReturn;
    }
    else
      strReturn = strOrEl.replace(reDataType, '');
  }

  return strReturn;
}


/***************************************************************/
//inputFilter
//define characters allowed in fields with specific data types
//USE WITH ONKEYPRESS ONLY
function inputFilter(strDataType, objEvent) {
  //allow any non-character keys, backspace etc..
  var charCode = document.all ? objEvent.keyCode : objEvent.which; 
  if(charCode==8 || charCode==9 || charCode==0)
		return true;
  
  //see if the character is removed 
  var strResult = removeInvalidChars(strDataType, String.fromCharCode(charCode));
  if(strResult && strResult.length == 1)
    return true;
  
  cancelEvent(objEvent); //cancel the keypress
  return false;
}


/***************************************************************/
//formatPhoneNumber
//Formats a phone number field into "(xxx) xxx-xxxx" or "xxx-xxxx" format, depending on length.
function formatPhoneNumber(strOrEl){
  //get the actual string we'll be working with
  var strValue = isString(strOrEl) ? strOrEl : strOrEl.value;
  //remove any non-numeric characters
  strValue = removeInvalidChars('phoneNumber', strValue);
  //if it's a ten digit number with a 1 at the beginning, assume it's a long distance indicator and remove it
  if(strValue.length == 11 && strValue.substr(0,1) == '1')
    strValue = strValue.substr(1);
  
  if(strValue.length == 7) //format a 7 digit number: 555-5555
    strValue = strValue.substr(0,3) + '-' + strValue.substr(3);
  else if(strValue.length == 10) //format a 10 digit number: (555) 555-5555
  	strValue = '(' + strValue.substr(0,3) + ') ' + strValue.substr(3,3) + '-' + strValue.substr(6);

  //if we got passed an element and the new value is different, set the element's value 
  if(!isString(strOrEl) && typeof strOrEl == 'object' && strOrEl.value != strValue)
    strOrEl.value = strValue;
  
  //return the resultant string
  return strValue;
}


/***************************************************************/
//imposeMaxLength
//reproduces the effect "maxlength" has on a regular text <input> for a <textarea> element 
function imposeMaxLength(intMaxLength, objEvent) {
	//get the object that fired the event
	var elText = getEventTarget(objEvent);
  var intTextLength = elText.value.length;
		
	if(objEvent.type=='keypress'){
    var chrCode = document.all ? objEvent.keyCode : objEvent.which;
  	if(chrCode==8 || chrCode==9 || chrCode==0)
  		return true;
		if(intTextLength >= intMaxLength){
      cancelEvent(objEvent);
			return false;
    }
	}
	else if(objEvent.type=='blur'){
  	if(intTextLength > intMaxLength){
      elText.value = elText.value.substr(0, intMaxLength); //truncate the text
      alert('This field can contain a maximum of ' + intMaxLength + ' characters. The text has been truncated to fit.');
      cancelEvent(objEvent); //don't let the event happen
      if(typeof elText.focus == 'function')
        elText.focus(); //focus the element that just had it's text truncated
      return false;
  	}
	}

	return true;
}


/***************************************************************/
//getFromURL
//gets the value of a variable passed to the page in the querystring 
//[equivalent to VB's request.querystring(varName) ]
function getFromURL(varName){
	var args = '';
	//get the URL of this page
	var pageURL = new String(window.location);
	//if the URL contains a question mark, then it was loaded with arguments in the URL
	if(pageURL.indexOf('?') != -1){
		//grab everything in the URL after the question mark
		args = pageURL.substr(pageURL.indexOf('?')+1);
		//split the querystring into an array of strings with each element containing "example=blah"
  	var splitArgs = args.split('&');
		//go through all the elements in the array of arguments
  	for(var i=0, l=splitArgs.length; i<l; i++){
			//split each array element into an array of 2 strings with the first element containing "example" and the second "blah"
  		splitArgs[i] = splitArgs[i].split('=');
			//if the variable passed in the querystring is our requested name
  		if(splitArgs[i][0].toLowerCase()==varName.toLowerCase()){
  			return decodeURIComponent(splitArgs[i][1]); //get it's contents
  		}
  	}
	}
	 	
	return ''; //if the variable doesn't exist return a blank string;
}


/***************************************************************/
//extractServerandPath
//takes a URL and extracts the server and path
//removes any file name or arguments. 
function extractServerandPath(inVar){
  var returnStr = new String(inVar);
  
  if(returnStr.indexOf('?') != -1)
  	returnStr = returnStr.substr(0,returnStr.indexOf('?'));
  returnStr = returnStr.substr(0,returnStr.lastIndexOf('/') + 1);
	
	return returnStr;
}


/***************************************************************/
//getServerNameFromURL
//
//
function getServerNameFromURL(strURL){
	var strServer = new String(strURL);
	
	if(strServer.indexOf('//') != -1){
	  strServer = strServer.substr(strServer.indexOf('//') + 2);
		strServer = strServer.substr(0, strServer.indexOf('/'));
		
		return strServer.toLowerCase();
	}
	
	return null;
}


/***************************************************************/
//setCookie
//sets a browser cookie
//
function setCookie(name, value, expires, path, domain, secure) {
  document.cookie= name + "=" + escape(value) +
		((expires) ? "; expires=" + expires.toGMTString() : "") +
		((path) ? "; path=" + path : "") +
		((domain) ? "; domain=" + domain : "") +
		((secure) ? "; secure" : "");
}


/***************************************************************/
//getCookie
//gets the value of a browser cookie by the cookie's name 
//
function getCookie(name){
  var dc = document.cookie;
  var prefix = name + "=";
  var begin = dc.indexOf("; " + prefix);
	
  if(begin == -1){
		begin = dc.indexOf(prefix);
		if(begin != 0)
			return null;
  }
	else
		begin += 2;

  var end = document.cookie.indexOf(";", begin);
	
  if(end == -1){
		end = dc.length;
  }
	
  return decodeURIComponent(dc.substring(begin + prefix.length, end));
}


/***************************************************************/
//deleteCookie
//removes a browser cookie from the browser cache
//
function deleteCookie(name, path, domain){
	if(getCookie(name)) {
		document.cookie = name + "=" +
			((path) ? "; path=" + path : "") +
			((domain) ? "; domain=" + domain : "") +
			"; expires=Thu, 01-Jan-70 00:00:01 GMT";
	}
}


/***************************************************************/
//getRandomInRange
//returns a random integer between intMinimum and intMaximum 
function getRandomInRange(intMinimum, intMaximum){
  //return Math.round(intMinimum + (Math.random() * (intMaximum - intMinimum)));
  return Math.floor((intMaximum - (intMinimum-1)) * Math.random()) + intMinimum;
}
  

/***************************************************************/
//isValidDate
//accepts either an <input> element or a string 
//returns true if the date is valid and in "mm/dd/yy" (6/26/81) or "dd-mmm-yy" (26-jun-81) format
function isValidDate(elOrStr){
	try{
  	var dtStr = null;
  	
  	if(typeof elOrStr == 'object')
  		dtStr = elOrStr.value;
  	else if(elOrStr!=null)
  		dtStr = elOrStr;
  	
  	if(parseDateString(dtStr)!=null)
  		return true;
	}
	catch(e){}
	
	return false;
}


/***************************************************************/
//parseDateString 
//parses a date string and returns a js date object
function parseDateString(strValue) {
	var strDate = strValue;
	var objReturnDate = new Date();
	
	var dayPart = '';
	var monthPart = '';
	var yearPart = '';
	
	if(strValue==null)
		return null;
  
	strDate = String(strDate);
	strDate = strDate.replace(/\//g, '-');
	strDate = strDate.replace(/ /g, '-');
	strDate = strDate.replace(/,/g, '-');
	strDate = strDate.replace(/\./g, '-');
	
	var temp = strDate.split('-');
	var parts = [];
	
	for(var x=0; x<temp.length; x++){
		if(temp[x] != ''){
			parts[parts.length] = temp[x];
		}
	}

	if(parts.length!=3){
		return null;
	}
	
	if(isMonth(parts[0])){
		dayPart = parts[1];
		monthPart = isMonth(parts[0]);
	}	
	else if(isMonth(parts[1])){
		dayPart = parts[0];
		monthPart = isMonth(parts[1]);
	}
  else{
		monthPart = parts[0];
		dayPart = parts[1];
  }

	
	yearPart = fourDigitYear(parts[2]);

  if(dayPart <= daysInMonth(yearPart, monthPart) && dayPart > 0 && monthPart < 13 && monthPart > 0 && yearPart > 1900 && yearPart < 2099){
		objReturnDate.setFullYear(yearPart,monthPart-1,dayPart);
  	return objReturnDate;
	}
  else{
  	return null;
  }
}


/***************************************************************/
//isMonth
//returns the month number from a month name (or short form)
//if the string doesn't contain a month name, returns zero 
function isMonth(inStr){
	inStr = inStr.toLowerCase();
	var monthName = new Array('january', 'february', 'march', 'april', 'may', 'june', 'july', 'august', 'september', 'october', 'november','december');
	for(var i=0, l=monthName.length; i<l; i++){
		if(inStr==monthName[i] || inStr==monthName[i].substr(0,3))
			return i+1;
	}
  return 0;
}


/***************************************************************/
//dateFormat
//formats a date in a specified type.
// 1 - dd-mmm-yyyy (26-Jun-1981)
// 2 - mm/dd/yyyy (6/26/1981)
function dateFormat(month, day, year, type){
  var objDate = null;
	var monthName = new Array('January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November','December');
  var frenchMonthName = new Array('Janvier', 'Février', 'Mars', 'Avril', 'Mai', 'Juin', 'Juillet', 'Aôut', 'Septembre', 'Octobre', 'Novembre','Décembre');
  var frenchMonthNameShort = new Array('Jan', 'Fév', 'Mars', 'Avr', 'Mai', 'Juin', 'Juil', 'Aôut', 'Sept', 'Oct', 'Nov','Déc');

  if(typeof month == 'object')
    objDate = month;
	else if(typeof month == 'string' && day == null & year == null){
 		objDate = parseDateString(month);
  }
  else if(month != null && day != null & year != null){
    objDate = parseDateString(day + ' ' + monthName[month-1] + ' ' + year);
  }
  
  if(objDate){
    var month = objDate.getMonth() + 1;
    var day = objDate.getDate();
    var year = objDate.getFullYear();
    var hour = objDate.getHours();
    var pm = false;
    
    if(hour == 0)
      hour = 12;
    if(hour > 12){
      hour = hour - 12;
      pm = true;
    }

    minute = objDate.getMinutes()
    if(minute<10)
      minute = '0' + minute;
    second = objDate.getSeconds();
    if(second<10)
      second = '0' + second;
    
	  if(!type)
		  type = 1;

  	if(type==1)
  		return day + '-' + monthName[month-1].substr(0,3) + '-' + year;
    else if(type==2)
  		return day + '-' + frenchMonthNameShort[month-1] + '-' + year;
  	else if(type==3)
  		return month + '/' + day + '/' + year;
  	else if(type==4)
  		return year + '-' + month + '-' + day;
    else if(type==5)
      if(hour == 12 && minute == '00' && pm === false)
        return day + '-' + monthName[month-1].substr(0,3) + '-' + year;
      else
        return day + '-' + monthName[month-1].substr(0,3) + '-' + year + ' ' + hour + ':' + minute + (pm ? 'pm' : 'am');
  }
  
  return '';
}


function fourDigitYear(year){
	year = String(year);
	
	if (year.length == 2){
			if(parseInt(year) < 50)
      	return '20' + year;
			else
				return '19' + year;
	}
	else if (year.length == 4)
		return year;
	else
		return -1;
}

function daysInMonth(year, month) {
	return [31,((!(year % 4 ) && ( (year % 100 ) || !( year % 400 ) ))?29:28),31,30,31,30,31,31,30,31,30,31][month-1];
}



/**************************************************/
//addDateFieldButtons
//
function addDateFieldButtons(strNameOfClass){
	var dateFields = getElementsByClassName(strNameOfClass);
	for(var i=0, l=dateFields.length; i<l; i++){
		dateFields[i].title = '(default date format dd-mmm-yyyy)';
		
		var elCalendarButton = document.createElement('INPUT');
		elCalendarButton.title = 'Choose the date from a calendar';
		elCalendarButton.type = 'button';
		elCalendarButton.className = 'calendarButton';

		addEvent(elCalendarButton, 'click', function(e){showCalendarControl(getEventTarget(e).previousSibling); });
		
		insertElementAfter(elCalendarButton, dateFields[i]);
		
		addEvent(dateFields[i], 'keypress', function(e){return inputFilter('date', e);});
		addEvent(dateFields[i], 'blur', function(e){validateAndReformat(getEventTarget(e));});
	}
}

/**************************************************/
//Add or Strip Slashes to/from a String
/**************************************************/

function addSlashes(str){
  str=str.replace(/\\/g,'\\\\');
  str=str.replace(/\'/g,'\\\'');
  str=str.replace(/\"/g,'\\"');
  str=str.replace(/\0/g,'\\0');
  return str;
}

function stripSlashes(str){
  str=str.replace(/\\'/g,'\'');
  str=str.replace(/\\"/g,'"');
  str=str.replace(/\\0/g,'\0');
  str=str.replace(/\\\\/g,'\\');
  return str;
}

/**************************************************/

function linkTextToUrl(str) 
{
	//convert any text that contains http into a link
	var exp = /(\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/ig;
	return str.replace(exp,"<a href='$1' target='_blank'>$1</a>");
}

/**************************************************/

function getNodeTree(object)
{	
	var sel = this.getSelection(object);
	var range = this.getRange(sel);	
	
	// get element of range
	var tag = this.getTag(range);
	
	if(tag == null) { return; }
	// get parent of element
	var node = this.getParent(tag);
	
	// init the tree as array with the current selected element
	var nodeTree = new Array(tag);
	// get all parent nodes
	var ii = 1;
	
	while(node != null && node.nodeName != "#document") {
		nodeTree[ii] = node;
		node = this.getParent(node);			
		ii++;
	}
	
	return nodeTree;
}
	
function getSelection(object)
{
	var ifrm = object.contentWindow;
	
	var doc = ifrm.document;
	var sel = null;
	if(ifrm.getSelection){
		sel = ifrm.getSelection();
	}
	else if (doc.getSelection) {
		sel = doc.getSelection();
	}
	else if (doc.selection) {
		sel = doc.selection;
	}
	return sel;
}

function getRange(sel)
{
	return sel.createRange ? sel.createRange() : sel.getRangeAt(0);
}

function getTag(range) 
{
		try {
		    if(!ddp.f.isIE()) {
				var node = range.startContainer;	
				var pos = range.startOffset;
				if(node.nodeType != 3) { node = node.childNodes[pos]; }
				
				if(node.nodeName && node.nodeName.search(/#/) != -1) {
					return node.parentNode;
				}
				return node;
			}
			else {
				if(range.length > 0) {
					return range.item(0);
				}
				else if(range.parentElement()) {
					return range.parentElement();
				}
			}
			return null;
		}
		catch(e) {
			return null;
		}
}

function getParent(element) {
		if(element.parentNode) {
			return element.parentNode;
		}
		return null;
	}


/**************************************************/

function setFloat(obj,where)
{
	var floatValue = obj.style['cssFloat'] || obj.style['styleFloat'];
	obj.style['cssFloat'] = where;
	obj.style['styleFloat'] = where;
}

/**************************************************/
//Export the public functions to a public namespace
//use: ddp.f.function();
/**************************************************/
	
	var ddpns = ddp.f;
	ddpns.$ = $;
	ddpns.addLoadEvent = addLoadEvent;
	ddpns.obsEvent = obsEvent;
	ddpns.mousePosition = mousePosition;
  ddpns.makeRealArray = makeRealArray;
  ddpns.isArray = isArray;
  ddpns.isString = isString;
	ddpns.removeAlpha = removeAlpha;
	ddpns.removeNonAsciiWord = removeNonAsciiWord;
	ddpns.checkValidPhoneNumber = checkValidPhoneNumber;
	ddpns.checkValidEmailAddress = checkValidEmailAddress;
	ddpns.isIE = isIE;
	ddpns.getBrowserGeometry = getBrowserGeometry;
	ddpns.returnMaxZindex = returnMaxZindex;
	ddpns.addEvent = addEvent;
	ddpns.removeEvent = removeEvent;
  ddpns.fireEvent = fireEvent;
  ddpns.cancelEvent = cancelEvent;
	ddpns.getEventTarget = getEventTarget;
  ddpns.getEventKey = getEventKey;
	ddpns.detectDoctype = detectDoctype;
	ddpns.addClass = addClass;
	ddpns.removeClass = removeClass;
	ddpns.hasClass = hasClass;
	ddpns.setClass = setClass;
  ddpns.getEffectiveStyle = getEffectiveStyle;
	ddpns.BrowserDetect = BrowserDetect;
	ddpns.getAncestorByClassName = getAncestorByClassName;
	ddpns.getElementsByClassName = getElementsByClassName;
	ddpns.getChildElementById = getChildElementById;
	ddpns.getElementForm = getElementForm;
	ddpns.getRadioValueByName = getRadioValueByName;
	ddpns.getElementLeft = getElementLeft;
	ddpns.getElementWidth = getElementWidth;
	ddpns.getElementRight = getElementRight;
	ddpns.getElementTop = getElementTop;
	ddpns.getElementHeight = getElementHeight;
	ddpns.getElementBottom = getElementBottom;
  ddpns.addStyleSheet = addStyleSheet;
  ddpns.addLinkStyleSheet = addLinkStyleSheet;
  ddpns.addScriptToHeader = addScriptToHeader;
	ddpns.removeElement = removeElement;
	ddpns.insertElementAfter = insertElementAfter;
	ddpns.setOpacity = setOpacity;
	ddpns.toCamelCase = toCamelCase;
	ddpns.countOccurances = countOccurances;
	ddpns.removeInvalidChars = removeInvalidChars;
	ddpns.inputFilter = inputFilter;
	ddpns.formatPhoneNumber = formatPhoneNumber;
	ddpns.imposeMaxLength = imposeMaxLength;
	ddpns.getFromURL = getFromURL;
	ddpns.extractServerandPath = extractServerandPath;
	ddpns.getServerNameFromURL = getServerNameFromURL;
	ddpns.setCookie = setCookie;
	ddpns.getCookie = getCookie;
	ddpns.deleteCookie = deleteCookie;
  ddpns.getRandomInRange = getRandomInRange;
  ddpns.isValidDate = isValidDate;
  ddpns.parseDateString = parseDateString;
	ddpns.addDateFieldButtons = addDateFieldButtons;
  ddpns.dateFormat = dateFormat;
  ddpns.addSlashes = addSlashes;
  ddpns.stripSlashes = stripSlashes;
  ddpns.linkTextToUrl = linkTextToUrl;
  ddpns.getNodeTree = getNodeTree;
  ddpns.getSelection = getSelection;
  ddpns.getRange = getRange;
  ddpns.getTag = getTag;
  ddpns.getParent = getParent;
  ddpns.setFloat = setFloat;
  
})();
