
function IsLeapYear(year)
	{
	return (year % 4)==0 && (year % 100)!=0 || (year % 400)==0;
	}



function GetMonthLength(month,year) 
	{
	var MonthLength=new Array(31,28,31,30,31,30,31,31,30,31,30,31);
	
	if(month==2 && IsLeapYear(year))
		return 29;
	else 
		return MonthLength[month-1];
	}


function DateFormatCheck(str,issueError)
	{
	//var datePat=/^(\d{1,2})(\-|\/|\.)(\d{1,2})\2(\d{2,4})$/;
	var datePat=/^(\d{2})(\/)(\d{2})\2(\d{4})$/;

	var datefields=str.match(datePat);
	if(datefields==null) {
		if(issueError)
			alert("La date "+str+" n'est pas dans le bon format (jj/mm/aaaa)");
		return false;
		}
	var day=parseInt(datefields[1],10);
	var month=parseInt(datefields[3],10);
	var year=parseInt(datefields[4],10);

	if(year<100) {
		if(year>50)
			year+=1900;
		else
			year+=2000;
		}
	else if(year<1000) {
		if(issueError)
			alert("La date "+str+" n'est pas dans le bon format car l'année est soit 2 chiffres, soit 4 chiffres ou plus");
		return false;
		}
	
	if(month<1 || month>12) {
		if(issueError)
			alert("La date "+str+" n'est pas dans le bon format car le mois est un chiffre entre 1 er 12");
		return false;
		}
	if(day<1 || day>GetMonthLength(month,year)) {
		if(issueError)
			alert("La date "+str+" n'est pas dans le bon format car le jour est un chiffre entre 1 er "+GetMonthLength(month,year));
		return false;
		}
	return true;		
	}
	
	
function EmailFormatCheck(emailStr,issueError)
	{
	// check if email us in the username@domain format
	var emailPat=/^(.+)@(.+)$/;
	// special characters that can't occur in the database
	var specialChars="\\(\\)<>@,;:\\\\\\\"\\.\\[\\]";
	// valid characters in a username or domain
	var validChars="\[^\\s" + specialChars + "\]";
	// quoted usernames are OK
	var quotedUser="(\"[^\"]*\")";
	// allow for [ip address] as a domain name
	var ipDomainPat=/^\[(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})\]$/;
	var atom=validChars + '+';
	var word="(" + atom + "|" + quotedUser + ")";
	var userPat=new RegExp("^" + word + "(\\." + word + ")*$");
	var domainPat=new RegExp("^" + atom + "(\\." + atom +")*$");

	var matchArray=emailStr.match(emailPat);
	if (matchArray==null) {
		if(issueError)
			alert("Adresse email incorrecte (pas de '@' ou de '.')")
		return false;
		}
	var user=matchArray[1];
	var domain=matchArray[2];

	if (user.match(userPat)==null) {
		if(issueError)
			alert("Le nom de l'utilisateur dans l'adresse email n'est pas correct.")
		return false;
		}

	var IPArray=domain.match(ipDomainPat);
	if (IPArray!=null) {
		for (var i=1;i<=4;i++) {
			if (IPArray[i]>255) {
				if(issueError)
					alert("L'adresse IP de l'email n'est pas valide!");
				return false;
				}
			}
		return true;
		}

	var domainArray=domain.match(domainPat);
	if (domainArray==null) {
		if(issueError)
			alert("Le domaine de l'adresse email n'est pas valide.")
		return false;
		}

	var atomPat=new RegExp(atom,"g");
	var domArr=domain.match(atomPat);
	var len=domArr.length;
	if (domArr[domArr.length-1].length<2 || domArr[domArr.length-1].length>4) {
		if(issueError)
			alert("Le domaine de l'adresse email doit consister de 2 à 4 caractères.")
		return false;
		}

	if (len<2) {
		if(issueError)
			alert("Pas de hostname avant l'adresse!")
		return false;
		}
		
	return true;
	}


function GetRadioChecked(buttonlist)
	{
	for(var i=0;i<buttonlist.length;++i)
		if(buttonlist[i].checked)
			return i;
	return -1;
	}
	

	
function StripSpace(str)
	{
    while(str.substring(0,1)==' ') 
		str=str.substring(1);
    while(str.substring(str.length-1,str.length)==' ') 
		str=str.substring(0,str.length-1);
    return str;
	}
	
		
function IsEmptyText(str)
	{
	return StripSpace(str).length==0;
	}


function IsEmptyInput(theInput)
	{
	return StripSpace(theInput.value).length==0;
	}


function CheckNonEmpty(theInput,msg)
	{
	if(IsEmptyInput(theInput)) {
		alert(msg);
		theInput.focus();
		return false;
		}
	return true;
	}

function D(x)
{
	if (x >= '0' && x <= '9') 
		return true;
	else
		return false;
}

function AllDigits(x)
{
	for (var i = 0; i < x.length; i++)
		if (!D(x.charAt(i)))
			return false;
	return true;
}

function AllDigitsFloat(x)
{
	var yetSeparator;
	yetSeparator = false;
	for (var i = 0; i < x.length; i++)
	{
		if (!D(x.charAt(i)) && (x.charAt(i) != '.' || yetSeparator) && (x.charAt(i) != ',' || yetSeparator))
			return false;
		if (x.charAt(i) == '.' || x.charAt(i) == ',')
			yetSeparator = true;
	}
	return true;
}
	
function CheckNumeric(theInput,msg)
	{
	if(IsEmptyInput(theInput) || !AllDigits(theInput.value)) {
		alert(msg);
		theInput.focus();
		return false;
		}
	return true;
	}

function CheckNumericFloat(theInput,msg)
	{
	if(IsEmptyInput(theInput) || !AllDigitsFloat(theInput.value.replace(",","."))) {
		alert(msg);
		theInput.focus();
		return false;
		}
	return true;
	}

function CheckEmail(theInput,msg)
	{
	if(!EmailFormatCheck(theInput.value,false)) {
		alert(msg);
		theInput.focus();
		return false;
		}
	return true;
	}

	
function CheckDate(theInput,msg)
	{
	if(!DateFormatCheck(theInput.value,false)) {
		alert(msg);
		theInput.focus();
		return false;
		}
	return true;
	}

	
function OpenCenteredDialog(dlgWidth,dlgHeight,url,targetName)
	{
	// a weak-hearted attempt at a modal dialog... we can't do modal stuff in Netscape, sadly
	var attr='toolbar=no,location=no,directories=no,status=no,menubar=0,scrollbars=1,resizable=1,width='+dlgWidth+',height='+dlgHeight;

	// attempt to center
	if(document.all) {
		// internet explorer
		attr+=',left='+(screen.width-dlgWidth)/2;
		attr+=',top='+(screen.height-dlgHeight)/2;
		}
	else {
		// netscape
		attr+=',screenX='+(window.screenX+((window.outerWidth-dlgWidth)/2));
		attr+=',screenY='+(window.screenY+((window.outerHeight-dlgHeight)/2));
		}
	if(targetName==null || targetName.length==0)
		targetName='Popup';
	var dlg=window.open(url,targetName,attr);
	dlg.focus();
	return dlg;
	}

function OpenSalonDuLivreDialog(dlgWidth,url,targetName)
	{
	// a weak-hearted attempt at a modal dialog... we can't do modal stuff in Netscape, sadly
	var attr='toolbar=no,location=no,directories=no,status=no,menubar=0,scrollbars=1,resizable=0,width='+dlgWidth+',height=390';

	// for salon du livre: in top left corner
	if(document.all) {
		// internet explorer
	    attr+=',left=0,top=0'
		}
	else {
		// netscape
	    attr+=',screenX=0,screenY=0'
		}
	if(targetName==null || targetName.length==0)
		targetName='Popup';
	var dlg=window.open(url,targetName,attr);
	dlg.focus();
	return dlg;
	}

function OpenModalDialog(dlgWidth,dlgHeight,url,targetName)
	{	
	if(window.showModalDialog)
		window.showModalDialog(url,null,"dialogWidth: "+dlgWidth+"px; dialogHeight: "+dlgHeight+"px");
	else 
		return OpenCenteredDialog(dlgWidth,dlgHeight,url,targetName)
	}

function RemoveOption(optionList,itemIndex)
	{
	if(document.all)
		optionList.remove(itemIndex);
	else
		optionList[itemIndex]=null;
	}


function AddOption(toOptions,itemText,itemValue,selectItem)
{
	if(document.all) 
	{
		var newItem=document.createElement("option");
		newItem.text=itemText;
		newItem.value=itemValue;
		newItem.defaultSelected=selectItem;
		newItem.selected=selectItem;
		toOptions.add(newItem);
	}
	else
		toOptions[toOptions.length]=new Option(itemText,itemValue,selectItem,selectItem);
}


function TransferItem(fromOptions,toOptions,selectItem)
{
	for(var i=fromOptions.length;i>0;--i) 
	{
		var item=fromOptions[i-1];
		if(item.selected) 
		{
			AddOption(toOptions,item.text,item.value,selectItem);
			RemoveOption(fromOptions,i-1);
		}
	}
}


function RemoveItem(theForm)
	{
	TransferItem(theForm.Selected.options,theForm.Available.options,false);
	}

function AddItem(theForm)
	{
	TransferItem(theForm.Available.options,theForm.Selected.options,true);
	}



function SelectAll(theSelect)
{
	var optionList=theSelect.options;
	for(var i=0;i< optionList.length;++i) 
		optionList[i].selected=true;		
}


function AddUrlParam(url,name,value)
{
	var str=url;
	if(str.indexOf('?')<0)
		str+='?';
	else
		str+='&';
	return str+name+'='+escape(value);
}

// add an event listener
function addEvent(o,e,f)
{
	if(o.addEventListener)
	{ 
		o.addEventListener(e,f,true); 
		return true; 
	}
	else if(o.attachEvent)
		return o.attachEvent("on"+e,f);
	else 
		return false;
}


// set a global variable if not already set
function setDefault(name,val) 
{
	if(typeof(window[name])=="undefined" || window[name]==null)
		window[name]=val;
}


function AjaxGetInnerText(node) 
{
	var innerText;
	if(typeof node.textContent!='undefined')
		innerText=node.textContent;
	else if(typeof node.innerText!='undefined') 
		innerText=node.innerText;
	else if(typeof node.text!='undefined')
		innerText=node.text;
	else 
		switch(node.nodeType) 
		{
			case 3:		// NODE_TEXT
			case 4:		// NODE_CDATA_SECTION 
				innerText=node.nodeValue;
				break;
			case 1:		// NODE_ELEMENT 
			case 11:	// NODE_DOCUMENT_FRAGMENT 
				innerText='';
				for (var i=0;i<node.childNodes.length;++i) 
					innerText+=AjaxGetInnerText(node.childNodes[i]);
				break;
			default:
				innerText='';
				break;
		}
	return innerText;
}

function AjaxGetNodeXml(node)
{
	if(typeof XMLSerializer!='undefined')
		return new XMLSerializer().serializeToString(node);
	else if(typeof node.xml!='undefined')
		return node.xml;
	else
		return '';
}


function AjaxShowError(request)
{
	var s=request.responseText;
	if(s==null || s.length==0)
		alert('Réponse absente');
	else
	{
		var p=s.indexOf('<body');
		if(p>=0)
			s=s.substr(p);
		alert('Réponse absente '+s);
		//document.body.innerHTML=s;	// remove this after debugging
	}
}

function AjaxResponse(request)
{
	var doc=request.responseXML;
	if(doc==null)
	{
		AjaxShowError(request);
		return;
	}
	var root=doc.documentElement;
	if(root==null)
	{
		var str='';
		if(doc.parseError && doc.parseError.errorCode!=0)
		{
			if(doc.parseError.url)
				str+=doc.parseError.url
			str+='(Ligne '+doc.parseError.line+')';
			str+=': '+doc.parseError.reason;
			str+='('+doc.parseError.errorCode+')';
		}
		else
			str='La réponse XML ne contient pas de racine.';
		alert(str);
		AjaxShowError(request);
		return;
	}
	if(root.nodeName!='ajax-response')
	{
		alert('Le nom de la racine de la réponse XML n\'est pas correct: '+root.nodeName+'('+AjaxGetNodeXml(root)+')');
		return;
	}
	var child=root.firstChild;
	while(child!=null)
	{
		var nodeName=child.nodeName;
		if(nodeName=='alert')
			alert(AjaxGetInnerText(child));
		else if(nodeName=='alerta')
		{
			var innerText='';
			var p=child.firstChild;
			while(p!=null)
			{
				innerText+=AjaxGetInnerText(p);
				if(p.nodeType==1 && p.nodeName=='p')
					innerText+='\n';
				p=p.nextSibling;
			}
			alert(innerText);			
		}
		else if(nodeName=='execute')
			eval(AjaxGetInnerText(child));
		else if(nodeName=='executeSubtree')
			eval(child.getAttribute('name')+'(child.firstChild)');
		else if(nodeName=='insertion'){
			var container=$(child.getAttribute('receiver'));
			container.innerHTML=AjaxGetInnerText(child);
		}
		else
			alert('Nom de requête inconnue: '+AjaxGetNodeXml(child));
		child=child.nextSibling;
	}
}


if(!Array.prototype.push)
{
	var push = 
		function()
		{
			for( var i = 0; arguments[ i ]!=null; i++ )
				this[this.length++] = arguments[ i ];
			return this;
		}
	Array.prototype.push = push;
}

function $() 
{
	var elements = new Array();

	for (var i = 0; i < arguments.length; i++) 
	{
		var element = arguments[i];
		if (typeof element == 'string')
			element = document.getElementById(element);

		if (arguments.length == 1)
			return element;

		elements.push(element);
	}
	return elements;
}


function ShowHideObj(obj,vis)
{
	var objStyle=obj.style;
	if(vis)
	{
		objStyle.visibility="visible";
		objStyle.display="block";
	}
	else
	{
		objStyle.visibility="hidden";
		objStyle.display="none";
	}
}

function FormSerialize(formName)
{
	var sFormData='';
	var oForm = $(formName);
	if(oForm)
		for(var i=0;i<oForm.elements.length;++i)
		{
			// note that we use escape instead of encodeURIComponent to work around an ASP anomaly
			var oElement=oForm.elements[i];
			var elName=oForm.elements[i].name;
			var elValue=oForm.elements[i].value;
			switch(oElement.type)
			{
				case 'select-multiple':
					for(var j=0;j<oElement.options.length;++j)
					{
						if(oElement.options[j].selected)
							sFormData+=escape(elName)+'='+escape(oElement.options[j].value)+'&';
					}
					break;
				case 'radio':
				case 'checkbox':
					if(oElement.checked)
						sFormData+=escape(elName)+'='+escape(elValue)+'&';
					break;
				case 'file':
					// stub case as XMLHttpRequest will only send the file path as a string.
					break;
				case 'undefined':
					// stub case for fieldset element which returns undefined.
					break;
				default:
					sFormData+=escape(elName)+'='+escape(elValue)+'&';
					break;
			}
		}
	return sFormData.substr(0,sFormData.length-1);
}

// work around a javascript crash bug in IE 5.01 because of asynchronous Ajax calls
var g_NoAsyncCalls=navigator.appName=='Microsoft Internet Explorer' && navigator.appVersion.indexOf('MSIE 5.0')>=0;

var AjaxRequester=
{
	MSXML_Progid:
	[
		'MSXML2.XMLHTTP.6.0',
		'MSXML2.XMLHTTP.5.0',
		'MSXML2.XMLHTTP.4.0',
		'MSXML2.XMLHTTP.3.0',
		'MSXML2.XMLHTTP',
		'Microsoft.XMLHTTP'
	],

	CreateXMLHttpRequest: function() 
	{
		// try the XMLHttpRequest first, since IE7 will incorporate it
		if(window.XMLHttpRequest)
			try 
			{ 
				return new XMLHttpRequest();
			} 
			catch (e) 
			{
			}
		if(window.ActiveXObject)
			for(var i=0; i<AjaxRequester.MSXML_Progid.length; ++i)
				try
				{
					return new ActiveXObject(AjaxRequester.MSXML_Progid[i]); 
				}
				catch(e)
				{
				}		
		alert("XMLHttpRequest not supported");
		return null;
	},
    
 
	EmptyFunction: function() 
	{
	},


	StatusOK: function(request)
	{
		if(request.status==200)
			return true;
		var str='';
		if(request.status==404)
			str="L'URL n'existe pas";
		else if(request.status==403)
			str='Accès interdit';
		else if(request.status==500)
		{
			str='Code erreur '+request.status;
			var response=request.responseText;
			if(response!=null && response.length>0)
			{
				response=response.replace(new RegExp('(?:<style.*?>)((\n|\r|.)*?)(?:<\/style>)','img'),'');	// strip style
				response=response.replace(new RegExp('(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)','img'),'');	// strip scripts
				response=response.replace(/<\/?[^>]+>/gi, '');	// strip tags
				str+=': '+response;
			}
		}
		else
			str='Code erreur '+request.status;
		alert(str);
		return false;
	},
	

	DoReadyStateChange: function(request,context)
	{
		context.onComplete(request);
	},


	OnReadyStateChange: function(context)
	{
		var request=context.request;
		// [0='Uninitialized', 1='Loading', 2='Loaded', 3='Interactive', 4='Complete'];			
		if(request.readyState<4)
			return;
		if(request.readyState==4)
		{
			if(this.StatusOK(request))
			{
				this.DoReadyStateChange(request,context);
				request.onreadystatechange=AjaxRequester.EmptyFunction;	// avoid memory leak in IE
				this.ajaxReady=true;
			}
		}
		context=null;
	},


	SendRequest: function(req,url,options,isAsync)
	{
		if(options.parameters)
		{
			if(url.indexOf('?')<0)
				url+='?';
			else
				url+='&';
			url+=options.parameters;
		}
		req.open("GET",url,isAsync);
		req.send(null);		
	},

	    
	DoRequest: function(url,options,isAsync)
	{
		var req=this.CreateXMLHttpRequest();

		if(isAsync)
			req.onreadystatechange=
				function()
				{
					AjaxRequester.OnReadyStateChange(context);
				}
					
		var context=
		{
			request: req,
			onComplete: options.onComplete
		};
		this.SendRequest(req,url,options,isAsync);
		if(!isAsync)
			this.DoReadyStateChange(req,context);
	},


	Request: function(url,options)
	{
	    this.ajaxReady=false;
		this.DoRequest(url,options,!g_NoAsyncCalls);
	},

	DoUpdaterStateChange: function(request,context)
	{
		var response=request.responseText;
		if(context.opts.insertion)
			context.opts.insertion(context.receiver,response);
		else
			context.receiver.innerHTML=response;
		if(context.opts.onComplete)
			context.opts.onComplete();
	},

	
	OnUpdaterStateChange: function(context)
	{
		var request=context.request;
		// [0='Uninitialized', 1='Loading', 2='Loaded', 3='Interactive', 4='Complete'];			
		if(request.readyState<4)
			return;
		if(request.readyState==4)
		{
			if(this.StatusOK(request))
			{
				this.DoUpdaterStateChange(request,context);
				request.onreadystatechange=AjaxRequester.EmptyFunction;	// avoid memory leak in IE
				this.ajaxReady=true;
			}
		}
		context=null;
	},
	

	DoUpdater: function(container,url,options,isAsync)
	{		
		var req=this.CreateXMLHttpRequest();

		if(isAsync)
			req.onreadystatechange=
				function()
				{
					AjaxRequester.OnUpdaterStateChange(context);
				}
					
		var context=
		{
			request: req,
			opts: options,
			receiver: $(container)
		};
		
		this.SendRequest(req,url,options,isAsync);
		
		if(!isAsync)
			this.DoUpdaterStateChange(req,context);
	},	

	
	Updater: function(container,url,options)
	{
	    this.ajaxReady=false;
		this.DoUpdater(container,url,options,!g_NoAsyncCalls);
	}	
}

function getDimension(d){

	if (!d) return 0;
	return parseInt(d);
}

var loadingShowed = false;

function loading(showDiv, smallIcon)
{
	var el = document.getElementById('loading');
	if (showDiv)
	{
		loadingShowed = true;
		var img = document.getElementById('loadingImg');
		if (smallIcon) img.src = 'img/loading_small.gif';
		else img.src = 'img/loading.gif';
		var x,y;
	
		if (self.innerHeight) // all except Explorer
		{
			x = self.innerWidth;
			y = self.innerHeight;
		}
		else if (document.documentElement && document.documentElement.clientHeight) // Explorer 6 Strict Mode
		{
			x = document.documentElement.clientWidth;
			y = document.documentElement.clientHeight;
		}
		else if (document.body) // other Explorers
		{
			x = document.body.clientWidth;
			y = document.body.clientHeight;
		}  

		var scrollTop = getDimension(document.documentElement.scrollTop);
		el.style.top = (((y - getDimension(el.style.height) - 20)/2) + scrollTop) + 'px';   
		el.style.left = (x - getDimension(el.style.width))/2 + 'px';
		el.style.display='block';
	}
	else
	{
		loadingShowed = false;
		el.style.display = 'none';
	}
}

function deleteContent(content){
	while(content.firstChild!=null)
		content.removeChild(content.firstChild);		
}

function clearLoading(){
	loading(false, false);
}

function hoverOver(element){
	element.className=element.className+'Hover';
}

function hoverOut(element){
	var className=element.className;
	className=className.substr(0,className.length-5)//Hover = 5 chars
	element.className=className;
}

function trim(str){
	return str.replace(/^\s*|\s*$/g,"");
}

function autoTab(item,next,datePart)
{
	var maxLength=item.getAttribute("maxlength");
	if(item.value.length==maxLength)
	{	
		var expr;
		if(datePart=="day")
			expr=/^[0-3][0-9]$/;
		else if(datePart=="month")
			expr=/^[0-1][0-9]$/;
		else
			expr=/^\d{4}$/;
			
		var datefields=item.value.match(expr);
		if(datefields!=null) {
			if(datePart=="day" && datefields>31)
				return;
			else if(datePart=="month" && datefields>12)
				return;
			if(next != null)
			{
				next.focus();
				next.select();
			}
		}
	}
}