/**
 * Net-Createurs simple library
		(string).trim			makes a L/R trim on the string xxxxxx
		
		browserInfo				Browser detection, returns Array[which->browser, majVersion->:main version, touchPad-> nothing, 'iPhone' or 'iPad' }
		NC.tools. :
		getStyle(obj)			Returns the computed styles of the object
		getCSSpointer(cssname)	Returns a pointer to a classname, in order to change its content dynamically
		center(obj)				Centers the object on the screen
		objSize(obj)			Returns the size W/H of the object, even if it is set to display:none
		returnXY(obj)			Returns absolute X and Y positions of obj in the window
		addLoadEvent(func)		Adds func to the onload document event list, preserving existing functions if any	

 */


/* Détection du navigateur utilisé...
On utilise la chaine retournée par navigator.userAgent :
IE5.5 (IE tester)	: Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.1; SV1; Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1) ; InfoPath.2; .NET CLR 1.1.4322)  
IE6 (vrai)			: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1) ; InfoPath.2; .NET CLR 1.1.4322)
IE7 (IE tester)		: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; SV1; Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1) ; InfoPath.2; .NET CLR 1.1.4322)  
IE8					: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0; slcc1; .net clr 2.0.50727; etc.)
FF 3.x				: Mozilla/5.0 (Windows; U; Windows NT 5.1; fr; rv:1.9.1.3) Gecko/20090824 Firefox/3.5.3
Opera 10			: Opera/9.80 (Windows NT 5.1; U; fr) Presto/2.2.15 Version/10.10
Safari 3 PC			: Mozilla/5.0 (Windows; U; Windows NT 5.1; fr-FR) AppleWebKit/525.28 (KHTML, like Gecko) Version/3.2.2 Safari/525.28.1
Chrome				: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/532.0 (KHTML, like Gecko) Chrome/3.0.195.38 Safari/532.0
iPhone				: mozilla/5.0 (iPhone; u; cpu iphone OS 3_1_2 like mac os x; fr-fr) applewebkit/528.18 (KHTML, like Gecko) version/4.0 mobile/7d11 safari/528.16
iPad (source Apple)	: Mozilla/5.0 (iPad; U; CPU OS 3_2 like Mac OS X; en-us) AppleWebKit/531.21.10 (KHTML, like Gecko) Version/4.0.4 Mobile/7B334b Safari/531.21.10
Positionne :	nc_nav -> array which='', IE, FF, OP, SA, CH
				majVersion = 0 si nav inconnu, ou nr de version majeur (1, 2, 3 etc.) du navigateur
				iPhone = true/false
*/

var	nc_nav={ which:'', majVersion:0, touchPad:'' },
	x=navigator.userAgent.toLowerCase(),
	isIE=x.indexOf('msie '),
	isFF=x.indexOf('firefox/'),
	isOP=x.substring(0,6)=='opera/',
	isCH=x.indexOf('chrome/'),
	isSA=(isCH==-1? x.indexOf('safari/') : -1);	// Chrome signe Chrome ET Safari
if(x.indexOf('iphone;')!=-1) nc_nav['touchPad']='iPhone';
else if(x.indexOf('ipad;')!=-1) nc_nav['touchPad']='iPad';
if(isSA!=-1 || isOP) voffset=x.indexOf('version/');
if(isIE!=-1) { nc_nav['which']='IE'; nc_nav['majVersion']=parseInt(x.substring(isIE+5)) }
else if(isFF!=-1) { nc_nav['which']='FF'; nc_nav['majVersion']=parseInt(x.substring(isFF+8)) }
else if(isOP) { nc_nav['which']='OP'; nc_nav['majVersion']=parseInt(x.substring(voffset+8)) }
else if(isSA!=-1) { nc_nav['which']='SA'; nc_nav['majVersion']=parseInt(x.substring(voffset+8)) }
else if(isCH!=-1) { nc_nav['which']='CH'; nc_nav['majVersion']=parseInt(x.substring(isCH+7)) };

// L/R trim. Usage = xxxxx.trim()
String.prototype.trim = function() { return this.replace(/^\s+|\s+$/g,"") };


if(typeof(NC)=='undefined') NC={};
NC.tools= {

	// =================================================
	// Lecture dynamique des style CSS réels (calculés) d'un objet
	// obj = ID de l'objet, ou objet lui même
	getStyle:function(obj) {
		if(typeof(obj)=='string') obj=document.getElementById(obj);
		return typeof obj.currentStyle=='undefined' ?
	  	  document.defaultView.getComputedStyle(obj, null)		// tous les navigateurs sauf IE
	  	: obj.currentStyle;										// IE
	},


	// =================================================
	// Centrage de l'objet "obj" à l'écran, obj peut être l'ID de l'objet à centrer, ou l'objet lui même
	// Rattache automatiquement l'objet à la racine du document, afin d'obtenir un centrage correct
	// Utilise objSize
	center:function(obj) {
		if(typeof(obj)=='string') obj=document.getElementById(obj);
		if(obj) {
			if(obj.parentNode.tagName!='BODY') document.body.appendChild(obj);	// rattache l'objet à la racine du body
			if(obj.style.position!='absolute') obj.style.position='absolute';
			var size=this.objSize(obj),										// Dimensions de l'objet à centrer
				win=this.winInfo();											// et celles de l'écran
			obj.style.left=win.left+Math.round((win.width-size.width)/2)+'px';		// Centrage X
			obj.style.top=win.top+Math.round((win.height-size.height)/2)+'px';		// Centrage Y
		}
		return false;
	},


	/* =================================================
	 * Retourne un tableau avec des infos sur la fenêtre : [width] / [height] = largeur / hauteur visible du document, [left) / [top] = offset left et top,
	 * [totalWidth] / [totalHeight] = largeur / hauteur totale du document
	 */
	winInfo:function() {
		var	n=navigator.userAgent.toLowerCase(),
			doc=document.compatMode && document.compatMode=="BackCompat" ? document.body : document.documentElement,
			doc1=n.indexOf("safari")>-1 ? document.body : doc;			// Forcage obligatoire avec Safari PC jusque version 4 incluse
		return { width:doc.clientWidth, height:doc.clientHeight, left:doc1.scrollLeft, top:doc1.scrollTop,
			totalHeight:Math.max(doc1.scrollHeight,doc.clientHeight), totalWidth:Math.max(doc1.scrollWidth,doc.clientWidth) }
	},

	// =================================================
	// Retourne la taille X / Y de l'objet obj, qui peut être l'ID d'un objet ou l'objet lui même
	objSize:function(obj) {
		if(typeof(obj)=='string') obj=document.getElementById(obj);
		if(obj) { this.makeReal(obj,1); ret= { width:obj.offsetWidth, height:obj.offsetHeight }; this.makeReal(obj,0) }
		else ret= {width:0, height:0 };
		return ret;
	},

	// =================================================
	// Retourne la position X/Y absolue de l'objet X dans la fenêtre
	// Remonte l'arborescence des nodes container pour ajouter les offset des <div> quand c'est nécessaire
	// X peut être l'id de l'objet, ou l'objet lui même (détection auto)
	// Problèmes :
	//	-	Bug IE6/7 avec les <div> relative. S'ils sont dans un <td> centré verticalement, IE6/7 ajoute 2 fois la marge du haut dûe au centrage
	//		la variable last_h permet de corriger cette erreur. A voir selon les montages...
	//	-	Bug tous : avec les <div> static. Leur position X/Y ne doit pas être prise en compte s'ils sont suivis d'un div autre que absolu
	getXY:function(obj) {
		var	nav=navigator.userAgent.toLowerCase(),isIE=nav.indexOf('msie '),ielower=isIE!=-1 && parseInt(nav.substring(isIE+5),10)<8,
			x0=0, y0=0;
		if(typeof(obj)=='string') obj=document.getElementById(obj);
		if(obj) {
			var x0=obj.offsetLeft, y0=obj.offsetTop, x1, y1,prevpos, thispos='',last_h=0;
			while(obj.parentNode && obj.parentNode.tagName!='BODY') {
				obj=obj.parentNode;
				if(obj.tagName=='DIV') {
					x1=typeof(obj.offsetLeft)=='number' ? obj.offsetLeft : 0;
					y1=typeof(obj.offsetTop)=='number' ? obj.offsetTop : 0;
					prevpos=thispos;
					thispos=typeof(document.defaultView)=='undefined' ?		// IE 6/7. Ne pas tester sur currentStyle car Opera10 le reconnait
						obj.currentStyle.position : document.defaultView.getComputedStyle(obj, null).position;

					switch(thispos) {
					case 'static':
						if(prevpos && prevpos!='absolute') { x1=0; y1=0 }
						else if(!prevpos && !ielower)  { x1=0; y1=0 };		// Chablais, sauf le ielower (IE 6/7) -> pages modèle marchands PP
						break;
					case 'relative':
						if(ielower) {
							h=this.getStyle(obj)['height'];
							if(h!='auto') last_h=parseInt(h,10);
						}
						break;
					}
					x0+=x1; y0+=y1;
				}
				else if(obj.tagName=='TD') {
					if(ielower && last_h) {y0-=obj.offsetHeight-last_h; last_h=0 };		// bug IE6/IE7
				}
			}
		}
		return {x:x0, y:y0 };
	},


	// =================================================
	// Multiple onload function created by: Simon Willison
	// http://simonwillison.net/2004/May/26/addLoadEvent/
	// usage : NC.tools.addLoadEvent( function() {fct_name()} )
	addLoadEvent:function(func) {
		var oldonload = window.onload;
		if (typeof window.onload != 'function') { window.onload = func; }
		else {
			window.onload = function() {
				if (oldonload) { oldonload(); }
				func();
			}
		}
	},

	// Multiple onresize function
	// if onscroll=true -> funciton will be lauched at each body scroll, too (used for rough on screen auto-center)
	addResizeEvent:function(func,onscroll) {
		var oldonresize = window.onresize;
		if (typeof window.onresize != 'function') { window.onresize = func; }
		else {
			window.onresize = function() {
				if (oldonresize) { oldonresize(); }
				func();
			}
		}
		if(typeof(onscroll)!='undefined' && onscroll) this.addScrollEvent(func);
	},

	// Multiple onscroll function
	addScrollEvent:function(func) {
		var oldonscroll = window.onscroll;
		if (typeof window.onscroll != 'function') { window.onscroll = func; }
		else {
			window.onscroll = function() {
				if (oldonscroll) { oldonscroll(); }
				func();
			}
		}
	},


	// =================================================
	// Parse an object SRC
	parseSRC:function(obj) {
		var ret={ path:'', fullname:'', name:'', extension:'' };
		if(typeof(obj)=='string') obj=document.getElementById(obj);
		if(obj.src) {
			var x=obj.src.split('/');
			ret.fullname=x.pop();
			ret.path=x.join('/') + (x.length ? '/' : '');
			x=ret.fullname.split('.');
			ret.extension=x.length ? x.pop() : '';
			ret.name=x.join('.');
		}
		return ret;
	},

	// =================================================
	// verify an email address, return true if address OK, or false otherwise
	emailCheck:function(email) {
		var email_addressRegxp = /^[!#-?A-~]+@([-_a-z0-9]{2,}\.)?[-_a-z0-9]{2,}(\.[a-z0-9]{2,4}){1,2}$/i;
		return email_addressRegxp.test(email);
	},

	// =================================================
	// verify a URL, return true if address OK, or false otherwise
	urlCheck:function(url) {
		var url_addressRegxp = /^(http(s)?:\/\/)?([-_a-z0-9]{2,}\.)?[-_a-z0-9]{2,}(\.[a-z0-9]{2,4}){1,2}$|(\.[a-z0-9]{2,4}){1,2}(\/[\x20-\x7E]+)*$/i;
		return url_addressRegxp.test(url) && !(/"/.test(url));
	},


	// *************** COOKIE MANAGEMENT ************************ //
	
	// Read cookie "name"
	getCookie:function(name) {
		var cookie='', i=document.cookie.indexOf(name+"="), content='';
		if (i>-1) {
			var	j=document.cookie.indexOf(';',i+name.length+1);
			if(j==-1) j=document.cookie.length;
			content=document.cookie.substring(i+name.length+1,j);
		}
		return content;
	},


	/* Store/delete a cookie
	 * Params = {name,value,expires,path,domain,secure}
	 * path -> nothing (= '/') or '/xxxxx' = from where this cookie will be visible
	 * value = content of the cookie, unescaped, or nothing -> delete the cookie
	 * expires : nothing -> cookie is deleted when the browser is closed, or numeric value -> seconds before the cookie dies
	 * domain = nothing or '.mydomain.com' for subdomains (to verify)
	 * secure -> true -> the cookie can only be used from a SSL server (https://etc.)
	 * Only the name is required. If value='' -> delete the cookie 'name', if such
	 * MAX	- total cookies on a browser = 300
	 *		- total cookies from one server or domain = 20
	 * 		- cookie size = 4KB 
	 */
	storeCookie:function(params) {
		if(params['expires']) {
			var expire = new Date();
			expire.setTime(expire.getTime() + (params['expires']*1000));
			params['expires'] = expire.toGMTString();
		}
		document.cookie=
			  params['name'] + '='
			+ (params['value'] ?
				  escape(params['value']) + (params['expires'] ? '; expires=' + params['expires'] : '')
				: '; expires=Thu, 01-Jan-70 00:00:01 GMT')
			+ '; path=' + (params['path'] ? params['path'] : '/')
			+ (params['domain'] ? '; domain=' + params['domain'] : '')
			+ (params['secure'] ? '; secure' : '')
		;
	},



	// *************** CLASSES MANAGEMENT ************************ //

	// Retourne un pointeur vers la classe cssname si elle existe, ou null sinon
	// Permet de modifier une classe CSS globale document, par exemple : sfa_css['paddingLeft']='8px'
	getCSSpointer:function(cssname) {
		var i=0,CSStab=new Array(),sfa_css=null,css='';
		if(document.styleSheets) do {
			css=typeof(document.styleSheets[i]);
			if(css!='undefined' && css!='unknown') {
				css=document.styleSheets[i];
				if (css.rules) CSStab=document.styleSheets[i].rules;				// IE
				else if(css.cssRules) CSStab=document.styleSheets[i].cssRules;	// Le rese
				else CSStab=new Array();
				for(var j in CSStab) if(CSStab[j].selectorText=='.'+cssname) sfa_css=CSStab[j]['style']; //;for(var k in sfa_css) alert(k +' -> '+sfa_css[k]) }
				// cssText = chaine de texte du style (PADDING-RIGHT : 8px) ou paddingRight=8px
				i++;
			}
			else css='';
		} while(css && sfa_css==null);
		return sfa_css;
	},

	// Change oldclass with newclass. If no new, remove the old one. If no old, adds the new one at the end.
	changeClass:function(object, newclass, oldclass) {
		if(typeof(object)=='string') object=document.getElementById(object);
		if(object) {
			var classes=object.className.split(' '),
				result='';
				if(typeof(oldclass)=='undefined') var oldclass='';
			for(var i in classes) {
				if(classes[i]) {
					if(classes[i]==oldclass) classes[i]=newclass;
					else if(classes[i]==newclass) {
						if(oldclass) classes[i]='';
						else newclass='';
					}
				}
			}
			if(newclass && !oldclass) classes[i+1]=newclass;
			for(var i in classes) result+=' ' + classes[i];
			object.className=result.trim();
		}

	},

	// return an array of ressources towards each docuyment's object using theclass
	searchClass:function(theclass) { return this.searchClassBrowse(theclass, new Array(), document.body); },

	searchClassBrowse:function(theclass,result,obj) {
		var i, thisclass;
		if(obj.nodeType!=3 && obj.className) {		// 3 = 'undefined' ( text content ? )
			thisclass=obj.className.split(' ');
			for(i in thisclass) if(thisclass[i]==theclass) result[result.length]=obj;
		}
		var child=obj.childNodes;
		for(i=0;i<child.length;i++) result=this.searchClassBrowse(theclass,result,child[i]);
		return result;
	},


	
	// ********** BASIC VISUAL EFFECTS ( alpha fade, color morph ***************** //

	// =================================================
	// alpha fade in /out. Params : id, [from], to, [step], [display block (default) or inline)], [delay]
	fademem: new Array(),

	fade:function(params) {
		var object=document.getElementById(params['id']),alpha;
		if(object) {

			// clear any previous fadein/out on this object
			if(this.fademem[params.id]) clearTimeout(this.fademem[params.id]);

			// calculate object start opacity
			var style=this.getStyle(object),
				display=style.display;
			if(params.from || params.from=='0') alpha=params.from;
			else {
				if(display=='none') alpha=0;
				else {
					if(style.opacity!='' && style.opacity!='undefined') var alpha=style.opacity*100;
					else if(style.filter && style.filter!='undefined') {
						var i=style.filter.indexOf('opacity=');
						if(i>-1) alpha=parseInt(style.filter.substring(i+8),10);
					}
					else alpha=100;
				}
			}

			// calculate object end opacity
			if(params.to<0) params.to=0; else if(params.to>100) params.to=100;

			// calculate actual step
			if(!params.step) params.step=34;		// fast animation
			params.step=Math.abs(params.step);
			if(params.to<alpha) params.step=-params.step;

			// launch fadein/out
			setTimeout(
				(display=='none' ?
					  "document.getElementById('"+params['id']+"').style.display='"
					+ (params['display'] ? params['display'] : 'inline')
					+ "';" : '')
				+ "NC.tools.alphaStep('" + params.id + "'," + alpha + "," + params.to + "," + params.step + ")"
				,params['delay'] ? params['delay'] : 1);
		}
	},

	alphaStep:function(id,alpha,target,step) {
		var object=document.getElementById(id);
		if(alpha<target && step<0) alpha0=target; else if(alpha>target && step>0) alpha0=target; else alpha0=alpha;
		object.style.opacity=alpha0/100;
		object.style.filter='alpha(opacity=' + alpha0 + ')';
		if(alpha==alpha0 && alpha!=target) this.fademem[id]=setTimeout("NC.tools.alphaStep('" + id + "'," + (alpha+step) + "," + target + "," + step + ")", 50);
		else {
			this.fademem[id]=false;
			if(alpha0==0) object.style.display='none';
		} 
	},


	/* Color morphing effect, from actual color to target color.
	 * Params	color = target color to go to, can be #RRGGBB, #RGB, rgb(r,g,b) or rgba(r, g, b, a)
	 *			what = what to change : 'color' (default if not specified), or 'backgroundColor'
 	 *			duration = morphing duration in msec (default = 1000)
	 */
	changeRGB:function(obj, params, isnext) {
		if(typeof(obj)=='string') obj=document.getElementById(obj);
		if(obj) {
			if(!obj.id) obj.id='fx-changeRGB-'+this.changeRGB_memo.length;
			var objID=obj.id;
			if(typeof(isnext)=='undefined' || !isnext) {
				// init of a new cycle
				if(!params.duration) params.duration=1000;
				if(!params.what) params.what='color';
				var	style=NC.tools.getStyle(obj);
				this.changeRGB_memo[objID]={
					start:this.readColor(style[params.what]),
					end:this.readColor(params.color),
					step:1,
					stepNb:Math.round(params.duration/50),
					timeout:false,
					what:params.what
				};
			}
			if(this.changeRGB_memo[objID]['timeout']) clearTimeout(this.changeRGB_memo[objID]['timeout']);
			var percent=this.changeRGB_memo[objID]['step']++/this.changeRGB_memo[objID]['stepNb'];
			r='#';
			for(var i=0;i<5;i+=2) r+=this.toHex(Math.floor(
				parseInt(this.changeRGB_memo[objID]['start'].substr(i,2),16)*(1-percent)
			  + parseInt(this.changeRGB_memo[objID]['end'].substr(i,2),16)*percent
			));
			obj.style[this.changeRGB_memo[objID]['what']]=r;
			if(percent<1) this.changeRGB_memo[objID]['timeout']=setTimeout("NC.tools.changeRGB('" + objID + "',Array(),1)",50);
			else this.changeRGB_memo[objID]['timeout']=false;
		}
	},
	changeRGB_memo: new Array(),


	/* **************** internal only entries, do not use externaly ******************** */
	hexa:new Array(0,1,2,3,4,5,6,7,8,9,'A','B','C','D','E','F'),
	toHex:function(dec) {	// Decimal to hexa conversion
		if (dec < 0) return('00');
		else if (dec > 255) return('FF');
		else return new String(this.hexa[Math.floor(dec/16)]) + new String(this.hexa[Math.floor(dec%16)]);
	},
	readColor:function(color) {	// Returns a color (#rgb or #rrggbb or color(r,g,b) as rrggbb
		if(color=='transparent') color='#fff';
		if(color.substring(0, 4)=="rgba") {		// Safari 5 : RGB + alpha
			eval('var rgb=new Array' + color.substring(4));
			if(!rgb[3]) color="#ffffff";
			else color="#" + this.toHex(rgb[0]) + this.toHex(rgb[1]) + this.toHex(rgb[2]);
		}
		else if(color.substring(0, 3)=="rgb") {		// Safari <5
			eval('var rgb=new Array' + color.substring(3));
			color="#" + this.toHex(rgb[0]) + this.toHex(rgb[1]) + this.toHex(rgb[2]);
		}
		else if(color.length == 4) color= 
			  "#" + color.substring(1, 2) + color.substring(1, 2)
			+ color.substring(2, 3) + color.substring(2, 3)
			+ color.substring(3, 4) + color.substring(3, 4);
		return color.substring(1);
	},



	// *************** PRIVATE FUNCTIONS ************************ //

	// Rend l'objet obj réel s'il est display:none, afin de pouvoir lire certaines de ses propiétés comme sa taille, ou de modifier les objets qu'il contient (IE6/7)
	// Appeler une fois avec cde=1 -> rend l'objet réel, puis avec cde=0 -> le replace dans son état d'origine
	// Attention avec IE6/7, si on rend un conteneur réel pour modifier un objet dedans il faut attendre ~300 msec avant de restituer l'état du conteneur 
	makeReal:function(obj,cde) {
		if(typeof(obj)=='string') obj=document.getElementById(obj);
		if(obj) {
			if(cde) {
				var style=this.getStyle(obj);
				if(style.display=='none') {
					obj.sf_changed=true;
					obj.sf_opacity=typeof(style.opacity)=='undefined' ? 0 : style.opacity;
					obj.sf_filter=typeof(style.filter)=='undefined'? '' : style.filter;
					obj.style.opacity=0; obj.style.filter='alpha(opacity=100)'; obj.style.display='block';
				}
				else obj.sf_changed=false;
			}
			else {
				var changed=obj.sf_changed;
				if(typeof(changed)!='undefined' && changed) {
					obj.style.display='none';
					obj.style.opacity=obj.sf_opacity;
					obj.style.filter=obj.sf_filter;
					obj.sf_changed=false;
				}
			}
		}
	}

}

