/*
 * ScienceActive's Windows
 *
 * This script was created by Hervé Soulard(Herve.Soulard@sienceactive.com)
 * Copyright 2007
 * 
 * Version: 1.0
 * Created: 2007-06-23	First working version
 *
 */

var allSAPanelInfo = new Array();


///////////////////////////////////////////////////////////////////////////////////
// The constructor for SAPanelInfo
//
function SAPanelInfo() {
	with (this) {
		margin = new Array(0, 0, 0, 0);
		padding = new Array(0, 0, 0, 0);
		border = new Array(0, 0, 0, 0);
		bow = new Array(0, 0);
		id = null;
		element = null;
		subcont = null; /* Of type SAWindow2 */
	}
	allSAPanelInfo[allSAPanelInfo.length] = this;
}

SAPanelInfo.prototype = {
	
	setId: function(id) {
		this.id = id;
		this.element = document.getElementById(id);
	},
	getId: function() {
		return this.id;
	},

	getElement: function() {
		return this.element;
	},
	
	getBox: function() {
		return this.box;
	},
	setBox: function(w, h) {
		this.box = this.initTab2(w, h);
	},

	getSubcont: function() {
		return this.subcont;
	},
	setSubcont: function(subcont) {
		// !!!! vérifier le type de subscont.
		this.subcont = subcont;
	},

	getMargin: function() {
		return this.margin;
	},
	setMargin: function(t, r, b, l) {
		this.margin = this.initTab4(t, r, b, l);
	},

	getPadding: function() {
		return this.padding;
	},
	setPadding: function(t, r, b, l) {
		this.padding = this.initTab4(t, r, b, l);
	},

	getBorder: function() {
		return this.border;
	},
	setBorder: function(t, r, b, l) {
		this.border = this.initTab4(t, r, b, l);
	},

	getTotalHeight: function() {
		var h = this.getTotalAroundHeight();
		h += this.box[SAPanelInfo.HEIGHT];
		return h;
	},

	getTotalWidth: function() {
		var w = this.getTotalAroundWidth();
		w += this.box[SAPanelInfo.WIDTH];
		return w;
	},

	getTopAroundHeight: function() {
		var h = this.margin[SAPanelInfo.TOP] + this.border[SAPanelInfo.TOP] + this.padding[SAPanelInfo.TOP];
		return h;
	},

	getBottomAroundHeight: function() {
		var h = this.margin[SAPanelInfo.BOTTOM] + this.border[SAPanelInfo.BOTTOM] + this.padding[SAPanelInfo.BOTTOM];
		return h;
	},

	getTotalAroundHeight: function() {
		var h = 0;
		h += this.margin[SAPanelInfo.TOP] + this.margin[SAPanelInfo.BOTTOM];
		h += this.border[SAPanelInfo.TOP] + this.border[SAPanelInfo.BOTTOM];
		h += this.padding[SAPanelInfo.TOP] + this.padding[SAPanelInfo.BOTTOM];
		return h;
	},
	
	getTotalAroundWidth: function() {
		var w = 0;
		w += this.margin[SAPanelInfo.LEFT] + this.margin[SAPanelInfo.RIGHT];
		w += this.border[SAPanelInfo.LEFT] + this.border[SAPanelInfo.RIGHT];
		w += this.padding[SAPanelInfo.LEFT] + this.padding[SAPanelInfo.RIGHT];
		return w;
	},
	
	setSize: function(w, h) {
		if (h != null && h >= 0) this.element.style.height = h + "px";
		if (w != null && w >= 0) this.element.style.width = w + "px";
		// On ajuste la taille de l'élément, alors actualiser les champs.
		var styles = this.getAllStyles(this.element);
		this.setBox(styles.width, styles.height);
	},
	
	setPos: function(t, r, b, l) {
		if (t != null) this.element.style.top = t + "px";
		if (r != null) this.element.style.right = r + "px";
		if (b != null) this.element.style.bottom = b + "px";
		if (l != null) this.element.style.left = l + "px";
	},

	getAllStyles: function(ele) {
		var styles = null;
		
		if (isIE()) {
			styles = ele.currentStyle;
		} else {
			styles = window.getComputedStyle(ele, null);
		}
		
		return styles;
	},

	autoFill: function() {
		if (this.element == null) return false;
		
		var styles = this.getAllStyles(this.element);

		with (styles) {
			// Attention à l'ordre des arguments.
			this.setMargin(marginTop, marginRight, marginBottom, marginLeft);
			this.setPadding(paddingTop, paddingRight, paddingBottom, paddingLeft);
			this.setBorder(borderTopWidth, borderRightWidth, borderBottomWidth, borderLeftWidth);
			this.setBox(width, height);
		}
		
		return true;
	},
	
	myAlert: function() {
		var styles = this.getAllStyles(this.element);
		alert(this.id + " : " + styles.margin + " - " + styles.padding + " - " + styles.borderWidth + 
			            " - " + styles.width + "," + styles.height);
		alert(this.id + " : " + this.margin + " - " + this.padding + " - " + this.border + " - " + this.box);
	},
	
	addClassName: function(name) {
		if (this.element == null) return false;
		if (!name) return false;
		
		this.element.className = this.element.className + " " + name;
		return true;
	},
	
	
	//
	//
	initTab4: function(t, r, b, l) {
		if (!t) t = "0";
		if (!r) r = "0";
		if (!b) b = "0";
		if (!l) l = "0";
		
		return new Array(parseInt(t), parseInt(r), parseInt(b), parseInt(l));
	},

	initTab2: function(w, h) {
		if (!w) w = "0";
		if (!h) h = "0";
				
		return new Array(parseInt(w), parseInt(h));
	}
}

SAPanelInfo.WIDTH = 	0;
SAPanelInfo.HEIGHT = 	1;

SAPanelInfo.TOP = 		0;
SAPanelInfo.RIGHT = 	1;
SAPanelInfo.BOTTOM = 	2;
SAPanelInfo.LEFT = 		3;

///////////////////////////////////////////////////////////////////////////////////
// The constructor for SAWindow2.
//
function SAWindow2( rootDivId, windId, windClass, menuId, menuClass, contId, contClass, type) {
	//if ( !hasSupport() || wind == null ) return;

	var thisObject = this;
	
	this.packDone = false;
	this.type = type;
	
	// Vérifier que le <div> conteneur existe bien.
	var rootEle = document.getElementById(rootDivId);
	if ( rootEle == null ) { return false; }


	// Voir si le 'rootDiv' est déjà un conteneur d'une autre fenêtre.
	var found = false;
	var rootSAPanelInfo = null;
	for (var i = 0; (i < allSAPanelInfo.length) && !found; i++) {
		var l = allSAPanelInfo[i];
		if (l) {
			var lId = l.getId();
			if (lId == rootDivId) {
				rootSAPanelInfo = l;				
				found = true;
			}
		}
	}
	
	if (found) {
		this.rootDiv = rootSAPanelInfo;
		rootSAPanelInfo.setSubcont(this);
	} else {
		// Informations sur le <div> racine.
		this.rootDiv = new SAPanelInfo();
		this.rootDiv.setId(rootDivId);
		this.rootDiv.autoFill();
	}

	// Créer les <div> pour la fenêtre, le menu et le contenu.
	var windEle = document.createElement("div");
	windEle.id = windId;
	var menuEle = document.createElement("div");
	menuEle.id = menuId;
	var contEle = document.createElement("div");
	contEle.id = contId;
	
	var rBarEle;
	var rBarId = windId + "rbar";
	if (this.type == SAWindow2.RESIZE_VERTICAL) {
		rBarEle = document.createElement("div");
		rBarEle.id = rBarId;
		rBarEle.onmousedown = function(event) { thisObject.startDrag(thisObject.wind, event); };
		var img = document.createElement("img");
		img.className = "SAWindow2-resizeBarImg";
		img.src = "img/up-down.gif";
		rBarEle.appendChild(img);
	}
	
	// Les ajouter au <div> racine.
	rootEle.appendChild(windEle);
	windEle.appendChild(menuEle);
	if (this.type == SAWindow2.RESIZE_VERTICAL) {
		windEle.appendChild(rBarEle);
	}
	windEle.appendChild(contEle);

	// Terminer la construction des <div>.
	this.wind = new SAPanelInfo();
	this.wind.setId(windId);
	this.wind.addClassName("SAWindow2");			// classe système.
	this.wind.addClassName(windClass);				// classe de l'utilisateur.
	this.wind.autoFill();							// Après avoir fixé les className, sinon pas de styles valides !!

	this.menu = new SAPanelInfo();
	this.menu.setId(menuId);
	this.menu.addClassName("SAWindow2-menu");		// classe système.
	this.menu.addClassName(menuClass);				// classe de l'utilisateur.
	this.menu.autoFill();							// Après avoir fixé les className, sinon pas de styles valides !!

	this.cont = new SAPanelInfo();
	this.cont.setId(contId);
	this.cont.addClassName("SAWindow2-content");	// classe système.
	this.cont.addClassName(contClass);				// classe de l'utilisateur.
	this.cont.autoFill();							// Après avoir fixé les className, sinon pas de styles valides !!

	if (this.type == SAWindow2.RESIZE_VERTICAL) {
		this.resizeBar = new SAPanelInfo();
		this.resizeBar.setId(rBarId);
		this.resizeBar.addClassName("SAWindow2-resizeBar");	// classe système.
		this.resizeBar.autoFill();
	}


	return true;
}

SAWindow2.prototype = {
	
	computeHeight: function(rootDiv, panel) {
		var rootEle = rootDiv.getElement();
		return rootEle.offsetHeight - panel.getTotalAroundHeight();
	},

	computeWidth: function(rootDiv, panel) {
		var rootEle = rootDiv.getElement();
		return rootEle.offsetWidth - panel.getTotalAroundWidth();
	},

	setSize: function(panel, w, h) {
		panel.setSize(w, h);
	},

	setPos: function(panel, t, r, b, l) {
		panel.setPos(t, r, b, l);
	},
	
	setTopMin: function(minTop) {
		this.minTop = minTop;
	},
	
	setBotMin: function(minBot) {
		this.minBot = minBot;
	},
	
	addToTop: function(subDivId) {
		var subDivEle = document.getElementById(subDivId);
		this.menu.getElement().appendChild(subDivEle);
		subDivEle.style.display = "block";
	},

	addToBot: function(subDivId) {
		var subDivEle = document.getElementById(subDivId);
		this.cont.getElement().appendChild(subDivEle);
		subDivEle.style.display = "block";
	},
	
	addSubPack: function(funcall) {
		this.subPack = funcall;
	},
	addSubResize: function(funcall) {
		this.subResize = funcall;
	},
	
	showTopOnly: function() {
		this.menu.getElement().style.display = "block";
		this.cont.getElement().style.display = "none";
		this.resize(null, null, false);
//		var width = this.rootDiv.getElement().offsetWidth - this.wind.getTotalAroundWidth();
//		var height = this.rootDiv.getElement().offsetHeight - this.wind.getTotalAroundHeight();
		
	},
	showBottomOnly: function() {
		this.menu.getElement().style.display = "none";
		this.cont.getElement().style.display = "block";
	},
	showBoth: function() {
		this.menu.getElement().style.display = "block";
		this.cont.getElement().style.display = "block";
	},
	
	saveSize: function(oldWidth, oldHeight) {
		// La fenêtre va être masquée, conserver la hauteur du panneau
		// de contenu. On doit la conserver pour pouvoir remettre les
		// panneaux à la bonne proportion lorsque la fenêtre sera à
		// nouveau affichée (la fenêtre du navigateur a pu être 
		// redimensionnée pendant que la fenêtre SA était masquée).
		this.oldWindHeight = this.wind.getTotalHeight();
		//this.oldWindWidth = oldWidth;
		//this.oldWindHeight = oldHeight;
	},
	
	repack: function(type) {
		if (this.type == SAWindow2.RESIZE_VERTICAL) {
			this.oldMenuWidth = this.menu.getTotalWidth() - this.menu.getTotalAroundWidth();
			this.oldMenuHeight = this.menu.getTotalHeight() - this.menu.getTotalAroundHeight();
			
			if (isOpera()) {
				// Pourquoi faire ça sous Opera ????? Il le faut, mais je ne sais pas.
				
				var border = this.menu.getBorder();
				var padding = this.menu.getPadding();
				
				this.oldMenuHeight -= border[SAPanelInfo.TOP] + border[SAPanelInfo.BOTTOM];
				this.oldMenuHeight -= padding[SAPanelInfo.TOP] + padding[SAPanelInfo.BOTTOM];

				this.oldMenuWidth -= border[SAPanelInfo.LEFT] + border[SAPanelInfo.RIGHT];
				this.oldMenuWidth -= padding[SAPanelInfo.LEFT] + padding[SAPanelInfo.RIGHT];
			}
		}
		
		this.type = type;
		this.packDone = false;
		
		if (type == SAWindow2.RESIZE_VERTICAL) {
			this.pack(null, null, true, false);
		} else {
			this.pack(null, null, true, true);
		}
	},

	pack: function(rootWidth, rootHeight, force, initPack) {

		if (this.packDone && !force) return false;

		var rootDiv = this.rootDiv.getElement();

		// On ne pack que si le <div> qui contient la fenêtre est visible. 
		// Sinon, on ne peut lire la taille des <div> internes.
		if (rootDiv.style.display == "none") return;


		this.packDone = true;

		// Ajuster la taille du <div> de la fenêtre :
		//     width :  largeur du conteneur parent - entourage du <div> 
		//     height : hauteur du conteneur parent - entourage du <div> 
		var height, width;
		if (rootWidth != null) {
			width = rootWidth - this.wind.getTotalAroundWidth();
		} else {
			width = this.rootDiv.getElement().offsetWidth - this.wind.getTotalAroundWidth();
		}
		if (rootHeight != null) {
			height = rootHeight - this.wind.getTotalAroundHeight();
		} else {
			height = this.rootDiv.getElement().offsetHeight - this.wind.getTotalAroundHeight();
		}
		this.setSize(this.wind, width, height);

		var windWidth = width;
		var windHeight= height;
		
		var menuWidth, menuHeight;
		var contWidth, contHeight;

		// Placer les <div> selon le type d'agencement.
		if (this.type == SAWindow2.STATIC_TOP) {
			// <div> du haut : 		hauteur fixe - largeur variable
			// <div> de la barre : 	aucun
			// <div> du bas :		hauteur variable - largeur variable

			// Placer le <div> du haut et ajuster sa taille :
			//     width :  	largeur du conteneur parent - entourage du <div> 
			//     height : 	hauteur figée par style CSS 
			//	   position : 	en haut, à gauche
			this.setPos(this.menu, 0, null, null, 0);
			width = this.wind.getElement().offsetWidth - this.menu.getTotalAroundWidth();
			this.setSize(this.menu, width, null);
			
			menuWidth = width;
			menuHeight = this.menu.getTotalHeight();

			// Somme des hauteur des <div> précédents, pour les calculs de position
			// et de hauteur ultérieurs.
			var precHeight = this.menu.getTotalHeight();

			// Placer le <div> du bas et ajuster sa taille :
			//     width :  	largeur du conteneur parent - entourage du <div> 
			//     height : 	hauteur du conteneur parent - hauteur du haut - entourage du <div> 
			//	   position : 	sous le <div> du haut, à gauche
			this.setPos(this.cont, precHeight, null, null, 0);
			width = this.wind.getElement().offsetWidth - this.cont.getTotalAroundWidth();
			height = this.wind.getElement().offsetHeight - precHeight - this.cont.getTotalAroundHeight();
			this.setSize(this.cont, width, height);
			
			contWidth = width;
			contHeight = height;
		} else if (this.type == SAWindow2.ONLY_TOP) {
			// <div> du haut : 		hauteur variable - largeur variable
			// <div> de la barre : 	aucun
			// <div> du bas :		aucun

			// S'assurer que le panneau est visible.
			this.menu.getElement().style.display = "block";

			// Masquer les panneaux inutiles.
			this.cont.getElement().style.display = "none";
			if (this.resizeBar) {
				this.resizeBar.getElement().style.display = "none";
			}

			// Placer le <div> du haut et ajuster sa taille :
			//     width :  	largeur du conteneur parent - entourage du <div> 
			//     height : 	hauteur du conteneur parent - entourage du <div> 
			//	   position : 	en haut, à gauche
			this.setPos(this.menu, 0, null, null, 0);
			width = this.wind.getElement().offsetWidth - this.menu.getTotalAroundWidth();
			height = this.wind.getElement().offsetHeight - this.menu.getTotalAroundHeight();
			this.setSize(this.menu, width, height);
			
			menuWidth = width;
			menuHeight = height;

		} else if (this.type == SAWindow2.ONLY_BOTTOM) {
			// <div> du haut : 		aucun
			// <div> de la barre : 	aucun
			// <div> du bas :		hauteur variable - largeur variable

			// S'assurer que le panneau est visible.
			this.cont.getElement().style.display = "block";

			// Masquer les panneaux inutiles.
			this.menu.getElement().style.display = "none";
			if (this.resizeBar) {
				this.resizeBar.getElement().style.display = "none";
			}

			// Placer le <div> du bas et ajuster sa taille :
			//     width :  	largeur du conteneur parent - entourage du <div> 
			//     height : 	hauteur du conteneur parent - entourage du <div> 
			//	   position : 	en haut, à gauche
			this.setPos(this.cont, 0, null, null, 0);
			width = this.wind.getElement().offsetWidth - this.cont.getTotalAroundWidth();
			height = this.wind.getElement().offsetHeight - this.cont.getTotalAroundHeight();
			this.setSize(this.cont, width, height);
			
			contWidth = width;
			contHeight = height;

		} else if (this.type == SAWindow2.RESIZE_VERTICAL) {
			// <div> du haut : 		hauteur variable - largeur variable
			// <div> de la barre : 	hauteur fixe - largeur variable
			// <div> du bas :		hauteur variable - largeur variable

			// S'assurer que les panneaux sont visibles.
			this.menu.getElement().style.display = "block";
			this.cont.getElement().style.display = "block";
			this.resizeBar.getElement().style.display = "block";

			// Placer le <div> du haut et ajuster sa taille :
			//     width :  	largeur du conteneur parent - entourage du <div> 
			//     height : 	hauteur initiale fixée par style CSS
			//	   position : 	en haut, à gauche
			this.setPos(this.menu, 0, null, null, 0);
			if (initPack == true) {
				width = this.wind.getElement().offsetWidth - this.menu.getTotalAroundWidth();
				height = (this.wind.getElement().offsetHeight * 0.4) - this.menu.getTotalAroundHeight();
			} else {
				width = this.oldMenuWidth;
				height = this.oldMenuHeight;
			}
			this.setSize(this.menu, width, height);

			menuWidth = width;
			menuHeight = height;

			// Somme des hauteur des <div> précédents, pour les calculs de position
			// et de hauteur ultérieurs.

			var precHeight = this.menu.getTotalHeight();

			// Placer le <div> de la barre de redimensionnement et ajuster sa taille :
			//     width :  	largeur du conteneur parent - entourage du <div> 
			//     height : 	hauteur figée par style CSS 
			//	   position : 	sous le <div> du haut, à gauche
			this.setPos(this.resizeBar, precHeight, null, null, 0);
			width = this.wind.getElement().offsetWidth - this.resizeBar.getTotalAroundWidth();
			this.setSize(this.resizeBar, width, null);
			
			precHeight += this.resizeBar.getTotalHeight();

			// Placer le <div> du contenu et ajuster sa taille :
			//     width :  	largeur du conteneur parent - entourage du <div> 
			//     height : 	hauteur du conteneur parent - hauteur des <div> précéd. - entourage
			//	   position : 	sous le <div> de la barre de défilement, à gauche
			this.setPos(this.cont, precHeight, null, null, 0);
			width = this.wind.getElement().offsetWidth - this.cont.getTotalAroundWidth();
			height = this.wind.getElement().offsetHeight - precHeight - this.cont.getTotalAroundHeight();
			this.setSize(this.cont, width, height);
			
			contWidth = width;
			contHeight = height;
		}

		// Packer les sous-conteneurs du menu et du contenu, si existants.
		var subcont;
		if (this.menu.getElement().style.display != "none") {
			subcont = this.menu.getSubcont();
			if (subcont) {
				subcont.pack(menuWidth, menuHeight, force, initPack);
			}
		}
		if (this.cont.getElement().style.display != "none") {
			subcont = this.cont.getSubcont();
			if (subcont) {
				subcont.pack(contWidth, contHeight, force, initPack);
			}
		}
		
		if (this.subPack) {
			this.subPack(force);
		}
		
		return true;
	},
	
	resize:	function (rootWidth, rootHeight, synch) {
		
		var rootDiv = this.rootDiv.getElement();

		// On ne redimensionne que si le DIV qui contient la fenêtre
		// est visible. Sinon, on ne peut lire la taille des DIV internes.
		if (rootDiv.style.display == "none") return;

		// Lors d'une synchronisation, on prend l'ancienne hauteur du <div> de la fenêtre.
		// Sinon on prend celle actuelle (avant le redimensionnement). Cette valeur sert
		// aux dimensionnements proportionnels des autres <div>.
		//
		// !!! Ca ne marche pas parfaitement. Lorsque la partie "menu" est trop petite, elle
		// n'est pas redimensionnée.
		//
		var oldWindHeight = 0;
		if (synch == true) {
			oldWindHeight = this.oldWindHeight;
		} else {
			oldWindHeight = this.wind.getTotalHeight();
		}

		// Ajuster la taille du <div> de la fenêtre :
		//     width :  largeur du conteneur parent - entourage du <div> 
		//     height : hauteur du conteneur parent - entourage du <div> 
		var height, width;
		if (rootWidth != null) {
			width = rootWidth - this.wind.getTotalAroundWidth();
		} else {
			width = this.rootDiv.getElement().offsetWidth - this.wind.getTotalAroundWidth();
		}
		if (rootHeight != null) {
			height = rootHeight - this.wind.getTotalAroundHeight();
		} else {
			height = this.rootDiv.getElement().offsetHeight - this.wind.getTotalAroundHeight();
		}
		this.setSize(this.wind, width, height);

		var menuWidth, menuHeight;
		var contWidth, contHeight;


		// Ajuster la position et la taille les <div> selon le type d'agencement.
		if (this.type == SAWindow2.STATIC_TOP) {
			// <div> du haut : 		hauteur fixe - largeur variable
			// <div> de la barre : 	aucun
			// <div> du bas :		hauteur variable - largeur variable

			// Ajuster la taille du <div> du haut :
			//     width :  	largeur du conteneur parent - entourage du <div> 
			//     height : 	hauteur figée par style CSS 
			//	   position : 	inchangée
			width = this.wind.getElement().offsetWidth - this.menu.getTotalAroundWidth();
			this.setSize(this.menu, width, null);

			menuWidth = width;
			menuHeight = this.menu.getTotalHeight();

			// Somme des hauteur des <div> précédents, pour les calculs de position
			// et de hauteur ultérieurs.
			var precHeight = this.menu.getTotalHeight();

			// Placer le <div> du bas et ajuster sa taille :
			//     width :  	largeur du conteneur parent - entourage du <div> 
			//     height : 	hauteur du conteneur parent - hauteur du haut - entourage du <div> 
			//	   position : 	inchangée (taille du haut figée)
			width = this.wind.getElement().offsetWidth - this.cont.getTotalAroundWidth();
			height = this.wind.getElement().offsetHeight - precHeight - this.cont.getTotalAroundHeight();
			this.setSize(this.cont, width, height);

			contWidth = width;
			contHeight = height;

		} else if (this.type == SAWindow2.ONLY_TOP) {
			// <div> du haut : 		hauteur variable - largeur variable
			// <div> de la barre : 	aucun
			// <div> du bas :		aucun

			// Ajuster la taille du <div> du haut :
			//     width :  	largeur du conteneur parent - entourage du <div> 
			//     height : 	hauteur du conteneur parent - entourage du <div> 
			//	   position : 	inchangé
			width = this.wind.getElement().offsetWidth - this.menu.getTotalAroundWidth();
			height = this.wind.getElement().offsetHeight - this.menu.getTotalAroundHeight();
			this.setSize(this.menu, width, height);
			
			menuWidth = width;
			menuHeight = height;

		} else if (this.type == SAWindow2.ONLY_BOTTOM) {
			// <div> du haut : 		aucun
			// <div> de la barre : 	aucun
			// <div> du bas :		hauteur variable - largeur variable

			// Ajuster la taille du <div> du bas :
			//     width :  	largeur du conteneur parent - entourage du <div> 
			//     height : 	hauteur du conteneur parent - entourage du <div> 
			//	   position : 	inchangée
			width = this.wind.getElement().offsetWidth - this.cont.getTotalAroundWidth();
			height = this.wind.getElement().offsetHeight - this.cont.getTotalAroundHeight();
			this.setSize(this.cont, width, height);
			
			contWidth = width;
			contHeight = height;

		} else if (this.type == SAWindow2.RESIZE_VERTICAL) {
			// <div> du haut : 		hauteur variable - largeur variable
			// <div> de la barre : 	hauteur fixe - largeur variable
			// <div> du bas :		hauteur variable - largeur variable

			// Placer le <div> du haut et ajuster sa taille :
			//     width :  	largeur du conteneur parent - entourage du <div> 
			//     height : 	pourcentage de la hauteur du <div> conteneur
			//	   position : 	inchangée
			width = this.wind.getElement().offsetWidth - this.menu.getTotalAroundWidth();
			var windHeight = this.wind.getTotalHeight();
			var menuHeight = this.menu.getTotalHeight() - this.menu.getTotalAroundHeight();
			var ratio = menuHeight / oldWindHeight;
			
			height = parseInt(Number(ratio * windHeight).toFixed());

			// Je ne sais pas pourquoi il faut faire ça sous Opera...
			if (isOpera()) {
				var border = this.menu.getBorder();
				var padding = this.menu.getPadding();
				
				height -= border[SAPanelInfo.TOP] + border[SAPanelInfo.BOTTOM];
				height -= padding[SAPanelInfo.TOP] + padding[SAPanelInfo.BOTTOM];
			}
			
			this.setSize(this.menu, width, height);

			menuWidth = width;
			menuHeight = height;

			// Somme des hauteur des <div> précédents, pour les calculs de position
			// et de hauteur ultérieurs.
			var precHeight = this.menu.getTotalHeight();

			// Placer le <div> de la barre de redimensionnement et ajuster sa taille :
			//     width :  	largeur du conteneur parent - entourage du <div> 
			//     height : 	hauteur figée par style CSS 
			//	   position : 	sous le <div> du haut, à gauche
			this.setPos(this.resizeBar, precHeight, null, null, 0);
			width = this.wind.getElement().offsetWidth - this.resizeBar.getTotalAroundWidth();
			this.setSize(this.resizeBar, width, null);
			
			precHeight += this.resizeBar.getTotalHeight();

			// Placer le <div> du contenu et ajuster sa taille :
			//     width :  	largeur du conteneur parent - entourage du <div> 
			//     height : 	hauteur du conteneur parent - hauteur des <div> précéd. - entourage
			//	   position : 	sous le <div> de la barre de défilement, à gauche
			this.setPos(this.cont, precHeight, null, null, 0);
			width = this.wind.getElement().offsetWidth - this.cont.getTotalAroundWidth();
			height = this.wind.getElement().offsetHeight - precHeight - this.cont.getTotalAroundHeight();
			this.setSize(this.cont, width, height);
			
			contWidth = width;
			contHeight = height;
			
		}
		
		// Redimensionner les sous-conteneurs du menu et du contenu, si existants. Il n'y
		// a pas de synchronisation.
		var subcont;
		if (this.menu.getElement().style.display != "none") {
			subcont = this.menu.getSubcont();
			if (subcont) resize(menuWidth, menuHeight, false);
		}
		if (this.cont.getElement().style.display != "none") {
			subcont = this.cont.getSubcont();
			if (subcont) subcont.resize(contWidth, contHeight, false);
		}

		return;
	},
	
	startDrag: function(bound, eve) {
		
		// Cas de IE qui ne passe pas l'événement dans le gestionnaire d'événements.
		var e = eve ||window.event;
		
		var rBarEle = this.resizeBar.getElement();
		
		// Position de la souris (en coordonnées de fenêtre) au début du glissement.
    	var debutX = e.clientX, debutY = e.clientY;
	    // Position d’origine (en coordonnées de document) de la barre.
    	var origX = rBarEle.offsetLeft, origY = rBarEle.offsetTop;
		// Tenir compte des décalages.
		var deltaX = debutX - origX, deltaY = debutY - origY;
	
		// Configurer la gestion des événements de la souris.
		startDrag(bound.getElement(), dragResizeBar, e);
		
		// Référence à cet objet de contenu (pour y faire référence dans resize()
		// et dans dragResizeBar().
		var thisObject = this;
		
		/**
		 * Voici le gestionnaire qui capture les événements mousemove lorsque
		 * l’utilisateur fait glisser la barre de défilement.
		 **/
		 
		function dragResizeBar(e) {
			if (!e) e = window.event;  // Modèle d’événements d’IE.

			var newPos = e.clientY - deltaY;
			thisObject.internalResize(bound, thisObject, newPos);
			
			if (e.stopPropagation) e.stopPropagation();  // DOM Niveau 2.
			else e.cancelBubble = true;                  // IE.
		}

		return;
	},
	
	
	/**
	 * Appelée depuis dragResizeBar(), les paramètres content et newBarPos
	 * sont définis.
	 */
	internalResize:	function (bound, saWind, newBarPos) {
		
		var boundEle = bound.getElement();
		
		if (saWind.type == SAWindow2.RESIZE_VERTICAL) {	
			// <div> du haut : 		hauteur variable - largeur variable
			// <div> de la barre : 	hauteur fixe - largeur variable
			// <div> du bas :		hauteur variable - largeur variable

			// Limiter les déplacements à la zone indiquée (bound). On sait que le
			// <div> du haut est en position haute (0).
			var topLimit = saWind.menu.getTotalAroundHeight();
			var botLimit = boundEle.offsetHeight - saWind.cont.getTotalAroundHeight();
			var rBarHeight = saWind.resizeBar.getTotalHeight();

			if (saWind.minTop) {
				topLimit = saWind.minTop;
			}
			if (saWind.minBot) {
				botLimit = boundEle.offsetHeight - saWind.minBot;
			}

			if (newBarPos <= topLimit) {
				return;
			} else if (newBarPos + rBarHeight >= botLimit) {
				return;
			}

			// Placer le <div> du haut et ajuster sa taille :
			//     width :  	largeur du conteneur parent - entourage du <div> 
			//     height : 	fonction de la nouvelle position de la barre de redimensionnement
			//	   position : 	inchangée
			width = saWind.wind.getElement().offsetWidth - saWind.menu.getTotalAroundWidth();
			height = newBarPos - saWind.menu.getTotalAroundHeight();
			saWind.setSize(saWind.menu, width, height);

			// Somme des hauteur des <div> précédents, pour les calculs de position
			// et de hauteur ultérieurs.
			var precHeight = saWind.menu.getTotalHeight();

			// Placer le <div> de la barre de redimensionnement et ajuster sa taille :
			//     width :  	largeur du conteneur parent - entourage du <div> 
			//     height : 	hauteur figée par style CSS 
			//	   position : 	sous le <div> du haut, à gauche
			saWind.setPos(saWind.resizeBar, precHeight, null, null, 0);
			width = saWind.wind.getElement().offsetWidth - saWind.resizeBar.getTotalAroundWidth();
			saWind.setSize(saWind.resizeBar, width, null);
			
			precHeight += saWind.resizeBar.getTotalHeight();

			// Placer le <div> du contenu et ajuster sa taille :
			//     width :  	largeur du conteneur parent - entourage du <div> 
			//     height : 	hauteur du conteneur parent - hauteur des <div> précéd. - entourage
			//	   position : 	sous le <div> de la barre de défilement, à gauche
			saWind.setPos(saWind.cont, precHeight, null, null, 0);
			width = saWind.wind.getElement().offsetWidth - saWind.cont.getTotalAroundWidth();
			height = saWind.wind.getElement().offsetHeight - precHeight - saWind.cont.getTotalAroundHeight();
			saWind.setSize(saWind.cont, width, height);
			
			
			if (this.subResize) {
				this.subResize();
			}
		}
		

		return;
	}
	
}


SAWindow2.RESIZE_VERTICAL = 1;
SAWindow2.STATIC_TOP = 		2;
SAWindow2.ONLY_TOP = 		3;
SAWindow2.ONLY_BOTTOM= 		4;


//##################################################################################
//##################################################################################
//##################################################################################
//##################################################################################
//##################################################################################

//##################################################################################
//##################################################################################
//##################################################################################
//##################################################################################
//##################################################################################

//##################################################################################
//##################################################################################
//##################################################################################
//##################################################################################
//##################################################################################



/*
// This function is used to define if the browser supports the needed
// features
function hasSupport() {

	if (typeof hasSupport.support != "undefined")
		return hasSupport.support;
	
	var ie55 = /msie 5\.[56789]/i.test( navigator.userAgent );
	
	hasSupport.support = ( typeof document.implementation != "undefined" &&
			document.implementation.hasFeature( "html", "1.0" ) || ie55 )
			
	// IE55 has a serious DOM1 bug... Patch it!
	if ( ie55 ) {
		document._getElementsByTagName = document.getElementsByTagName;
		document.getElementsByTagName = function ( sTagName ) {
			if ( sTagName == "*" )
				return document.all;
			else
				return document._getElementsByTagName( sTagName );
		};
	}

	return hasSupport.support;
}
*/

///////////////////////////////////////////////////////////////////////////////////
// The constructor for SA windows.
//
// wind : HTMLElement	The html element used to represent the window
// menu : HTMLElement	The html element used to represent the menu
// cont : HTMLElement	The html element used to represent the content
//
function SAWindow( wind, menu, cont) {
	//if ( !hasSupport() || wind == null ) return;
	
	if ( wind == null ) return;
	
	this.wind = wind;
	this.menu = menu;
	this.content = cont;
	this.SAcontent = undefined;
	
	// Ajouter la classe d'une fenêtre SA à l'élément qui représente
	// cette fenêtre.
	this.wind.className = this.classNameTag + " " + this.wind.className;

	// Idem pour le menu et le contenu.
	this.menu.className = this.menu_classNameTag + " " + this.menu.className;
	this.content.className = this.content_classNameTag + " " + this.content.className;


}

SAWindow.prototype = {

	classNameTag:			"sa-window",
	menu_classNameTag:		"sa-menu",
	content_classNameTag:	"sa-content",

	pack: function (rootDiv) {

		// On ne pack que si le DIV qui contient la fenêtre
		// est visible. Sinon, on ne peut lire la taille des DIV internes.
		if (rootDiv.style.display == "none") return;

		// Ajuster la taille des panneaux menu et contenu.
		var windHeight = this.wind.offsetHeight;
		var menuHeight = this.menu.offsetHeight;
		var contHeight = windHeight - menuHeight;

/*
		//!!!!
		var compStyle = window.getComputedStyle(this.content, null);
		var pt = parseInt(compStyle.paddingTop);
		var mt = parseInt(compStyle.marginTop);
		var bt = parseInt(compStyle.borderTopWidth);
		var bb = parseInt(compStyle.borderBottomWidth);
		contHeight -= (pt + mt + bt + bb);
		//!!!
*/
		
		this.content.style.height = contHeight + 'px';
		
		// Construire le contenu.
		var done = false;
		if (this.SAcontent != undefined) {
			done = this.SAcontent.pack(this.content);
		}
		return done;
	},

	saveSize: function (rootDiv) {
		// La fenêtre va être masquée, conserver la hauteur du panneau
		// de contenu. On doit la conserver pour pouvoir remettre les
		// panneaux à la bonne proportion lorsque la fenêtre sera à
		// nouveau affichée (la fenêtre du navigateur a pu être 
		// redimensionnée pendant que la fenêtre SA était masquée).
		this.oldContentHeight = this.content.offsetHeight;
	},

	resize:	function (rootDiv, synch) {
		
		// On ne redimensionne que si le DIV qui contient la fenêtre
		// est visible. Sinon, on ne peut lire la taille des DIV internes.
		if (rootDiv.style.display == "none") return;
		
		// Mémoriser la taille précédente du volet de contenu. Pour une
		// resynchronisation, on celle sauvegardé par saveSize(). Sinon
		// on prend celle actuelle (avant le redimensionnement).
		var oldContHeight = 0;
		if (synch == true) {
			oldContHeight = this.oldContentHeight;
		} else {
			oldContHeight = this.content.offsetHeight;
		}

		// Ajuster la taille des panneaux menu et contenu.
		var windHeight = this.wind.offsetHeight;
		var menuHeight = this.menu.offsetHeight;
		var contHeight = windHeight - menuHeight;
		this.content.style.height = contHeight + 'px';

		// Ajuster la taille du contenu.
		if (this.SAcontent != undefined) {
			this.SAcontent.resizeFromBrowser(this.content, oldContHeight);
		}
		
		return;
	},
	
	setContent:	function (cont) {
		this.SAcontent = cont;
		return;
	},
	
	changeMode: function (mode) {
		if (this.SAcontent != undefined) {
			this.SAcontent.changeMode(this.content, mode);
		}
		return;
	},

	dragContentPanels: function (myEvent) {
		if (this.SAcontent != undefined) {
			this.SAcontent.drag(this.content, myEvent);
		}
		return;
	}
	
};


///////////////////////////////////////////////////////////////////////////////////
// The constructor for SA content.
//
// panel1 : HTMLElement	The html element used to represent the first panel
// panel2 : HTMLElement	The html element used to represent the second panel
// bar : HTMLElement	The html element used to represent the resize bar
// type	: int			An int specifing the type of the content layout
//
function SAContent( panel1, panel2, bar, type) {
	//if ( !hasSupport() || wind == null ) return;
	
	this.panel1 = panel1;
	this.panel2 = panel2;
	this.bar = bar;
	this.type = type;
	this.packDone = false;
	this.mode = undefined;
	
	if (this.type == SAContent.VERT) {
		
		//
		this.toggleStatus = SAContent.VERT_CENTER;
	
		// Ajuster les classes
		this.panel1.className = this.topPanel_classNameTag + " " + this.panel1.className;
		this.panel2.className = this.botPanel_classNameTag + " " + this.panel2.className;
		this.bar.className = this.horBar_classNameTag + " " + this.bar.className;
	}
}

SAContent.prototype = {

	topPanel_classNameTag:		"sa-top-panel",
	botPanel_classNameTag:		"sa-bot-panel",
	horBar_classNameTag:		"sa-hor-resizebar",

	changeMode: function (bound, mode) {
		this.mode = mode;
		
		if (mode == SAContent.FULL_BOTTOM) {
			this.resize(bound, this, 0);
		} else if (mode == SAContent.FULL_TOP) {
			this.resize(bound, this, bound.offsetHeight - this.bar.offsetHeight);
		} else if (mode == SAContent.FULL_FREE) {
			this.resize(bound, this, this.bar.offsetTop);
		}
		return;
	},


	pack: function (bound) {
		
		//alert("Packing : " + bound.id);
		
		if (!this.packDone) {
			this.packDone = true;
			this.mode = SAContent.FULL_FREE;
			this.resize(bound, this, (bound.offsetHeight - this.bar.offsetHeight)/2);
			// On a fait le pack;
			return true;
		} else {
			// On n'a pas fait le pack;
			return false;
		}
	},

	resizeFromBrowser: function(bound, oldHeight) {

		//alert("Resizing browser " + bound.id);

		var contObject = this;
		
		if (contObject.type == SAContent.VERT) {
	
			var boundHeight = bound.offsetHeight;

			var topPanelPos = 0;
			var topPanelHeight;

			var resizeBarPos = 0;
			var resizeBarHeight = contObject.bar.offsetHeight;

			var botPanelPos = 0;
			var botPanelHeight = 0;

			if (contObject.mode == SAContent.FULL_BOTTOM) {
				topPanelHeight = 0;
				resizeBarPos = 0;
				botPanelPos = resizeBarHeight;
				botPanelHeight = boundHeight - resizeBarHeight;
			} else if (contObject.mode == SAContent.FULL_TOP) {
				topPanelHeight = boundHeight - resizeBarHeight;
				resizeBarPos = boundHeight - resizeBarHeight;
				botPanelPos = boundHeight - resizeBarHeight;
				botPanelHeight = 0;
			} else if (contObject.mode == SAContent.FULL_FREE) {
				// Calculer les tailles relatives par rapport à l'ancienne
				// dimension.
				if (oldHeight == 0) oldHeight = 1;
				var topPanelRatio = contObject.panel1.offsetHeight / oldHeight;
				topPanelHeight = parseInt(Number(topPanelRatio * boundHeight).toFixed());
				resizeBarPos = topPanelHeight;
				botPanelPos = resizeBarPos + resizeBarHeight;
				botPanelHeight = boundHeight - topPanelHeight - resizeBarHeight;
			} else {
				alert("Wrong mode");
			}


			contObject.panel1.style.height = topPanelHeight + "px";
			contObject.panel1.style.top = topPanelPos + "px";

			contObject.bar.style.height = resizeBarHeight + "px";
			contObject.bar.style.top = resizeBarPos + "px";

			contObject.panel2.style.height = botPanelHeight + "px";
			contObject.panel2.style.top = botPanelPos + "px";

			
		}

		return;
	},


	/**
	 * Appelée depuis dragResizeBar(), les paramètres content et newBarPos
	 * sont définis.
	 */
	resize:	function (bound, content, newBarPos) {
		
		var contObject;
		
		if (content != undefined) {
			contObject = content;
		} else {
			contObject = this;
		}
			
		if (contObject.type == SAContent.VERT) {
	
			var boundHeight = bound.offsetHeight;

			var topPanelPos = 0;
			var topPanelHeight;

			var resizeBarPos = 0;
			var resizeBarHeight = contObject.bar.offsetHeight;

			var botPanelPos;
			var botPanelHeight;

			if (newBarPos != undefined) {
				// Positionnement explicite de la resize bar.

				// Garder la barre dans les limites de l'élément de bound.
				if (newBarPos < 0) {
					newBarPos = 0;
					// !!!!!!
					// 
					// Problème: si le contenu contient un élément ayant une hauteur
					// minimum, la barre de défilement passe par dessus. Il faudrait
					// vérifier jusqu'où on peut réduire le panneau.
					//
					// !!!!!!
				} else if (newBarPos > (boundHeight - resizeBarHeight)) {
					newBarPos = boundHeight - resizeBarHeight;
				}
				
				// Calculer les nouvelles dimensions et positions des panels.
				resizeBarPos = newBarPos;
				topPanelHeight = resizeBarPos;
				botPanelPos = resizeBarPos + resizeBarHeight;
				botPanelHeight = boundHeight - topPanelHeight - resizeBarHeight;
			}
			
			contObject.panel1.style.height = topPanelHeight + "px";
			contObject.panel1.style.top = topPanelPos + "px";

			contObject.panel2.style.height = botPanelHeight + "px";
			contObject.panel2.style.top = botPanelPos + "px";

			contObject.bar.style.height = resizeBarHeight + "px";
			contObject.bar.style.top = resizeBarPos + "px";
			
		}

		return;
	},
	
	drag: function (bound, myEvent) {
		
		this.mode = SAContent.FULL_FREE;
		
		//this.setMode(bound, SAContent.FULL_FREE);

		// Position de la souris (en coordonnées de fenêtre) au début du glissement.
    	var debutX = myEvent.clientX, debutY = myEvent.clientY;
	    // Position d’origine (en coordonnées de document) de la barre.
    	var origX = this.bar.offsetLeft, origY = this.bar.offsetTop;
		// Tenir compte des décalges.
		var deltaX = debutX - origX, deltaY = debutY - origY;
	
		// Configurer la gestion des événements de la souris.
		startDrag(bound, dragResizeBar, myEvent);
		
		// Référence à cet objet de contenu (pour y faire référence dans resize()
		// et dans dragResizeBar().
		var thisObject = this;
		
		/**
		 * Voici le gestionnaire qui capture les événements mousemove lorsque
		 * l’utilisateur fait glisser la barre de défilement.
		 **/
		function dragResizeBar(e) {
			if (!e) e = window.event;  // Modèle d’événements d’IE.

			var newPos = e.clientY - deltaY;
			thisObject.resize(bound, thisObject, newPos);
			
			if (e.stopPropagation) e.stopPropagation();  // DOM Niveau 2.
			else e.cancelBubble = true;                  // IE.
		}

		return;
	}

};


SAContent.VERT = 1;

SAContent.VERT_TOP = 	1;
SAContent.VERT_BOTTOM = 2;
SAContent.VERT_CENTER = 3;

SAContent.FULL_BOTTOM =	1;
SAContent.FULL_TOP =	2;
SAContent.FULL_FREE =	3;


///////////////////////////////////////////////////////////////////////////////////
// Tools.


function isIE() {
	var ie = /msie/i.test(navigator.userAgent);
	return ie;
}
