/**************************************************
 * dom-drag.js
 * 09.25.2001
 * www.youngpup.net
 **************************************************
 * 10.28.2001 - fixed minor bug where events
 * sometimes fired off the handle, not the root.
 **************************************************/

var Drag = {

    obj : null,

    init : function(o, oRoot, minX, maxX, minY, maxY, bSwapHorzRef, bSwapVertRef, fXMapper, fYMapper)
    {
        o.onmousedown    = Drag.start;

        o.hmode            = bSwapHorzRef ? false : true ;
        o.vmode            = bSwapVertRef ? false : true ;

        o.root = oRoot && oRoot != null ? oRoot : o ;

        if (o.hmode  && isNaN(parseInt(o.root.style.left  ))) o.root.style.left   = "0px";
        if (o.vmode  && isNaN(parseInt(o.root.style.top   ))) o.root.style.top    = "0px";
        if (!o.hmode && isNaN(parseInt(o.root.style.right ))) o.root.style.right  = "0px";
        if (!o.vmode && isNaN(parseInt(o.root.style.bottom))) o.root.style.bottom = "0px";

        o.minX    = typeof minX != 'undefined' ? minX : null;
        o.minY    = typeof minY != 'undefined' ? minY : null;
        o.maxX    = typeof maxX != 'undefined' ? maxX : null;
        o.maxY    = typeof maxY != 'undefined' ? maxY : null;

        o.xMapper = fXMapper ? fXMapper : null;
        o.yMapper = fYMapper ? fYMapper : null;

        o.root.onDragStart    = new Function();
        o.root.onDragEnd    = new Function();
        o.root.onDrag        = new Function();
    },

    start : function(e)
    {
        var o = Drag.obj = this;
        e = Drag.fixE(e);
        var y = parseInt(o.vmode ? o.root.style.top  : o.root.style.bottom);
        var x = parseInt(o.hmode ? o.root.style.left : o.root.style.right );
        o.root.onDragStart(x, y);

        o.lastMouseX    = e.clientX;
        o.lastMouseY    = e.clientY;

        if (o.hmode) {
            if (o.minX != null)    o.minMouseX    = e.clientX - x + o.minX;
            if (o.maxX != null)    o.maxMouseX    = o.minMouseX + o.maxX - o.minX;
        } else {
            if (o.minX != null) o.maxMouseX = -o.minX + e.clientX + x;
            if (o.maxX != null) o.minMouseX = -o.maxX + e.clientX + x;
        }

        if (o.vmode) {
            if (o.minY != null)    o.minMouseY    = e.clientY - y + o.minY;
            if (o.maxY != null)    o.maxMouseY    = o.minMouseY + o.maxY - o.minY;
        } else {
            if (o.minY != null) o.maxMouseY = -o.minY + e.clientY + y;
            if (o.maxY != null) o.minMouseY = -o.maxY + e.clientY + y;
        }

        document.onmousemove    = Drag.drag;
        document.onmouseup        = Drag.end;

        return false;
    },

    drag : function(e)
    {
        e = Drag.fixE(e);
        var o = Drag.obj;

        var ey    = e.clientY;
        var ex    = e.clientX;
        var y = parseInt(o.vmode ? o.root.style.top  : o.root.style.bottom);
        var x = parseInt(o.hmode ? o.root.style.left : o.root.style.right );
        var nx, ny;

        if (o.minX != null) ex = o.hmode ? Math.max(ex, o.minMouseX) : Math.min(ex, o.maxMouseX);
        if (o.maxX != null) ex = o.hmode ? Math.min(ex, o.maxMouseX) : Math.max(ex, o.minMouseX);
        if (o.minY != null) ey = o.vmode ? Math.max(ey, o.minMouseY) : Math.min(ey, o.maxMouseY);
        if (o.maxY != null) ey = o.vmode ? Math.min(ey, o.maxMouseY) : Math.max(ey, o.minMouseY);

        nx = x + ((ex - o.lastMouseX) * (o.hmode ? 1 : -1));
        ny = y + ((ey - o.lastMouseY) * (o.vmode ? 1 : -1));

        if (o.xMapper)        nx = o.xMapper(y)
        else if (o.yMapper)    ny = o.yMapper(x)

        Drag.obj.root.style[o.hmode ? "left" : "right"] = nx + "px";
        Drag.obj.root.style[o.vmode ? "top" : "bottom"] = ny + "px";
        Drag.obj.lastMouseX    = ex;
        Drag.obj.lastMouseY    = ey;

        Drag.obj.root.onDrag(nx, ny);
        return false;
    },

    end : function()
    {
        document.onmousemove = null;
        document.onmouseup   = null;
        Drag.obj.root.onDragEnd(    parseInt(Drag.obj.root.style[Drag.obj.hmode ? "left" : "right"]), 
                                    parseInt(Drag.obj.root.style[Drag.obj.vmode ? "top" : "bottom"]));
        Drag.obj = null;
    },

    fixE : function(e)
    {
        if (typeof e == 'undefined') e = window.event;
        if (typeof e.layerX == 'undefined') e.layerX = e.offsetX;
        if (typeof e.layerY == 'undefined') e.layerY = e.offsetY;
        return e;
    }
};
/**
*
*  Base64 encode / decode
*  http://www.webtoolkit.info/
*
**/

var Base64 = {

	// private property
	_keyStr : "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",

	// public method for encoding
	encode : function (input) {
		var output = "";
		var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
		var i = 0;

		input = Base64._utf8_encode(input);

		while (i < input.length) {

			chr1 = input.charCodeAt(i++);
			chr2 = input.charCodeAt(i++);
			chr3 = input.charCodeAt(i++);

			enc1 = chr1 >> 2;
			enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
			enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
			enc4 = chr3 & 63;

			if (isNaN(chr2)) {
				enc3 = enc4 = 64;
			} else if (isNaN(chr3)) {
				enc4 = 64;
			}

			output = output +
			this._keyStr.charAt(enc1) + this._keyStr.charAt(enc2) +
			this._keyStr.charAt(enc3) + this._keyStr.charAt(enc4);

		}

		return output;
	},

	// public method for decoding
	decode : function (input) {
		var output = "";
		var chr1, chr2, chr3;
		var enc1, enc2, enc3, enc4;
		var i = 0;

		input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");

		while (i < input.length) {

			enc1 = this._keyStr.indexOf(input.charAt(i++));
			enc2 = this._keyStr.indexOf(input.charAt(i++));
			enc3 = this._keyStr.indexOf(input.charAt(i++));
			enc4 = this._keyStr.indexOf(input.charAt(i++));

			chr1 = (enc1 << 2) | (enc2 >> 4);
			chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
			chr3 = ((enc3 & 3) << 6) | enc4;

			output = output + String.fromCharCode(chr1);

			if (enc3 != 64) {
				output = output + String.fromCharCode(chr2);
			}
			if (enc4 != 64) {
				output = output + String.fromCharCode(chr3);
			}

		}

		output = Base64._utf8_decode(output);

		return output;

	},

	// private method for UTF-8 encoding
	_utf8_encode : function (string) {
		string = string.replace(/\r\n/g,"\n");
		var utftext = "";

		for (var n = 0; n < string.length; n++) {

			var c = string.charCodeAt(n);

			if (c < 128) {
				utftext += String.fromCharCode(c);
			}
			else if((c > 127) && (c < 2048)) {
				utftext += String.fromCharCode((c >> 6) | 192);
				utftext += String.fromCharCode((c & 63) | 128);
			}
			else {
				utftext += String.fromCharCode((c >> 12) | 224);
				utftext += String.fromCharCode(((c >> 6) & 63) | 128);
				utftext += String.fromCharCode((c & 63) | 128);
			}

		}

		return utftext;
	},

	// private method for UTF-8 decoding
	_utf8_decode : function (utftext) {
		var string = "";
		var i = 0;
		var c = c1 = c2 = 0;

		while ( i < utftext.length ) {

			c = utftext.charCodeAt(i);

			if (c < 128) {
				string += String.fromCharCode(c);
				i++;
			}
			else if((c > 191) && (c < 224)) {
				c2 = utftext.charCodeAt(i+1);
				string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
				i += 2;
			}
			else {
				c2 = utftext.charCodeAt(i+1);
				c3 = utftext.charCodeAt(i+2);
				string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
				i += 3;
			}

		}

		return string;
	}

}//////////////////////////////////////////////////////////////////////////////////////////
/// AJOUT 2.5.3: Remise Ã  plat des fonctionnalitÃ©s AJAX
///		- Tentative d'homogÃ©nÃ©isation des fonctions
///		- Passage des valeurs en POST pour Ã©viter limitations de taille d'URL
///		- Utilisation de requÃªtes asynchrones
//////////////////////////////////////////////////////////////////////////////////////////

// Fonction getServerRequest
// ConservÃ©e par compatibilitÃ© avec l'existant (fonction du pagejs)
// Le paramÃ¨tre strHTTPMethod n'est pas pris en compte (on passe maintenant tout en POST)
function getServerRequest(strMethod, astrParams, strHTTPMethod) {
	return ajax_syncMethod(strMethod, astrParams);
}

// Fonction ajax_prepareContexte
// Renvoie un paramÃ¨tre Ã  ajouter au tableau de paramÃ¨tres, contenant tout le contexte de page pour un appel AJAX
function ajax_prepareContexte() {
	// Ajoute le contexte de page
	var strVals = '';
	for (i = 0; i < _aCtrls.length; i++) {
		var strIDCtrl = _aCtrls[i];
		var oCtrl = document.getElementById(strIDCtrl);
		if (oCtrl) {
			if (strVals) strVals += "&";
			strVals += strIDCtrl + "=" + oCtrl.value;
		} 			
	}

	for (i = 0; i < _aParams.length; i++) {
		var strParam = _aParams[i];
		var aCtrl = document.getElementsByName("__PageParam__" + strParam);
		if (aCtrl.length > 1) {
			for (iCtrl = 0; iCtrl < aCtrl.length; iCtrl ++) {
				var oCtrl = aCtrl[iCtrl];
				if (oCtrl) {
					if (strVals) strVals += "&";
					strVals += "__PageParam__" + strParam + "[]=" + oCtrl.value;
				}
			} 			
		}
		else {
			var oCtrl = aCtrl[0];
			if (oCtrl) {
				if (strVals) strVals += "&";
				strVals += "__PageParam__" + strParam + "=" + oCtrl.value;
			} 			
		}
	}
	
	// Ajoute aussi la liste des paramÃ¨tres de page
	if (strVals) strVals += "&";
	strVals += "__ParamsList" + "=" + document.getElementById("__ParamsList").value;
	
	// Renvoie le paramÃ¨tre Ã  ajouter au tableau
	return '__ajax:' + base64PSencode(strVals);
}


// Fonction ajax_prepareData
// Met en forme le tableau de paramÃ¨tre pour le passer Ã  la requÃªte AJAX
function ajax_prepareData(astrParams) {
	// Ajout des paramÃ¨tres
	var strParams = '';
	if (astrParams) {
		if (astrParams.toString()) {
			if (astrParams.toString().split(",")) {
			 	for(var i = 0; i < astrParams.toString().split(",").length; i++) {
			 		if (astrParams[i]) {
				 		// On regarde si c'est dÃ©jÃ  encodÃ©, si c'est le cas on n'encode pas
						if (strParams) strParams += '&';      
				 		
				 		if (astrParams[i].toString().indexOf("%") != -1) {
				 			strParams += 'params[]=' + astrParams[i];
						}
						else {
							strParams += 'params[]=' + escape(astrParams[i]);
						}
					}
					// Si la valeur du paramÃ¨tre est zÃ©ro :
					else {
						if (strParams) strParams += '&';      
						strParams += 'params[]=0';
					}
				}
			}
		}
	}
	return strParams;
}

// Fonction getAjaxRequest
// ConservÃ©e par compatibilitÃ© avec l'existant (fonction du pagejs)
// Passe une requÃªte en rajoutant le contexte de page dans les paramÃ¨tres
function ajax_asyncRequestWithContext(strMethod, astrParams, strDivID) {
	strURL = _strJSI + '&method=' + strMethod;

	// Ajoute un paramÃ¨tre de contexte Ã  la liste des paramÃ¨tres
	astrParams[astrParams.length] = ajax_prepareContexte();

	// PrÃ©pare les paramÃ¨tres	
	strParams = ajax_prepareData(astrParams);

	// ExÃ©cute la requÃªte avec un HTTP Request asynchrone
	ajax_asyncRequest(strURL, strParams, strDivID);
}


// Fonction ajax_asyncRequest
// Envoie une requÃªte ajax asynchrone et renvoie la rÃ©ponse dans la div dont l'ID est spÃ©cifiÃ©e
// Les donnÃ©es doivent Ãªtre URLEncodÃ©es
function ajax_asyncRequest(strURL, strData, strDivID, oContainer) {
	var xmlDoc = null;
	
	// SÃ©lection navigateur
 	if (typeof window.ActiveXObject != 'undefined' ) {
		xmlDoc = new ActiveXObject("Microsoft.XMLHTTP");
	}
	else {
		xmlDoc = new XMLHttpRequest();
	}

	xmlDoc.open("POST", strURL, true);	// Asynchrone
	
	// Fonction de callback dynamique
	xmlDoc.onreadystatechange = function() {
	    if (xmlDoc.readyState != 4) { return; }

	    // AJOUT 2.5.4: Si on a prÃ©cisÃ© un container (infobulle par exemple) alors on remplit et on resize
	    if (strDivID) {
		    var oDiv = document.getElementById(strDivID);
		    oDiv.innerHTML = xmlDoc.responseText;
		}
		else {
	    	oContainer.fill(xmlDoc.responseText);
	    	oContainer.move();
		}
	};
	
	// En-tÃªte pour les donnÃ©es envoyÃ©es en POST au format URLEncodÃ©		
	xmlDoc.setRequestHeader("Content-Type","application/x-www-form-urlencoded; charset=utf-8");
	
	// Envoie la requÃªte
	xmlDoc.send(strData);
}


// Fonction ajax_asyncRequest
// Envoie une requÃªte ajax synchrone
function ajax_syncRequest(strURL, strData) {
	if (! _bWorking) {
		startWorking();
		
		var xmlDoc = null;
		//if (!strMethod) strMethod = "GET";		// MODIF 2.4.3
	
	 	if (typeof window.ActiveXObject != 'undefined' ) {
			xmlDoc = new ActiveXObject("Microsoft.XMLHTTP");
		}
		else {
			xmlDoc = new XMLHttpRequest();
		}

		xmlDoc.open("POST", strURL, false);
		xmlDoc.setRequestHeader("Content-Type","application/x-www-form-urlencoded; charset=utf-8");
		xmlDoc.send(strData);
		
		stopWorking();
	
		if ( xmlDoc.readyState != 4 ) return ;
		
	    return xmlDoc.responseText;
	}
}


// Fonction ajax_asyncMethod
// Appel asynchrone d'une mÃ©thode en ajax
function ajax_asyncMethod(strMethod, astrParams, strDivID, oContainer) {
	strURL = _strJSI + '&method=' + strMethod;

	// PrÃ©pare les paramÃ¨tres	
	strParams = ajax_prepareData(astrParams);

	// ExÃ©cute la requÃªte avec un HTTP Request
	strResult = ajax_asyncRequest(strURL, strParams, strDivID, oContainer);
}

// Fonction ajax_syncMethod
// Appel synchrone d'une mÃ©thode en ajax
function ajax_syncMethod(strMethod, astrParams) {
	strURL = _strJSI + '&method=' + strMethod;

	// PrÃ©pare les paramÃ¨tres
	strParams = ajax_prepareData(astrParams);

	// ExÃ©cute la requÃªte avec un HTTP Request
	return ajax_syncRequest(strURL, strParams);
}

// Fonction ajax_getValue
// Code de rÃ©cupÃ©ration de la valeur instantanÃ©e cÃ´tÃ© client
function ajax_getValue(strID) {
	var oControl = document.getElementById(strID);
	
	// AJOUT 2.5.5: Gestion des radio buttons
	if (!oControl) {
	    // On est peut-Ãªtre dans le cas de radio button. Ce sont en fait des input diffÃ©rents
		// Avec un mÃªme name mais des id diffÃ©rents
		// Du coup on tente de travailler avec le name
		var aControls = document.getElementsByName(strID);
		// Retourne une concatÃ©nation (avec des ,) de toutes les valeurs qui sont checked
		var strReturn = '';
		for (var iCtrl =0; iCtrl < aControls.length; iCtrl ++) {
			var oControl = aControls[iCtrl];
			if (oControl.checked) {
				if (strReturn) strReturn += ',';
				strReturn += oControl.value;
			}
		}
		return strReturn;
	}
	else {
		if (oControl.tagName == 'SELECT') {
			return oControl.options[oControl.options.selectedIndex].value;
		}
		else {
			return oControl.value;
		}
	}
}
//////////////////////////////////////////////////////////////////////////////////////////
/// AJOUT 2.5.4: Gestion propre des infobulles
//////////////////////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////////////////////
// Classe Infobulle
//	- Permet de stocker les propriÃ©tÃ©s d'une infobulle
//////////////////////////////////////////////////////////////////////////////////////////
var Infobulle = function(iIndex, strID, bLockable) {
	this.index = iIndex;		// Indice de crÃ©ation de l'infobulle
	this.id = strID;			// identifiant unique de l'infobulle
	this.visible = false;		// VisibilitÃ©
	this.filled = false;		// Remplie
	this.lockable = bLockable;	// Infobulle avec "punaise" ou pas
	this.locked = false;		// Infobulle lockÃ© ou pas
	this.positionAuto = true;	// Type de positionnement
	this.content = '';			// Contenu de l'infobulle
	this.timer = null;			// Timer de suppression
	this.parentIndex = null;	// Indice de l'infobulle parent
	this.childIndex = null;		// Indice de l'infobulle enfant
	
	// Parties composant l'infobulle
	this.html_div = null;
	this.html_att = null;
	this.html_tb = null;
	this.html_t = null;
	this.html_hdl = null;
	this.html_c = null;
	this.html_content = null;
	this.html_parent = null;	// Parent html (permet le "rattachement" de la div)
	
	// A la crÃ©ation de l'objet, on crÃ©e aussi la DIV elle mÃªme
	var strDiv = '';
	var strHTMLID = 'ifb' + this.index;

	// CrÃ©e le contenu de la div
	strDiv += '<div id="'+ strHTMLID + '_div" class="rpt_div">';
	strDiv += '<table><tr>';
	
	// contenu principal
	strDiv += '<td class="bord">';
	strDiv += '<table>';
	if (this.lockable) {
		// Barre avec punaise
		strDiv += '<tr id="'+ strHTMLID + '_tb">';
		strDiv += '<td></td>';
		strDiv += '<td align="right"><img id="'+ strHTMLID + '_t" src="/layout/images/ico_punaise.gif"></td>';
		strDiv += '<tr>';
		// Handle
		strDiv += '<tr id="'+ strHTMLID + '_hdl" class="handle" style="display:none;">';
		strDiv += '<td></td>';
		strDiv += '<td align="right"><img id="'+ strHTMLID + '_c" src="/layout/images/popup/ico_close_02.gif"></td>';
		strDiv += '<tr>';
	}
	// Contenu
	if (_bLog) strDiv += '<tr><td colspan="2">' + strHTMLID + '</td></tr>';
	
	strDiv += '<tr>';
	strDiv += '<td colspan="2" class="form_champ" id="' + strHTMLID + '_divcontent"><img src="/layout/images/wait2.gif"></td>';
	strDiv += '</tr>';
	strDiv += '</table>';
	strDiv += '</td>';
	
	// PointillÃ©s d'attache
	strDiv += '<td class="att" id="'+ strHTMLID + '_att">&nbsp;</td>';
	strDiv += '</tr></table>';
	strDiv += '</div>';

	// Attachement du contenu au document
	var oDiv = document.createElement('div');
	oDiv.innerHTML = strDiv;	
	document.body.insertBefore(oDiv, null);
	
	// RÃ©cupÃ¨re les divs utiles
	this.html_div = document.getElementById(strHTMLID + '_div');
	if (! this.html_div) return false;
	
	this.html_att = document.getElementById(strHTMLID + '_att');
	this.html_content = document.getElementById(strHTMLID + '_divcontent');
	if (this.lockable) {
		this.html_tb = document.getElementById(strHTMLID + '_tb');
		this.html_t = document.getElementById(strHTMLID + '_t');
		this.html_hdl = document.getElementById(strHTMLID + '_hdl');
		this.html_c = document.getElementById(strHTMLID + '_c');
	}
		
	// Div cachÃ©e par dÃ©faut
	this.html_div.style.visibility = "hidden";
	
	// Ajoute les Ã©vÃ©nements liÃ©s
	this.addEvents();
	
}
// MÃ©thode fill: Remplit Ã  partir d'un contenu
Infobulle.prototype.fill = function(strContent) {
	this.html_content.innerHTML = strContent;
	this.filled = true;
	
	// Pour chaque Ã©lÃ©ment du contenu de type image on ajoute l'index de l'ifb courante
	// Ca permettra de gÃ©rer la notion de pÃ¨re/fils
	var aElems = this.html_content.getElementsByTagName('img'); 
	
	for (iElem = 0; iElem < aElems.length; iElem ++ ) {
		aElems[iElem].index = this.index;
	}
}
// MÃ©thode move: Positionne l'infobulle (Ã©ventuellement par rapport Ã  l'Ã©lÃ©ment parent fourni)
Infobulle.prototype.move = function() {
	// Attention, on positionne tant que Ã§a bouge (limite = 5 fois)
	// En effet, le fait de dÃ©placer peut changer le offsetWidth
	// Du coup il faut quelques itÃ©rations pour trouver la bonne position
	var iCount = 0;
	var iOldLeft = -1000;
	var iLeft = getLeft(this.html_parent) - this.html_div.offsetWidth;
	if (iLeft < 0) iLeft = 0;

	while(iLeft != iOldLeft && iCount < 5) {
		if (this.positionAuto) {
			this.html_div.style.left = iLeft;
			this.html_div.style.top = getTop(this.html_parent);
		}
		else {
			this.html_div.style.left = iLeft;
			this.html_div.style.top = getTop(this.html_parent) - this.html_div.offsetHeight;
		}
		iOldLeft = iLeft;
		iLeft = getLeft(this.html_parent) - this.html_div.offsetWidth;
		if (iLeft < 0) iLeft = 0;
		iCount ++;
	}
}
// MÃ©thode show: Rend une infobulle visible
Infobulle.prototype.show = function() {
	this.visible = true;
	this.html_div.style.visibility = "visible";
}
// MÃ©thode hide: Rend une infobulle invisible
Infobulle.prototype.hide = function() {
	// Si il y a un enfant, on maintient ouvert tant que l'enfant est visible
	if (this.childIndex) {
		oChild = g_ifbm.infobulles[this.childIndex];
		if (oChild && oChild.visible) return false;
	}

	// Si lockÃ©e alors on dÃ©locke
	if (this.locked) this.unlock();
	
	this.visible = false;
	this.html_div.style.visibility = "hidden";
	
	// DÃ©place hors de l'Ã©cran
	this.html_div.style.left = -1000;
	this.html_div.style.top = -1000;

	// Annule l'Ã©ventuel timer
	if (this.timer) clearTimeout(this.timer);
}
// MÃ©thode lock: Convertit en infobulle fixe
Infobulle.prototype.lock = function() {
	this.html_att.style.display = 'none';
	this.html_tb.style.display = 'none';
			
	// correction bug IE sur prise en charge table-row
	if (navigator.appName == 'Netscape') {
		this.html_hdl.style.display = 'table-row';
	}
	else {
		this.html_hdl.style.display = 'block';
	}
	
	// Active le bouton de fermeture
	var oIfb = this;
	this.html_c.onclick = function(event) {oIfb.hide();}
	
	// Active le drag & drop
	Drag.init(this.html_hdl, this.html_div);

	// Note la popup comme Ã©tant lockÃ©e	
	this.locked = true;
}
// MÃ©thode unlock: Convertit en infobulle mobile
Infobulle.prototype.unlock = function() {
	// correction bug IE sur prise en charge table-row
	if (navigator.appName == 'Netscape') {
		this.html_tb.style.display = 'table-row';
	}
	else {
		this.html_tb.style.display = 'block';
	}
	this.html_att.style.display = 'block';	
	this.html_hdl.style.display = 'none';
			
	// Note la popup comme Ã©tant dÃ©lockÃ©e	
	this.locked = false;
}

// MÃ©thode countDown: Commence un dÃ©compte de suppression
Infobulle.prototype.countDown = function() {
	if (this.timer) clearTimeout(this.timer);
	
	if (!this.locked) {
		this.timer = setTimeout('oIfb = g_ifbm.infobulles[' + this.index + ']; oIfb.hide()', 200);
	
		// S'il a un parent, met un countdown aussi sur le parent
		if (this.parentIndex) {
			oParent = g_ifbm.infobulles[this.parentIndex];
			if (oParent) {
				oParent.countDown();
			}
		}
	}		
}
// MÃ©thode keepAlive: Annule la suppression
Infobulle.prototype.keepAlive = function() {
	if (this.timer) clearTimeout(this.timer);
}

// MÃ©thode addEvents: Ajoute les gestionnaires d'Ã©vÃ©nements automatiques
Infobulle.prototype.addEvents = function() {
	var oIfb = this;
	this.html_div.onmouseover = function(event) {oIfb.keepAlive();}
	this.html_div.onmouseout = function(event) {oIfb.countDown();}
	if (this.lockable) {
		this.html_tb.ondblclick = function(event) {oIfb.lock();}
		this.html_t.onclick = function(event) {oIfb.lock();}
	}
}


//////////////////////////////////////////////////////////////////////////////////////////
// Classe IfbManager
//	- Classe de gestion des infobulles de la page
//////////////////////////////////////////////////////////////////////////////////////////
var IfbManager = function() {
	this.infobulles = new Array();	// Tableau des infobulles
	this.nextIndex = 1;				// Prochain index disponible
}
// MÃ©thode addIfb: Ajoute une infobulle
IfbManager.prototype.addIfb = function(oElem, strID, bLockable, bPositionAuto) {
	if (! _bLoaded) return;				// Si page non chargÃ©e, annule

	var oIfb = null;
	// Recherche si on n'a pas dÃ©jÃ  une infobulle avec cet ID
	for(iIndex = 1; iIndex < this.infobulles.length; iIndex ++) {
		if (this.infobulles[iIndex].id == strID) {
			oIfb = this.infobulles[iIndex];
		}
	}

	// Si on a dÃ©jÃ  l'infobulle, il faut juste la rÃ©activer
	if (oIfb) {
		// Si vÃ©rouillÃ©, on ne fait rien de plus!
		if (oIfb.locked) return oIfb;
		oIfb.visible = true;
	}
	// Dans le cas contraire il faut la crÃ©er
	else {
		var oIfb = new Infobulle(this.nextIndex, strID, bLockable);

		// Ajoute au tableau
		this.infobulles[this.nextIndex] = oIfb;
		this.nextIndex ++;
		
		if (!oIfb) return false;	// Si problÃ¨me pendant la crÃ©ation, on laisse tomber

		// Positionne les propriÃ©tÃ©s
		oIfb.lockable = bLockable;
		oIfb.positionAuto = bPositionAuto;
		oIfb.html_parent = oElem;
		
		// On ajoute un gestionnaire onmouseout pour la fermeture de l'infobulle
		oElem.onmouseout = function(event) {
			oIfb.countDown(); 
		}
	}

	// Regarde si ifb pÃ¨re
	if (oElem.index) {
		oParent = this.infobulles[oElem.index];
		if (oParent) {
			oParent.childIndex = oIfb.index;
			oIfb.parentIndex = oParent.index;
		} 
	}

	// On affiche
	oIfb.show();

	// On positionne l'infobulle
	oIfb.move();
	
	// On supprime toutes les infobulles non lockÃ©es
	for(iIndex = 1; iIndex < this.infobulles.length; iIndex ++) {
		if (this.infobulles[iIndex].id != oIfb.id && ! this.infobulles[iIndex].locked) {
			this.infobulles[iIndex].hide();
		}
	}

	// On retourne l'index d'infobulle
	return oIfb.index;
}
// MÃ©thode fillIfb: Remplit une infobulle (Ã©ventuellement de maniÃ¨re asynchrone)
IfbManager.prototype.fillIfb = function(iIndex, strMethod, astrParams, strContenu) {
	// RÃ©cupÃ¨re l'infobulle
	var oIfb = this.infobulles[iIndex];
	// Teste si l'infobulle existe
	if (! oIfb) return false;
	// Teste si toujours visible
	if (! oIfb.visible) return false;
	// Teste si dÃ©jÃ  remplie
	if (oIfb.filled) return false;
	
	// 2 cas de figure: contenu passÃ© directement ou par appel ajaxasynchrone
	if (strContenu) {
		oIfb.fill(strContenu);

		// DÃ©place au bon endroit
		oIfb.move();
	}
	else if(strMethod && astrParams) {
		// Appel ajax asynchrone
		ajax_asyncMethod(strMethod, astrParams, '', oIfb);
		
		// Note tout de suite comme rempli pour Ã©viter appels ajax multiples
		this.filled = true;
	}
}


// CrÃ©e un gestionnaire d'infobulles global
var g_ifbm = new IfbManager();
//////////////////////////////////////////////////////////////////////////////////////////
/// AJOUT 2.5.4: Scripts liÃ©s aux WebControls
//////////////////////////////////////////////////////////////////////////////////////////
// Ce fichier est destinÃ© Ã  gÃ©rer les javascripts liÃ©s aux WebControls aprÃ¨s rÃ©Ã©criture propre
// en javascript objet
// La classe WCManager permet de gÃ©rer tous les WebControls en lot
// Chaque WebControl ne doit appeler qu'une mÃ©thode qui lui rattache ensuite tous les appels js
 

//////////////////////////////////////////////////////////////////////////////////////////
// Classe WCManager
//	- Classe de gestion des webcontrols de la page
//////////////////////////////////////////////////////////////////////////////////////////
var WCManager = function() {
	this.controls = new Array();	// Tableau des infobulles
	this.nextIndex = 1;				// Prochain index disponible
}
// MÃ©thode gÃ©nÃ©rique d'ajout d'un contrÃ´le
WCManager.prototype.addControl = function(oCtrl, oElem) {
	if (!oCtrl) return false;

	// Ajoute au tableau
	this.controls[this.nextIndex] = oCtrl;
	oCtrl.index = this.nextIndex;
	this.nextIndex ++;

	// Initialise 
	oCtrl.init();
	
	// Attache les Ã©vÃ©nements
	oCtrl.addEvents();
	
	// Place un flag pour ne pas initialiser 2 fois
	oElem.added = 1;
}
// Ajoute un WebUploadFlat
WCManager.prototype.addWebUploadFlat = function(oElem, strID, iMaxFileSize) {
	// On regarde si le traitement n'a pas dÃ©jÃ  Ã©tÃ© fait
	if (oElem.added) return true; 
	
	// CrÃ©e un nouveau contrÃ´le
	var oCtrl = new WebUploadFlat(strID);
	
	// Positionne les options
	oCtrl.maxFileSize = iMaxFileSize;
		
	// Ajout du contrÃ´le au gestionnaire 
	this.addControl(oCtrl, oElem);
}
// Ajoute un WebSelector
WCManager.prototype.addWebSelector = function(oElem, strID, iSize, iWidth, bLineFeed, bAutoPostback, strOnChange, iNbElemMaxi, strErrNbElemMaxi) {
	// Si page non chargÃ©e, retente plus tard
	if (! _bLoaded) {
		setTimeout(function () { g_wcm.addWebSelector(oElem, strID, iSize, iWidth, bLineFeed, bAutoPostback, strOnChange, iNbElemMaxi, strErrNbElemMaxi) }, 200);
	}
	else {
		// On regarde si le traitement n'a pas dÃ©jÃ  Ã©tÃ© fait
		if (oElem.added) return true; 
		
		// CrÃ©e un nouveau contrÃ´le
		var oCtrl = new WebSelector(strID);
		
		// Positionne les options
		oCtrl.size = iSize;
		oCtrl.width = iWidth;
		oCtrl.lineFeed = bLineFeed;
		oCtrl.autoPostback = bAutoPostback;
		oCtrl.onChange = strOnChange;
		oCtrl.nbMax = iNbElemMaxi;
		oCtrl.errMax = strErrNbElemMaxi;
			
		// Ajout du contrÃ´le au gestionnaire 
		this.addControl(oCtrl, oElem);
	}
}


//////////////////////////////////////////////////////////////////////////////////////////
// Classe WebUploadFlat
//////////////////////////////////////////////////////////////////////////////////////////
var WebUploadFlat = function(strID) {
	this.id = strID;			// identifiant unique
	this.index = -1;			// Indice de crÃ©ation
	this.maxFileSize = 0;		// Taille maximale
	
	// Parties HTML
	this.html_hid = null;		// Champ cachÃ© contenant le nom temporaire
	this.html_upl= null;		// imput file
	this.html_txt = null;		// Champ texte contenant le nom original
	this.html_mfs = null;		// Champ MAX_FILE_SIZE
}
// Initialisation du contrÃ´le
WebUploadFlat.prototype.init = function() {
	// Charge les composants HTML
	this.html_hid = document.getElementById(this.id);
	this.html_upl = document.getElementById(this.id + '_upl');
	this.html_txt = document.getElementById(this.id + '_txt');
	this.html_mfs = document.getElementById(this.id + '_mfs');
	
	// Place les balises name
	this.html_hid.name = this.html_hid.id;
	this.html_upl.name = this.html_upl.id;
	this.html_txt.name = this.html_txt.id;
}
// MÃ©thode addEvents: Ajoute les gestionnaires d'Ã©vÃ©nements automatiques
WebUploadFlat.prototype.addEvents = function() {
	var oCtrl = this;
	
	// DÃ©clenche un postback sur le onchange
	this.html_upl.onchange = function(event) {
		oCtrl.prepareForm();
		throwPostBack(oCtrl.id);
	}
}
// MÃ©thode prepareForm: PrÃ©pare le formulaire Ã  l'envoi
WebUploadFlat.prototype.prepareForm = function() {
	var oForm = document.getElementById('MainForm');
	
	// Ajoute l'encodage multipart
	oForm.encoding = "multipart/form-data";
	
	// Ajoute un champ MAX_FILE_SIZE
	var strMaxFileSize = '<input type="hidden" name="MAX_FILE_SIZE" value="' + this.maxFileSize + '" />';
	this.html_mfs.innerHTML = strMaxFileSize;	
}


//////////////////////////////////////////////////////////////////////////////////////////
// Classe WebSelector
//////////////////////////////////////////////////////////////////////////////////////////
var WebSelector = function(strID) {
	this.id = strID;			// identifiant unique
	this.index = -1;			// Indice de crÃ©ation
	this.size = 0;				// Taille de la liste
	this.width = 0;				// Largeur de la liste
	this.lineFeed = true;		// Affiche ou pas un retour Ã  la ligne entre chaque Ã©lÃ©ment
	this.autoPostback = false;	// EvÃ©nement appelÃ© sur le onchange
	this.onChange = '';			// EvÃ©nement appelÃ© sur le onchange
	this.nbMax = 0;				// Nb d'Ã©lÃ©ments maxi autorisÃ©s
	this.errMax = '';			// Message si dÃ©passemetn du nombre d'Ã©lÃ©ments maxi
	this.filled = false;		// Remplie
	this.visible = false;		// VisibilitÃ©
	this.timer = null;			// Timer de suppression
	
	// Parties HTML
	this.html_hid = null;		// Champ cachÃ©
	this.html_tbl = null;		// Tableau principal
	this.html_div = null;		// Div d'infobulle de sÃ©lection
	this.html_sel = null;		// Div des Ã©lÃ©ments sÃ©lectionnÃ©s
	this.html_add = null;		// TD du bouton add
	this.html_rem = null;		// TD du bouton clear
	this.html_ico = null;		// Zone des icÃ´nes
	this.html_img_add = null;	// Image du bouton add
	this.html_img_rem = null;	// Image du bouton clear
	this.html_list = null;		// Liste de selection
	this.html_wait = null;		// Image d'attente
}
// Initialisation du contrÃ´le
WebSelector.prototype.init = function() {
	// AJOUT 2.5.4: On regarde si la div de mÃªme id n'existe pas dÃ©jÃ .
	// Si c'est le cas on la rÃ©cupÃ¨re, sinon on en crÃ©e une
	var oDivExiste = document.getElementById(this.id + '_div');
	if (oDivExiste) {
	    var oDiv = oDivExiste.parentNode;
	}
	else {
		var oDiv = document.createElement('div');
	}

	// A la crÃ©ation de l'objet, on crÃ©e aussi la div de sÃ©lection
	var strDiv = '';
	strDiv += '<div id="' + this.id + '_div" class="wsel_sel">';
	strDiv += '<img src="/layout/images/wait2.gif" />';
	strDiv += '<select multiple id="' + this.id + '_left" style="display:none">';
	strDiv += '</select>';
	strDiv += '</div>';

	oDiv.innerHTML = strDiv;
	document.body.insertBefore(oDiv, null);
	
	// Charge les composants HTML
	this.html_hid = document.getElementById(this.id);
	this.html_tbl = document.getElementById(this.id + '_tbl');
	this.html_div = document.getElementById(this.id + '_div');
	this.html_list = document.getElementById(this.id + '_left');
	
	// Retrouve les td d'image et celle de classe "i" et celle de la classe sel
	var aTDs = this.html_tbl.getElementsByTagName('td');
	for (var iTD = 0; iTD < aTDs.length; iTD ++){
		if (aTDs[iTD].className == 'add') {
			this.html_add = aTDs[iTD];
		}
		else if (aTDs[iTD].className == 'rem') {
			this.html_rem = aTDs[iTD];
		}
		else if (aTDs[iTD].className == 'i') {
			this.html_ico = aTDs[iTD];
		}
		else if (aTDs[iTD].className == 'sel' || aTDs[iTD].className == 'sel lf') {
			this.html_sel = aTDs[iTD];
		}

		if (this.html_add && this.html_rem && this.html_ico && this.html_sel) break;
	}

	// Retrouve l'image d'attente
	var aImgs = this.html_div.getElementsByTagName('img');
	this.html_wait = aImgs[0];

	// Place les tags HTML sur les composants du contrÃ´le
	if (this.width) this.html_sel.style.width = this.width;
	
	// CrÃ©e les images des boutons add et remove
	this.html_img_add = document.createElement('img');
	this.html_img_add.src = '/psframework/webcontrols/resources/images/ws_add.gif';
	this.html_add.appendChild(this.html_img_add);

	this.html_img_rem = document.createElement('img');
	this.html_img_rem.src = '/psframework/webcontrols/resources/images/ws_clear.gif';
	this.html_img_rem.style.cursor = 'pointer';
	this.html_rem.appendChild(this.html_img_rem);


	// Options sur le select
	this.html_list.size = this.size;
	this.html_list.style.width = this.width + 20 + 'px';
}

// MÃ©thode addEvents: Ajoute les gestionnaires d'Ã©vÃ©nements automatiques
WebSelector.prototype.addEvents = function() {
	var oCtrl = this;

	// Attache les remove sur les anchors de la liste des sÃ©lectionnÃ©s
	var aAnchors = this.html_sel.getElementsByTagName('A');
	for (var iAnchor = 0; iAnchor < aAnchors.length; iAnchor ++) {
		if (aAnchors[iAnchor].id) {
			// A l'intÃ©rieur du onclick, this fait rÃ©fÃ©rence Ã  l'anchor
			aAnchors[iAnchor].onclick = function (event) {
				oCtrl.remove(this);	
			}
		}
	}
	
	// EvÃ©nement sur l'icÃ´ne d'ajout
	this.html_img_add.onmouseover = function (event) {
		// Affiche
		oCtrl.show();
		
		// Positionne
		oCtrl.move();

		// Chargement AJAX
		if (! oCtrl.filled) {
			oCtrl.load();
		}
		
	}
	this.html_img_add.onmousemove = function (event) { oCtrl.keepAlive(); }

	// EvÃ©nement sur l'icÃ´ne de clear
	this.html_img_rem.onclick = function (event) { oCtrl.clear(); }
	
	// EvÃ©nements de masquage de la div
	this.html_img_add.onmouseout = function (event) { oCtrl.countDown();}
	this.html_div.onmouseover = function (event) { oCtrl.keepAlive(); }
	this.html_div.onmouseout = function (event) { oCtrl.countDown(); }
	
	// Ajout d'un Ã©lÃ©ment
	this.html_list.onclick = function (event) { this.focus(); oCtrl.add(); this.focus();}
	
	// AJOUTS 2.5.5: Gestion du clavier
	this.html_list.onkeypress = function (event) {
	    var iKey;
     	if (window.event) {
	        iKey = window.event.keyCode;
	    }
	    else if (event.which) {
	        iKey = event.which;
		}
		// Si touche entrÃ©e
		if (iKey == 13) {
		    // RÃ©cupÃ¨re les Ã©lÃ©ments dans la sÃ©lection et les bascule
		    this.focus(); oCtrl.add(); this.focus();

		}
	}
	
	// AJOUT 2.5.5: Force le focus sur le survol
	this.html_list.onmouseover = function (event) { this.focus(); }
}

// MÃ©thode add: Ajoute un Ã©lÃ©ment Ã  la sÃ©lection
WebSelector.prototype.add = function() {
	// Boucle sur les options pour trouver celles qui sont sÃ©lectionnÃ©es
	var aIndex = new Array();
	for (var iOption = 0; iOption < this.html_list.options.length; iOption ++) {
	    // Attention, l'indice effectif va changer donc il faut Ã  chaque fois dÃ©caler de 1
	    if (this.html_list.options[iOption].selected) aIndex.push(iOption - aIndex.length);
	}

	// Ajout effectif
	for (var iOption = 0; iOption < aIndex.length; iOption ++) {
	    this._add(aIndex[iOption]);
	}

 	// Synchronise
	this.sync();
}

// MÃ©thode add: Ajoute un Ã©lÃ©ment Ã  la sÃ©lection
// MÃ©thode privÃ©e qui ne dÃ©clenche pas de synch
WebSelector.prototype._add = function(iOldIndex) {
	if (iOldIndex == -1) return;
	var oOption = this.html_list.options[iOldIndex];

	// ContrÃ´le sur le nombre d'Ã©lÃ©ments sÃ©lectionnÃ©s
	if (this.nbMax > 0) {
		var aAnchors = this.html_sel.getElementsByTagName('A');

		if (aAnchors.length >= this.nbMax) {
			if (this.errMax != '') alert(this.errMax);
		    return false;
		}
	}
	// Supprime l'Ã©lÃ©ment de la liste de sÃ©lection en gardant le niveau de scroll
	var iScroll = this.html_list.scrollTop;
	if (iOldIndex > 0) {
		if (this.html_list.options[iOldIndex - 1]) this.html_list.selectedIndex = iOldIndex - 1;
	}
	this.html_list.options[iOldIndex] = null;
	this.html_list.scrollTop = iScroll;

	// CrÃ©e le nouvel Anchor
	var oAnchor = document.createElement('A');
	oAnchor.id = this.id + '#' + oOption.value;
	oAnchor.appendChild(document.createTextNode(oOption.text)); // MODIF 2.5.5
	this.html_sel.insertBefore(oAnchor, null);

	// Ajoute l'Ã©vÃ©nement liÃ©
	var oCtrl = this;
	oAnchor.onclick = function(event) {
		// Ici this fait rÃ©fÃ©rence Ã  l'anchor
		oCtrl.remove(this);
	}
}


// MÃ©thode remove: Supprime un Ã©lÃ©ment de la sÃ©lection (publique)
WebSelector.prototype.remove = function(oElem) {
	this._remove(oElem);

	// Synchronise
	this.sync();
}

// MÃ©thode clear: Vide la sÃ©lection
WebSelector.prototype.clear = function() {
	var aAnchors = this.html_sel.getElementsByTagName('A');
	for (var iAnchor = aAnchors.length - 1; iAnchor >= 0; iAnchor --) {
		if (aAnchors[iAnchor].id) {
			this._remove(aAnchors[iAnchor]);	
		}
	}
	
	// Synchronise
	this.sync();
}

// MÃ©thode _remove: Supprime un Ã©lÃ©ment de la sÃ©lection
// MÃ©thode privÃ©e qui ne dÃ©clenche pas de synch
WebSelector.prototype._remove = function(oElem) {
	// MODIF 2.5.5: Il faut charger la liste de droite pour supprimer, sinon les valeurs disparaissent
	// Attention, chargement synchrone: on doit Ãªtre sÃ»r d'aller au bout avant de faire la suppression
	if (! this.filled && ! this.autopostback) {
		var strOptions = ajax_syncMethod('WebSelector::getListeAjax', new Array(this.id), '', this);
		this.fill(strOptions);
	}
	
	var aID = oElem.id.split('#');
	var strIDCtrl = aID[0];
	var strValeurElem = aID[1];
	
	var strCaption = oElem.innerHTML;

	// Si la liste de sÃ©lection existe, on remet dans cette liste
	if (this.filled) {
		var oOption = new Option(htmlspecialchars_decode(strCaption), strValeurElem);   // MODIF 2.5.5
		oOption.title = htmlspecialchars_decode(strCaption);
		this.html_list.options[this.html_list.options.length]= oOption;
	}
	oElem.parentNode.removeChild(oElem);
}


// MÃ©thode sync: Synchronise la valeur du champ cachÃ©
WebSelector.prototype.sync = function() {
	// Construit la liste des ID
	var aAnchors = this.html_sel.getElementsByTagName('A');
	var s = '';
	for (var iAnchor = 0; iAnchor < aAnchors.length; iAnchor ++) {
		if (aAnchors[iAnchor].id) {
			var strID = aAnchors[iAnchor].id;
			var aID = strID.split('#');
			var strValeur = aID[1];
			
			if (s) s += ',';
			s += strValeur;
		}
	}
	
	// Affecte la valeur au champ cachÃ©
	this.html_hid.value = s;

	// MÃ©canisme d'autopostback
	if (this.autoPostback) throwPostBack(this.id);

	// Le OnChange
	if (this.onChange) eval(this.onChange);
}

// MÃ©thode fill: Remplit Ã  partir d'un contenu
WebSelector.prototype.fill = function(strContent) {
	// Parse la chaÃ®ne qui est du type clÃ©1>valeur1|clÃ©2>valeur2|...
	var aOpt = strContent.split('|');
	for (var iOption = 0; iOption < aOpt.length; iOption++ ) {
		var aKeyVal = aOpt[iOption].split('~');
		
		if (aKeyVal[0] && aKeyVal[1]) {
			// Ajoute une option
			var oOption = new Option(aKeyVal[1], aKeyVal[0]);
			oOption.title = aKeyVal[1];
			this.html_list.options[this.html_list.options.length]= oOption;
		}
	}
	this.filled = true;

	// Masque l'image d'attente
	this.html_wait.style.display = 'none';

	// Affiche le select
	this.html_list.style.display = 'block';

	// SÃ©lectionne le premier Ã©lÃ©ment de la liste
	if (this.html_list.options.length > 0) {
		this.html_list.selectedIndex = 0;
		this.html_list.focus();
	}
}

// MÃ©thode load: Charge le contenu
WebSelector.prototype.load = function() {
	ajax_asyncMethod('WebSelector::getListeAjax', new Array(this.id), '', this);
	// Note tout de suite comme rempli pour Ã©viter appels ajax multiples
	this.filled = true;
}

// MÃ©thode move: Positionne la div de sÃ©lection
WebSelector.prototype.move = function() {
	this.html_div.style.left = getLeft(this.html_add) + this.html_add.offsetWidth + 2;
	this.html_div.style.top = getTop(this.html_ico);
}
// MÃ©thode show: Affiche la liste de sÃ©lection
WebSelector.prototype.show = function() {
	this.visible = true;
	this.html_div.style.visibility = 'visible';
}

// MÃ©thode hide: Cache la liste de sÃ©lection
WebSelector.prototype.hide = function() {
	this.visible = false;
	this.html_div.style.visibility = 'hidden';
}
// MÃ©thode countDown: Commence un dÃ©compte de masquage
WebSelector.prototype.countDown = function() {
	if (this.timer) clearTimeout(this.timer);
	this.timer = setTimeout('var oCtrl = g_wcm.controls[' + this.index + ']; oCtrl.hide()', 200);
}
// MÃ©thode keepAlive: Annule le masquage
WebSelector.prototype.keepAlive = function() {
	if (this.timer) clearTimeout(this.timer);
}


//////////////////////////////////////////////////////////////////////////////////////////
// CrÃ©e un gestionnaire global
var g_wcm = new WCManager();
/**
 * $Id: mcimagemanager.js 634 2009-01-08 16:52:45Z spocke $
 *
 * @author Moxiecode
 * @copyright Copyright © 2004-2008, Moxiecode Systems AB, All rights reserved.
 */

(function() {
	window.mcImageManager = {
		settings : {
			document_base_url : '',
			relative_urls : false,
			remove_script_host : false,
			use_url_path : true,
			remember_last_path : 'auto',
			target_elements : '',
			target_form : '',
			handle : 'image,media'
		},

		setup : function() {
			var t = this, o, d = document, cp = [];

			// Find document_base_url
			o = d.location.href;

			if (o.indexOf('?') != -1)
				o = o.substring(0, o.indexOf('?'));

			o = o.substring(0, o.lastIndexOf('/') + 1);

			t.settings.default_base_url = unescape(o);

			// Find script base URL
			function get(nl) {
				var i, n;

				for (i=0; i<nl.length; i++) {
					n = nl[i];

					cp.push(n);

					if (n.src && /mcimagemanager\.js/g.test(n.src))
						return n.src.substring(0, n.src.lastIndexOf('/'));
				}
			};

			o = d.documentElement;
			if (o && (o = get(o.getElementsByTagName('script'))))
				return t.baseURL = o;

			o = d.getElementsByTagName('script');
			if (o && (o = get(o)))
				return t.baseURL = o;

			o = d.getElementsByTagName('head')[0];
			if (o && (o = get(o.getElementsByTagName('script'))))
				return t.baseURL = o;
		},

		relaxDomain : function() {
			var t = this, p = /(http|https):\/\/([^\/:]+)\/?/.exec(t.baseURL);

			// Use tinymce relaxed domain
			if (window.tinymce && tinymce.relaxedDomain && tinymce.relaxedDomain != document.location.hostname) {
				t.relaxedDomain = tinymce.relaxedDomain;
				return;
			}

			// Relax domain
			if (p && p[2] != document.location.hostname)
				document.domain = t.relaxedDomain = p[2].replace(/.*\.(.+\..+)$/, '$1');
		},

		init : function(s) {
			this.extend(this.settings, s);
		},

		browse : function(s) {
			var t = this;

			s = s || {};

			if (s.fields) {
				s.oninsert = function(o) {
					t.each(s.fields.replace(/\s+/g, '').split(/,/), function(v) {
						var n;

						if (n = document.getElementById(v))
							t._setVal(n, o.focusedFile.url);
					});
				};
			}

			this.openWin({page : 'index.html', scrollbars : 'yes'}, s);
		},

		edit : function(s) {
			this.openWin({page : 'edit.html', width : 800, height : 500}, s);
		},

		upload : function(s) {
			this.openWin({page : 'upload.html', width : 550, height : 350}, s);
		},

		view : function(s) {
			this.openWin({page : 'view.html', width : 800, height : 500}, s);
		},

		createDir : function(s) {
			this.openWin({page : 'createdir.html', width : 450, height : 280}, s);
		},

		openWin : function(f, a) {
			var t = this, w, v;

			t.windowArgs = a = t.extend({}, t.settings, a);
			f = t.extend({
				x : -1,
				y : -1,
				width : 800,
				height : 500,
				inline : 1
			}, f);

			if (f.page)
				f.url = t.baseURL + '/../index.php?type=im&page=' + f.page;

			if (a.session_id)
				f.url += '&sessionid=' + a.session_id;

			if (a.custom_data)
				f.url += '&custom_data=' + escape(a.custom_data);

			if (t.relaxedDomain)
				f.url += '&domain=' + escape(t.relaxedDomain);

			if (a.custom_query)
				f.url += a.custom_query;

			// Open in specified frame
			if (a.target_frame) {
				if (v = frames[a.target_frame])
					v.document.location = f.url;

				if (v = document.getElementById(a.target_frame))
					v.src = f.url;

				return;
			}

			// Use jQuery WindowManager
			if (window.jQuery && jQuery.WindowManager)
				return jQuery.WindowManager.open(f, a);

			// Use TinyMCE window API
			if (window.tinymce && tinyMCE.activeEditor)
				return tinyMCE.activeEditor.windowManager.open(f, a);

			if (f.x == -1)
				f.x = parseInt(screen.width / 2.0) - (f.width / 2.0);

			if (f.y == -1)
				f.y = parseInt(screen.height / 2.0) - (f.height / 2.0);

			// Use native dialogs
			w = window.open(f.url, 'mcImageManagerWin', 'left=' + f.x + 
				',top=' + f.y + ',width=' + f.width + ',height=' + 
				f.height + ',scrollbars=' + (f.scrollbars ? 'yes' : 'no') + 
				',resizable=' + (f.resizable ? 'yes' : 'no') + 
				',statusbar=' + (f.statusbar ? 'yes' : 'no')
			);

			try {
				w.focus();
			} catch (ex) {
				// Ignore
			}
		},

		each : function(o, f, s) {
			var n, l;

			if (o) {
				s = s || o;

				if (o.length !== undefined) {
					for (n = 0, l = o.length; n < l; n++)
						f.call(s, o[n], n, o);
				} else {
					for (n in o) {
						if (o.hasOwnProperty(n))
							f.call(s, o[n], n, o);
					}
				}
			}
		},

		extend : function() {
			var k, a = arguments, t = a[0], i, v;

			for (i = 1; i < a.length; i++) {
				if (v = a[i]) {
					for (k in v)
						t[k] = v[k];
				}
			}

			return t;
		},

		// Legacy functions
		open : function(fn, en, url, cb, s) {
			var t = this, el;

			s = s || {};

			// Use input value if it was found
			if (!s.url && document.forms[fn] && (el = document.forms[fn].elements[en.split(',')[0]]))
				s.url = el.value;

			if (!cb) {
				s.oninsert = function(o) {
					var e, i, v, f = o.focusedFile;

					v = en.replace(/\s+/g, '').split(',');

					for (i = 0; i < v.length; i++) {
						if (e = document.forms[fn][v[i]])
							t._setVal(e, f.url);
					}
				};
			} else {
				if (typeof(cb) == 'string')
					cb = window[cb];

				s.oninsert = function(o) {
					cb(o.focusedFile.url, o);
				};
			}

			t.browse(s);
		},

		filebrowserCallBack : function(fn, u, ty, w, ask) {
			var t = mcImageManager, i, hl, fo, s = {};

			// Is filemanager included, ask it first
			if (window.mcFileManager && !ask) {
				hl = mcFileManager.settings.handle;

				hl = hl.split(',');
				for (i = 0; i < hl.length; i++) {
					if (ty == hl[i])
						fo = 1;
				}

				if (fo && mcFileManager.filebrowserCallBack(fn, u, ty, w, 1))
					return;
			}

			// Grab imagemanager prefixed options
			t.each(tinyMCE.activeEditor ? tinyMCE.activeEditor.settings : tinyMCE.settings, function(v, k) {
				if (k.indexOf('imagemanager_') === 0)
					s[k.substring(13)] = v;
			});

			t.browse(t.extend(s, {
				url : w.document.forms[0][fn].value,
				relative_urls : 0,
				oninsert : function(o) {
					var f, u, na;

					f = w.document.forms[0];
					u = o.focusedFile.url;
					inf = o.focusedFile.custom;

					// Let TinyMCE convert the URLs
					if (typeof(TinyMCE_convertURL) != "undefined")
						u = TinyMCE_convertURL(u, null, true);
					else if (tinyMCE.convertURL)
						u = tinyMCE.convertURL(u, null, true);
					else
						u = tinyMCE.activeEditor.convertURL(u, null, true);

					// Set alt and title info
					if (inf.custom && inf.custom.description) {
						na = ['alt', 'title', 'linktitle'];
						for (i = 0; i < na.length; i++) {
							if (f.elements[na[i]])
								f.elements[na[i]].value = inf.custom.description;
						}
					}

					t._setVal(f[fn], u);

					w = null; // IE leak
				}
			}));

			return true;
		},

		_setVal : function(n, v) {
			n.value = v;

			try {
				n.onchange();
			} catch (e) {
				// Skip it
			}
		}
	};

	mcImageManager.setup();
	mcImageManager.relaxDomain();
})();