/*
Copyright (c) 2008, PMP Concept
version: 1
*/

/*****************************************************************************
 *
 * 								Objet PMP
 *
 *	Fonction
 *
 *		L'objet PMP est un objet global dont la fonction est la gestion des
 *		différentes classes JavaScript de la librairie PMP.
 *
 *****************************************************************************/

// L'objet global PMP.

if (typeof PMP == "undefined") 
{
    /***
     * 
	 *	Si l'objet PMP existe il sera écrasé de sorte que le namespace soit
     	préservé															 *
     																	     *
																		   ***/
	var PMP = { 
		version:"1.0",

		browser: 
		{
			IE:     !!(window.attachEvent && !window.opera),
			Opera:  !!window.opera,
			WebKit: navigator.userAgent.indexOf('AppleWebKit/') > -1,
			Gecko:  navigator.userAgent.indexOf('Gecko') > -1 && navigator.userAgent.indexOf('KHTML') == -1,
			MobileSafari: !!navigator.userAgent.match(/Apple.*Mobile.*Safari/),

			strictMode: (document.documentElement && document.documentElement.scrollTop || document.compatMode && document.compatMode != "BackCompat" ? true : false)
		}
	 };
}



/***
 * 
 * 	Retourne le namespace spécifié et le crée s'il n'existe pas
 *
 * 	Attention aux mots réservés lors de la définition d'un espace de noms
 *
 *
 *	Paramètres
 * 		arguments : (String*) espace de nom à créer
 *	
 *	Retourne une reference (Object) sur le dernier espace de nom crée		 *
     																	     *
																		   ***/
PMP.namespace = function() 
{
    var arg = arguments;	// récupère la liste des arguments passés en paramètres
	var o=null, i, j, d;
	
    for (i=0; i<arg.length; i++)
	{
        d=arg[i].split(".");
        o=PMP;

        // PMP est implicite donc ignoré si passé en paramètre
        for (j=(d[0] == "PMP") ? 1 : 0; j<d.length; j++) 
		{
            o[d[j]]=o[d[j]] || {};
            o=o[d[j]];
        }
    }

    return o;
};



/***
 * 
 * 	Initialisation de l'objet global PMP									 *
     																	     *
																		   ***/
PMP.init = function() 
{
	// création du namespace "util" pour les classes
    this.namespace("util");

	// création du namespace "com" pour les composants
    this.namespace("com");

	// chemins des scripts
	this.pathracine = "/";
	this.pathlib = "";
	this.pmplib = "";
	this.ajaxURL = "";
	
	//context d'exécution
	this.context = {};
	this.context.ajax = false;	
	this.context.currentModule = false;
	this.context.currentModuleConf = "";
	this.context.parentModule = false;
	this.context.subDomain = false;
	this.context.backoffice = false;
	
	// récupération du script actuel
	var script = PMP.dom.getElementByAttribute("script", "src", /pmp\.js(\?.*)?$/);
	if(script)
	{
		// chemin par défaut des librairies;
		this.pmplib = script.src.replace(/pmp\.js(\?.*)?$/,'');
		this.pathlib = this.pmplib.replace(/librairiesjs\/?$/,'');
		this.ajaxURL = this.pathlib.replace(/_library\/_scripts\/?$/,'_ajax/alias_back.php');
		// récupération des paramètres passés dans l'url
		var parameters = PMP.url.getParameters(script.src);
		for(var param in parameters)
		{
			switch(param)
			{
				case "load":
					var extensions = parameters[param].split(",");
					for(var iExtention=0; iExtention<extensions.length; iExtention++)
					{
						PMP.common.include("librairiesjs/"+extensions[iExtention].trim()+".js");
					}
					break;
	
				case "pathracine":
					this.pathracine = parameters.pathracine;
					break;

				case "pathlib":
					this.pathlib = parameters.pathlib;
					break;

				case "ajaxURL":
					this.ajaxURL = parameters.ajaxURL;
					break;

				case "ajax":
					if(parseInt(parameters.ajax)==1)
						this.context.ajax = true;
					break;
	
				case "currentModule":
					if(parameters.currentModule)
						this.context.currentModule = parameters.currentModule;
					break;
	
				case "currentModuleConf":
					if(parameters.currentModuleConf)
						this.context.currentModuleConf = parameters.currentModuleConf;
					break;
	
				case "parentModule":
					if(parameters.parentModule)
						this.context.parentModule = parameters.parentModule;
					break;
	
				case "subDomain":
					if(parameters.subDomain)
						this.context.subDomain = parameters.subDomain;
					break;
	
				case "backoffice":
					if(parseInt(parameters.backoffice)==1)
						this.context.backoffice = true;
					break;
	
				default:
					//this[param] = parameters[param];
					break;
			}
		}
	}

	this.pmplib = this.pathlib+"librairiesjs/";
};



/***
 * 
 * 	Fournie les fonctions générales	de la librarie PMP						 *
     																	     *
																		   ***/
PMP.common = {
        
    // Détermine si l'objet envoyé en paramère n'est pas défini
    isUndefined: function(obj) 
	{
        return typeof obj == 'undefined';
    },
    
	// Détermine si l'objet envoyé en paramère est un tableau
    isArray: function(obj)
	{ 
		if(PMP.common.isUndefined(obj))
			return false;

		if (obj && obj.constructor && 
                   obj.constructor.toString().indexOf('Array') > -1) 
		{
            return true;
        } 
		else
		{
            return PMP.common.isObject(obj) && obj.constructor == Array;
        }
    },

    // Détermine si l'objet envoyé en paramère est un booléen
    isBoolean: function(obj)
	{
        if(PMP.common.isUndefined(obj))
			return false;

		return typeof obj == 'boolean';
    },
    
    // Détermine si l'objet envoyé en paramère est une fonction
    isFunction: function(obj)
	{
        if(PMP.common.isUndefined(obj))
			return false;

		return typeof obj == 'function';
    },
        
    // Détermine si l'objet envoyé en paramère est null
    isNull: function(obj)
	{
        return obj === null;
    },
        
    // Détermine si l'objet envoyé en paramère est un nombre
    isNumber: function(obj) 
	{
        if(PMP.common.isUndefined(obj))
			return false;
		
		obj = +obj; //parseInt(obj);
		return typeof obj == 'number' && isFinite(obj);
    },
      
    // Détermine si l'objet envoyé en paramère est un objet ou une fonction
    isObject: function(obj)
	{
        if(PMP.common.isUndefined(obj))
			return false;

		return obj && (typeof obj == 'object' || PMP.common.isFunction(obj));
    },
        
    // Détermine si l'objet envoyé en paramère est une chaine
    isString: function(obj) 
	{
        if(PMP.common.isUndefined(obj))
			return false;

		return typeof obj == 'string';
    },
    
    // Détermine si l'objet envoyé en paramère est un evenement
    isEvent: function(obj) 
	{
        if(PMP.common.isUndefined(obj))
			return false;

		if (obj && obj.constructor && 
                   obj.constructor.toString().indexOf('Event') > -1) 
		{
            return true;
        } 
		else
		{
            //return PMP.common.isObject(obj) && obj.constructor == Event;
			return true;
        }
    },
        
    // Détermine si l'objet a une propriété ou non
    hasOwnProperty: function(obj, prop) 
	{
        if (Object.prototype.hasOwnProperty) {
            return obj.hasOwnProperty(prop);
        }
        
        return !PMP.common.isUndefined(obj[prop]) && 
                obj.constructor.prototype[prop] !== obj[prop];
    },
        
    
   /***
	* 
 	* 	Définit le prototype, le constructeur et la superclasse pour gérer
    * 	un héritage qui permet de chainer les constructeurs et methodes.
    *	
	*	Paramètres
	* 		subclass : 		(Function) L'objet à modifier
    * 		superclass :	(Function) L'objet parent
    *		overrides :		(Object) propriétés/methodes supplémentaire à 
							ajouter au proptotype.  
							Les propriétés/methodes définies ici remplace 
							les propriétés/methodes de la superclasse		 *
     																	     *
																		   ***/
    extend: function(subclass, superclass, overrides) 
	{
        if (!superclass||!subclass) 
		{
            throw new Error("PMP.common.extend : echec, vérifier les paramètres.");
        }
        
		var F = function() {};
        F.prototype = superclass.prototype;
        subclass.prototype = new F();
        subclass.prototype.constructor = subclass;
        subclass.baseConstructor = superclass;
  		subclass.superclass = superclass.prototype;

        if (superclass.prototype.constructor == Object.prototype.constructor) 
		{
            superclass.prototype.constructor = superclass;
        }
    	
        if (overrides)
		{
            for (var i in overrides)
			{
                subclass.prototype[i] = overrides[i];
            }
        }
    },
	
	
	
	/***
	* 
 	* 	Inclut un fichier JavaScript s'il n'est pas déjà présent.
    *	
	*	Paramètres
	* 		file : 		(String) Le nom du ficher à inclure				 	
	* 		path : 		(String) Le repertoire du ficher à inclure			*
     																	    *
																		  ***/
    include: function (file) 
	{
		// liste ordonnée de chargement des scripts pour éviter les conflits (tiniMCE, script.aculo.us)
		var orderedScripts = new Array( 	"prototype.js",			// librairie de base pour scriptaculous
											"tiny_mce.js",			// declaration du tinyMCE
											"scriptaculous.js",		// librairie d'effets scriptaculous
											"basic_config.js.php", 	// initialisation du tinyMCE  
											"notification.js" 		// affichage des notifications 
											);
				
		var script = PMP.dom.getElementByAttribute("script", "src", file);
		// vérification de l'existance de ce fichier
		if(script)
			return;
		
		var nextScriptElement = null;
		var isOrderedScript = false;
		var scripts = document.getElementsByTagName('script');
		//récupération de l'indice de l'élément dans le tableau ordonné
		for (var iOrder=0; iOrder<orderedScripts.length; iOrder++)
		{
			if( file.search(orderedScripts[iOrder]) > -1 )
			{
				isOrderedScript = true;
			}
			else if(isOrderedScript)
			{
				// recherche le premier élément script suivant
				for (i=0; i<scripts.length; i++)
				{
					//alert(scripts[i].src + ", " + orderedScripts[iOrder] + " = " + scripts[i].src.search(orderedScripts[iOrder]));
					if( scripts[i].src && scripts[i].src.search(orderedScripts[iOrder])>-1 )
					{
						nextScriptElement = scripts[i];
						break;
					}
				}
			}

			if(nextScriptElement)
				break;
		}

		var scriptElement = document.createElement('script');
		scriptElement.setAttribute('type','text/javascript');
		scriptElement.setAttribute('language','javascript');
		//var path = !PMP.common.isNull(path) ? PMP.pathlib+path+file : PMP.pmplib+file;
		var path = PMP.pathlib+file;
		//alert(head + ", " + path);
		scriptElement.setAttribute('src',path);

		if(PMP.browser.IE)
		{
			document.write('<script type="text/javascript" src="'+path+'"><\/script>');
			return;
		}
		else
		{
			if(nextScriptElement)
				PMP.dom.insertBefore(scriptElement, nextScriptElement, head);
			else
			{
				var head = document.getElementsByTagName('head')[[0]];
				head.appendChild(scriptElement);
			}
		}
	},
	
	
	
	/***
	* 
 	* 	Retourn le body du document.
    *																		 *
     																	     *
																		   ***/
   	truebody : function (obj)
   	{
		//return (!window.opera && document.compatMode && document.compatMode!="BackCompat")? document.documentElement : document.body
		if(obj)
		{
			if(obj.document)
				obj = obj.document;
		}
		else
			var obj = document;

		return obj.documentElement && PMP.browser.strictMode ? obj.documentElement : obj.body;
	},


	autoSize : function(obj) 
	{
		var obj = PMP.dom.getElement(obj);
	
		if(!obj)
			return;
		
		var height = 0;
		var width = 0;
			
		if(obj.nodeName == "IFRAME")
		{
			if(obj.contentDocument)
			{
				var iframeDoc = obj.contentDocument;
			}
			else if(obj.contentWindow)
			{
				var iframeDoc = obj.contentWindow;
			}
			else
			{
				iframeDoc = obj.document;
			}

			if(iframeDoc.document)
				iframeDoc = iframeDoc.document;
			
			iframeDocBody = iframeDoc.body; //PMP.common.truebody(iframeDoc);
			if(iframeDocBody)
			{
				if(iframeDocBody.scrollHeight>height)
					height = iframeDocBody.scrollHeight;
				if(iframeDocBody.scrollWidth>width)
					width = iframeDocBody.scrollWidth;
			}
	
			iframeDocContentDocument = iframeDoc.documentElement; //PMP.common.truebody(iframeDoc);
			if(iframeDocContentDocument)
			{
				if(iframeDocContentDocument.scrollHeight>height)
					height = iframeDocContentDocument.scrollHeight;
				if(iframeDocContentDocument.scrollWidth>width)
					width = iframeDocContentDocument.scrollWidth;
			}
			
			iframeDocHtml = iframeDoc.getElementsByTagName("html")[0];
			if(iframeDocHtml)
			{
				if(iframeDocHtml.scrollHeight>height)
					height = iframeDocHtml.scrollHeight;
				if(iframeDocHtml.scrollWidth>width)
					width = iframeDocHtml.scrollWidth;
		
				//iframeDocHtml.style.height = '100%';
				//iframeDocHtml.style.width = '100%';
			}
		}
		else
		{
			if(obj.scrollHeight>height)
				height = obj.scrollHeight;
			if(obj.scrollWidth>width)
				width = obj.scrollWidth;
		}
		
		if(height>0 && width>0)
		{
			obj.style.height = height + 'px';
			obj.style.width = width + 'px';
		}
	},
	
	
	/***
	* 
 	* 	Retourn la position top d'un élément.
    *																		 *
     																	     *
																		   ***/
   	getElementTop : function (element, parent)
   	{
		var elemTop = 0;
		if(!PMP.common.isUndefined(parent))
			parent = PMP.dom.getElement(parent);
		else
			var parent = null;

		if(element)
		{
			elemTop = element.offsetTop;
			tempEl = element.offsetParent;
			while (tempEl != parent && tempEl!=null) 
			{
				elemTop += tempEl.offsetTop;
				tempEl = tempEl.offsetParent;
			}
		}
		
		return elemTop;
	},
	
	
	/***
	* 
 	* 	Retourn la position left d'un élément.
    *																		 *
     																	     *
																		   ***/
   getElementLeft : function (element, parent)
   	{
		var elemLeft = 0;
		if(!PMP.common.isUndefined(parent))
			parent = PMP.dom.getElement(parent);
		else
			var parent = null;

		if(element)
		{
			elemLeft = element.offsetLeft;
			tempEl = element.offsetParent;
			while (tempEl != parent && tempEl!=null) 
			{
				elemLeft += tempEl.offsetLeft;
				tempEl = tempEl.offsetParent;
			}
		}
			
		return elemLeft;
	},
	
	
	/***
	* 
 	* 	Retourne la largeur visible d'un élément.
    *																		 *
     																	     *
																		   ***/
	getElementWidth : function (element, strict)
   	{
		var element = PMP.dom.getElement(element);

		if(!element)
			return 0;

		if(!PMP.common.isBoolean(strict))
			var strict = false;

		return strict ? element.clientWidth : element.offsetWidth;
	},
	
	
	/***
	* 
 	* 	Retourne la hauteur visible d'un élément.
    *																		 *
     																	     *
																		   ***/
	getElementHeight : function (element, strict)
   	{
		var element = PMP.dom.getElement(element);

		if(!element)
			return 0;

		if(!PMP.common.isBoolean(strict))
			var strict = false;

		return strict ? element.clientHeight : element.offsetHeight;
	},
	
	
	/***
	* 
 	* 	Retourne la largeur totale du contenu d'un élément.
    *																		 *
     																	     *
																		   ***/
	getContentWidth : function (element)
   	{
		var element = PMP.dom.getElement(element);

		return element ? (element.scrollWidth > element.offsetWidth ? element.scrollWidth : element.offsetWidth) : 0;
	},
	
	
	/***
	* 
 	* 	Retourne la hauteur totale du contenu d'un élément.
    *																		 *
     																	     *
																		   ***/
	getContentHeight : function (element)
   	{
		var element = PMP.dom.getElement(element);
		
		//if(element && PMP.common.truebody(element))
		//	element =  PMP.common.truebody(element);
		
		//INFOS HEIGHT
		//alert('Window: '+window.innerHeight + '\ndocumentElement.clientHeight: ' +document.documentElement.clientHeight+ '\ndocumentElement.offsetHeight: '+document.documentElement.offsetHeight+'\ndocumentElement.scrollHeight : '+document.documentElement.scrollHeight+'\nbody.clientHeight: '+document.body.clientHeight+'\nbody.offsetHeight'+document.body.offsetHeight+'\nbody.scrollHeight: '+document.body.scrollHeight);
		
		return element ? (element.scrollHeight > element.offsetHeight ? element.scrollHeight : element.offsetHeight) : 0;
	},
	
	
	/***
	* 
 	* 	Retourne les propriétés de la fenetre du navigateur.
    *																		 *
     																	     *
																		   ***/
	getWindowProperties : function (property)
   	{
		if(!PMP.common.isString(property))
			var property = "";

		var properties = new Object();

		if(self.innerWidth) // tout navigateur sauf IE
		{
			properties.innerWidth = self.innerWidth;
			properties.innerHeight = self.innerHeight;
			properties.scrollLeft = self.pageXOffset;
			properties.scrollTop = self.pageYOffset;
		}
		else if(window.innerWidth)
		{
			properties.innerWidth = window.innerWidth;
			properties.innerHeight = window.innerHeight;
			properties.scrollLeft = window.pageXOffset;
			properties.scrollTop = window.pageYOffset;
		}
		else if(document.documentElement && document.documentElement.clientWidth) // navigateur avec DOCTYPE valid : IE6 Strict Mode
		{
			properties.innerWidth = document.documentElement.clientWidth;
			properties.innerHeight = document.documentElement.clientHeight;
			properties.scrollLeft = document.documentElement.scrollLeft;
			properties.scrollTop = document.documentElement.scrollTop;
		}
		else if(document.body) // autre navigateur à défaut
		{
			properties.innerWidth = document.body.clientWidth;
			properties.innerHeight = document.body.clientHeight;
			properties.scrollLeft = document.body.scrollLeft;
			properties.scrollTop = document.body.scrollTop;
		}

		// correction de la taille de la fenêtre pour tenir compte des scrollbars
		if(properties.innerWidth)
			properties.innerWidth -= 16;
		if(properties.innerHeight)
			properties.innerHeight -= 10;

		if(property!="")
			return properties[property];
		else
			return properties;
	},
	
	
	/***
	* 
 	* 	Retourne la position left d'un élément.
    *																		 *
     																	     *
																		   ***/
	horizontalCenter : function (element)
   	{
		var windowProperties = PMP.common.getWindowProperties();
	
		var element = PMP.dom.getElement(element);
		if(element)
		{
			var innerWidth = windowProperties.innerWidth;
			var left = (innerWidth - element.offsetWidth)/2 + windowProperties.scrollLeft;
			if(left<0)
				element.style.left = 0 + "px";
			else if(left+element.offsetWidth > PMP.common.getContentWidth(PMP.common.truebody()))
				element.style.left = PMP.common.getContentWidth(PMP.common.truebody()) - element.offsetWidth + "px";
			else
				element.style.left = left + "px";
		}
	},
	
	
	/***
	* 
 	* 	Retourn la position left d'un élément.
    *																		 *
     																	     *
																		   ***/
	verticalCenter : function (element)
   	{
		var windowProperties = PMP.common.getWindowProperties();
	
		var element = PMP.dom.getElement(element);
		if(element)
		{
			var innerHeight = windowProperties.innerHeight;
			
			var top = (innerHeight - element.offsetHeight)/2 + windowProperties.scrollTop;
			
			if(top<0)
				element.style.top = 0 + "px";
			else if(top + element.offsetHeight > PMP.common.getContentHeight(PMP.common.truebody()))
				element.style.top = PMP.common.getContentHeight(PMP.common.truebody()) - element.offsetHeight + "px";
			else
				element.style.top = top + "px";
		}
	},
	
	
	/***
	* 
 	* 	Retourn le noeud courant lors de l'execution d'une page.
    *																		 *
     																	     *
																		   ***/
   getCurrentNode : function (node)
   	{
		if( this.isUndefined(node) )
			var node = document.lastChild;
		
		while (node && node.nodeType != 1)
		{
			if(node.previousSibling)
				node = node.previousSibling;
			else
				break;
		}
		
		if( node.nodeType == 1 )
			return this.getCurrentNode(node.lastChild) || node;
			
		return false;
	},
	
	
	/***
	* 
 	* 	serialise un tableau, object, ... pour communication avec php.
    *																		 *
     																	     *
																		   ***/
   serialize : function (txt)
   {
		switch(typeof(txt))
		{
			case 'string':
				return 's:'+txt.length+':"'+txt+'";';
			case 'number':
				if(txt>=0 && String(txt).indexOf('.') == -1 && txt < 65536) return 'i:'+txt+';';
				return 'd:'+txt+';';
			case 'boolean':
				return 'b:'+( (txt)?'1':'0' )+';';
			case 'object':
				var i=0,k,ret='';
				for(k in txt){
					//alert(isNaN(k));
					if(!isNaN(k)) k = Number(k);
					ret += this.serialize(k) + this.serialize(txt[k]);
					i++;
				}
				return 'a:'+i+':{'+ret+'}';
			default:
				return 'N;';
				alert('var undefined: '+typeof(txt));return undefined;
		}
	},
	
	
	/***
	* 
 	* 	déserialise une chaine pour communication avec php.
    *																		 *
     																	     *
																		   ***/
   unserialize : function (txt)
   {
		var level=0,arrlen=new Array(), del=0, final=new Array(), key=new Array(), save=txt;

		while(1)
		{
			switch(txt.substr(0,1))
			{
				case 'N':
					del = 2;
					ret = null;
				break;
				case 'b':
					del = txt.indexOf(';')+1;
					ret = (txt.substring(2,del-1) == '1')?true:false;
				break;
				case 'i':
					del = txt.indexOf(';')+1;
					ret = Number(txt.substring(2,del-1));
				break;
				case 'd':
					del = txt.indexOf(';')+1;
					ret = Number(txt.substring(2,del-1));
				break;
				case 's':
					del = txt.substr(2,txt.substr(2).indexOf(':'));
					ret = txt.substr( 1+txt.indexOf('"'),del);
					del = txt.indexOf('"')+ 1 + ret.length + 2;
				break;
				case 'a':
					del = txt.indexOf(':{')+2;
					ret = new Array();
					arrlen[level+1] = Number(txt.substring(txt.indexOf(':')+1, del-2))*2;
				break;
				case 'O':
					txt = txt.substr(2);
					var tmp = txt.indexOf(':"')+2;
					var nlen = Number(txt.substring(0, txt.indexOf(':')));
					name = txt.substring(tmp, tmp+nlen );
					//alert(name);
					txt = txt.substring(tmp+nlen+2);
					del = txt.indexOf(':{')+2;
					ret = new Object();
					arrlen[level+1] = Number(txt.substring(0, del-2))*2;
				break;
				case '}':
					txt = txt.substr(1);
					if(arrlen[level] != 0){alert('var missed : '+save); return undefined;};
					//alert(arrlen[level]);
					level--;
				continue;
				default:
					if(level==0) return final;
					alert('syntax invalid(1) : '+save+"\nat\n"+txt+"level is at "+level);
					return undefined;
			}

			if(arrlen[level]%2 == 0)
			{
				if(typeof(ret) == 'object'){alert('array index object no accepted : '+save);return undefined;}
				if(ret == undefined){alert('syntax invalid(2) : '+save);return undefined;}
				key[level] = ret;
			} 
			else
			{
				var ev = '';
				for(var i=1;i<=level;i++){
					if(typeof(key[i]) == 'number'){
						ev += '['+key[i]+']';
					}else{
						ev += '["'+key[i]+'"]';
					}
				}
				eval('final'+ev+'= ret;');
			}

			arrlen[level]--;//alert(arrlen[level]-1);

			if(typeof(ret) == 'object')
				level++;

			txt = txt.substr(del);
			continue;
		}
	}
	
}



/***
 * 
 *	Extention dom :
 * 
 * 	Fournie les fonctions de gestion des éléments du DOM					*
     																	    *
																		  ***/
PMP.dom = 
{
    // récupère un élément dans le DOM
    getElement: function(element, parent)
	{ 
		if(PMP.common.isUndefined(parent) || PMP.common.isNull(parent))
			parent = document;
		else
		{
			parent = PMP.dom.getElement(parent);
			
			if(!parent)
				return null;

			if(parent.nodeName == "IFRAME")
			{
				if(parent.contentDocument)
				{
					var parent = parent.contentDocument;
				}
				else if(parent.contentWindow)
				{
					var parent = parent.contentWindow;
				}
				else
				{
					parent = parent.document;
				}
	
				if(parent.document)
					parent = parent.document;
			}
		}
			
		if(PMP.common.isString(element))
		{
			var elementStr = element;

			element = parent.getElementById(elementStr);
		
			if(!element && document.all)
				element = document.all[elementStr];
			
			if(!element)
			{
				element = top.frames[element];
				/*
				var frames = window.frames; // or // var frames = window.parent.frames;
				for (var i = 0; i < frames.length; i++)
				{ 
					alert(PMP.debug.trace(frames[i]));
				}
				*/
			}
		}

		return element;
    },

	// récupère la propriété d'un élément dans le DOM
    getElementProperty: function(element, property, parentObj)
	{ 
		if(PMP.common.isUndefined(property))
			return undefined;

		element = PMP.dom.getElement(element, parentObj);
		return element ? eval("element."+property) : undefined;
    },

	// assigne la propriété d'un élément dans le DOM
    setElementProperty: function(element, property, value, parentObj)
	{ 
		if(PMP.common.isUndefined(property) || PMP.common.isUndefined(value))
			return false;

		element = PMP.dom.getElement(element, parentObj);
		
		if(!element)
			return false;

		
		//element[property] = value;

		// découpage de la propriété pour gérer les sous propriétés (ex: "style.display")
		properties = property.split(".");
		for(var i=0; i<properties.length; i++)
		{
			if(!element)
				break;
			
			if(i==properties.length-1)
			{
				element[properties[i]] = value;
				break;
			}
			else
				element = element[properties[i]];
		}
    },

	// assigne la propriété d'un élément dans le DOM
    setElementsProperty: function(elements, property, value, parentObj)
	{ 
		if(!PMP.common.isArray(elements))
			return false;

		for(var i=0; i<elements.length; i++)
		{
			PMP.dom.setElementProperty(elements[i], property, value, parentObj);	
		}
    },

	// masque les éléments à partir d'un id
    hideElementsByTagName: function(tagname,from)
	{ 
		if(tagname==null)
			return;
		
		if(PMP.common.isUndefined(from))
			var fromNode = document;
		else
		{
			if(PMP.common.isString(from))
				fromNode = document.getElementById(from);
			else
				fromNode = from;
		}

		if(!fromNode)
			return;

		var elements = fromNode.getElementsByTagName(tagname);
		
		for (i = 0; i < elements.length; i++)
			elements[i].style.visibility = 'hidden';
    },

	// affiche les éléments
    showElementsByTagName: function(tagname,from)
	{ 
		if(tagname==null)
			return;
		
		if(PMP.common.isUndefined(from))
			var fromNode = document;
		else
		{
			if(PMP.common.isString(from))
				fromNode = document.getElementById(from);
			else
				fromNode = from;
		}

		if(!fromNode)
			return;

		var elements = fromNode.getElementsByTagName(tagname);
		
		for (i = 0; i < elements.length; i++)
			elements[i].style.visibility = 'visible';
    },

	// récupère le noeud enfant DOM à la position 'index' dans la liste des enfants de node
    getChildAt: function(node, index, nodeType)
	{ 
		node = PMP.dom.getElement(node);
		// par défaut on récupère le noeud de type élément à l'index donné
		if(PMP.common.isUndefined(nodeType))
			var nodeType = 1;

		if(!PMP.common.isNumber(index) || index>=node.childNodes.length)
			return null;

		var node = node.firstChild;
		var iChild=0;
		while (node!=null) 
		{
			// si le type de noeud ne correspond pas à celui recherché
			if(PMP.common.isNumber(nodeType) && node.nodeType!=nodeType)
			{
				node = node.nextSibling;
				continue;
			}

			//vérification de l'indice
			if(iChild==index)
				return node;	
			
			node = node.nextSibling;
			iChild ++;
		}
		return node;
		
    },

	// récupère le noeud suivant correspondant au nom passé en paramètre
    nextItem : function(item, nodeName) 
	{
		if (item == null) return
		var next = item.nextSibling
		while (next != null) {
			if (next.nodeName == nodeName) return next
			next = next.nextSibling
		}
		return null
	},

	// récupère le noeud précédant correspondant au nom passé en paramètre
    previousItem : function(item, nodeName) 
	{
		var previous = item.previousSibling;
		while (previous != null) 
		{
			if (previous.nodeName == nodeName) 
				return previous;
			previous = previous.previousSibling;
		}
		return null;
	},

	// insère un noeud juste avant le noeux passé en paramètre
    insertBefore : function(item1, item2, parent) 
	{
		if(!item2)
			return;
		var parent = item2.parentNode;
		parent.insertBefore(item1, item2);
	},

	// insère un noeud juste après le noeux passé en paramètre
    insertAfter : function(item1, item2) 
	{
		if(!item2)
			return;
		var parent = item2.parentNode;
		parent.insertBefore(item1, item2 ? item2.nextSibling : null);
	},

	moveBefore : function(item1, item2) 
	{
		var parent = item1.parentNode;
		parent.removeChild(item1);
		parent.insertBefore(item1, item2);
	},

	moveAfter : function(item1, item2) 
	{
		var parent = item1.parentNode;
		parent.removeChild(item1);
		parent.insertBefore(item1, item2 ? item2.nextSibling : null);
	},
	
	getElementsByMaskId : function(maskId, type) //maskId : masque, exemple='photo[%i][ordre]'
	{
		var maskStr = maskId;
		
		maskStr = maskStr.replace(/\[/g,"\\[");
		maskStr = maskStr.replace(/\]/g,"\\]");
		maskStr = maskStr.replace(/%i/g,"\\d+");
		maskStr = maskStr.replace(/%s/g,"\\w+");
		
		regexp = new RegExp(maskStr);
		
		var foundElements = new Array();
		elements = document.getElementsByTagName(type);
		for(iElem=0; iElem<elements.length; iElem++)
		{
			var idStr = elements[iElem].id;
			
			if(!idStr)
				continue;
			
			if( idStr.search(regexp)>=0 )
			{
				foundElements.push(elements[iElem]);
			}
		}
		
		return foundElements;
		
	},
	
	getElementByMaskId : function(maskId, type) //maskId : masque, exemple='photo[%i][ordre]'
	{
		var maskStr = maskId;
		
		maskStr = maskStr.replace(/\[/g,"\\[");
		maskStr = maskStr.replace(/\]/g,"\\]");
		maskStr = maskStr.replace(/%i/g,"\\d+");
		maskStr = maskStr.replace(/%s/g,"\\w+");
		
		regexp = new RegExp(maskStr);
		
		var foundElements = new Array();
		elements = document.getElementsByTagName(type);
		for(iElem=0; iElem<elements.length; iElem++)
		{
			var idStr = elements[iElem].id;
			
			if(!idStr)
				continue;
			
			if( idStr.search(regexp)>=0 )
			{
				foundElements.push(elements[iElem]);
			}
		}
		
		return foundElements;
		
	},
	
	getElementByAttribute : function(tagname, attribute, value)
	{
		if(PMP.common.isUndefined(tagname) || PMP.common.isUndefined(attribute) || PMP.common.isUndefined(value))
			return null;

		var elements = document.getElementsByTagName("html")[0].getElementsByTagName(tagname);
		for(var iElement=0; iElement<elements.length; iElement++)
		{
			var element = elements[iElement];
			if(element && element[attribute] && element[attribute].search(value)>-1)
			{
				return element;
				break;
			}
		}

		return null;
	}
};



/***
 * 
 *	Extention url :
 * 
 * 	Fournie les fonctions de gestion de l'url								*
     																	    *
																		  ***/
PMP.url = 
{
    // récupère les paramètres de l'url
    getParameters: function (url) 
	{
		if(PMP.common.isUndefined(url))
			var url = window.location.href;

		var queryString = url.match(/\?(.*)/);
		queryString = queryString ? queryString[1] : "";
		var parametersCouple = queryString.split('&');
		var parameters = new Object();
		for(var i=0; i<parametersCouple.length; i++)
		{
			var parameter = parametersCouple[i].split('=');
			if(parameter.length > 1)
				parameters[parameter[0]] = parameter[1];
		}
		return parameters;
	},
	
    // récupère un paramètres de l'url
    getParameter: function (param, url) 
	{
		if(PMP.common.isUndefined(param))
			return "";

		if(PMP.common.isUndefined(url))
			var url = window.location.href;

		var parameters = PMP.url.getParameters(url);
		
		return !PMP.common.isUndefined(parameters[param]) ? parameters[param] : "";
	},
	
    // réécriture de l'url
    rewrite: function (params, url, context) 
	{
		if(!PMP.common.isBoolean(context))
			context = true;

		if(!PMP.common.isObject(params) && !context)
			return url;

		if(!PMP.common.isObject(params))
			params = {};

		// ajout du context d'exécution
		if(context)
		{
			if(PMP.context.ajax)
				params["ajax"] = 1;

			if(PMP.context.parentModule)
				params["parentModule"] = PMP.context.parentModule;

			if(PMP.context.currentModule)
				params["currentModule"] = PMP.context.currentModule;

			if(PMP.context.subDomain)
				params["subDomain"] = PMP.context.subDomain;
	
			if(PMP.context.backoffice)
				params["backoffice"] = 1;
		}

		if(PMP.common.isUndefined(url))
			var url = window.location.href;

		var parameters = PMP.url.getParameters(url);
		for(var param in params)
			parameters[param] = params[param];

		url = url.replace(/\?(.*)$/, "");
		
		var queryString = "";
		for(var param in parameters)
		{
			if(queryString!="")
				queryString += "&";

			queryString += param+"="+parameters[param];
		}

		url += "?"+queryString;

		return url;
	}
};






/***
 * 
 * 	Fournie les fonctions de gestion de debug 								 *
     																	     *
																		   ***/
PMP.debug = 
{
    // affiche en détail le contenu d'une variable
    trace: function (obj) 
	{
		if(typeof obj == "object") 
		{
			var proprietes = "";
			for (var i in obj)
				proprietes += i+" = "+obj[i]+"\n";
			
			return "Type\n"+typeof(obj)+"\n\nValue\n" + proprietes;
		} 
		else
		{
			return "Type: "+typeof(obj)+"\nValue: "+obj;
		}
	}
};






/***
 * 
 * 	Fournie les fonctions de gestion des chaines de caractères				 *
     																	     *
																		   ***/
PMP.string = 
{
  	format: {
		decimal:',',
		centaine:'.'
	}
};




/***
 * 
 * 	Surcharge des fonctions javascript pour permettre leur exécution en
	concervant leur context
	ex : exécuter une méthode d'un object au déclenchement d'un évenement 
		 tout en concervant le contexte d'exécution de l'obet en question	*
     																	    *
																		  ***/
Function.prototype.bind = function (object)
{
    var __method = this;
    
	if (arguments.length < 2 && PMP.common.isUndefined(arguments[0]))
		return __method;

	var object = arguments[0];
	var args = [];
	for(var i=1; i<arguments.length; i++)
		args.push(arguments[i]);
	
	return function () 
	{
		return __method.apply(object, args);
    };
}


/***
 * 
 * 	Surcharge du type String												*
     																	    *
																		  ***/
String.prototype.ltrim = function()
{
	var str = this;

	var regExpBeginning = /^\s+/;
	str = str.replace(regExpBeginning, "");

	// suppression du bit d'identification du codage UTF8, UTF16-BE ou UTF16-LE
	str = str.replace(String.fromCharCode(65279), "");

	return str;
};

String.prototype.rtrim = function()
{
	var str = this;

	var regExpEnd = /\s+$/;
	str = str.replace(regExpEnd, "");

	// suppression du bit d'identification du codage UTF8, UTF16-BE ou UTF16-LE
	str = str.replace(String.fromCharCode(65279), "");

	return str;
};

String.prototype.trim = function()
{
	var str = this;
	
	return str.ltrim().rtrim();
};

String.prototype.cleanWhiteSpace = function()
{
	var str = this;
	var regExpLineBreak       = /\r\n/g;
	var regExpWhiteSpace      = />\s+</g;
	
	str = str.replace(regExpLineBreak, "");
	str = str.replace(regExpWhiteSpace, "><");

	return str;
}

String.repeat = function(i, m) { for (var o = []; m > 0; o[--m] = i); return(o.join('')); }

String.sprintf = function()
{
	var i = 0, a, f = arguments[i++], o = [], m, p, c, x;
	while (f) 
	{
		if (m = /^[^\x25]+/.exec(f)) o.push(m[0]);
		else if (m = /^\x25{2}/.exec(f)) o.push('%');
		else if (m = /^\x25(?:(\d+)\$)?(\+)?(0|'[^$])?(-)?(\d+)?(?:\.(\d+))?([b-fosuxX])/.exec(f)) 
		{
			if (((a = arguments[m[1] || i++]) == null) || (a == undefined)) 
				throw("Too few arguments.");
			if (/[^s]/.test(m[7]) && (typeof(a) != 'number'))
				throw("Expecting number but found " + typeof(a));
			switch (m[7]) 
			{
				case 'b': a = a.toString(2); break;
				case 'c': a = String.fromCharCode(a); break;
				case 'd': a = parseInt(a); break;
				case 'e': a = m[6] ? a.toExponential(m[6]) : a.toExponential(); break;
				case 'f': a = m[6] ? parseFloat(a).toFixed(m[6]) : parseFloat(a); break;
				case 'o': a = a.toString(8); break;
				case 's': a = ((a = String(a)) && m[6] ? a.substring(0, m[6]) : a); break;
				case 'u': a = Math.abs(a); break;
				case 'x': a = a.toString(16); break;
				case 'X': a = a.toString(16).toUpperCase(); break;
			}
			a = (/[def]/.test(m[7]) && m[2] && a > 0 ? '+' + a : a);
			c = m[3] ? m[3] == '0' ? '0' : m[3].charAt(1) : ' ';
			x = m[5] - String(a).length;
			p = m[5] ? String.repeat(c, x) : '';
			o.push(m[4] ? a + p : p + a);
		}
		else throw ("Huh ?!");
		f = f.substring(m[0].length);
	}
	return o.join('');
}

String.format = function(string, format) 
{ 
	if(!PMP.common.isString(string) && !PMP.common.isNumber(string))
		string = "";

	switch(format)
	{
		case "url":
			if(string.search(/^http:\/\//) < 0)
				string = 'http://'+string;
			else
				string = string.replace(/^(http:\/\/)+/,"http://");
			break;
			
		case "number":
			var precision = String.format.arguments.length>2 && PMP.common.isNumber(String.format.arguments[2]) ? String.format.arguments[2] : 2;

			nombre = parseFloat(string);
			
			if( !PMP.common.isNumber(nombre) )
				nombre = 0;
			
			// si le nombre de décimales passé en paramètre est valide
			if (precision != null)
			{
				nombre = nombre.toFixed(precision);
			}
			
			// on récupère le signe du nombre
			var sign = nombre < 0 ? "-" : "";
			
			// on récupère la partie entière du nombre
			var entiere = (nombre > 0 ? Math.floor(nombre) : Math.abs(Math.ceil(nombre))).toString();
			
			// on récupère la partie decimale du nombre
			var decimale = nombre.toString().substring (entiere.length + sign.length);
			
			// on définit le séparateur: celui passé en paramètre s'il est valide sinon '.' par défaut
			decimale = PMP.common.isNumber(precision) && precision > 0 || decimale.length > 1 ? (PMP.string.format.decimal + decimale.substring (1)) : "";
			
			// si le nombre de décimal est inférieur à precision on ajoute des 0
			if (PMP.common.isNumber(precision) && precision > 0)
			{
				for (i = decimale.length - 1, z = precision; i < z; ++i)
					decimale += "0";
			}
			
			if ((PMP.string.format.centaine != PMP.string.format.decimal || decimale.length == 0) && PMP.string.format.centaine != "")
			{
				for (i = entiere.length - 3; i > 0; i -= 3)
					entiere = entiere.substring (0 , i) + PMP.string.format.centaine + entiere.substring (i);
			}
			
			string = sign + entiere + decimale;
			break;
			
		default:
			break;
	}

	return string;
}



/***
 * 
 * 	Surcharge du type Element												*
     																	    *
																		  ***/
/*
Element.prototype.hide = function()
{
	this.style.display = "none";
}

Element.prototype.show = function()
{
	this.style.display = "";
}

Element.prototype.sizeToContent = function()
{
	alert("sizeToContent");
	this.style.width = "auto";
	this.style.height = "auto";
}
*/


/***
 * 
 * 	Alias de fonctions														*
     																	    *
																		  ***/
// alias de la fonction extend
PMP.extend = PMP.common.extend;

// alias de la fonction include
PMP.include = PMP.common.include;



// Initialisation de l'objet PMP
PMP.init();