function fullfill(info,form,element,newclass){
	var selelem = document.forms[form].elements[element];

	if (info!= ''){
		selelem.value = info;
	}
	switch(newclass){
		case 'ok':
			selelem.className="citiesOK";
			break;
		case 'ko':
			selelem.className="citiesKO";
			break;
		case 'hd':
			selelem.className="cities";
			break;
	}
}
function applic(form,element){
	var ind = document.forms[form].elements[element].options[document.forms[form].elements[element].selectedIndex].value;
	if (ind != ''){
		eval (ind);
	}
}


var it_popupDecorator = {
	outputHeader: function(builder) { builder.a('<table class="style1Bg" cellpadding="0" cellspacing="0" border="0"><tr><td class="style1LeftCorner style1LeftBorderWidth popupLeftCorner"></td><td class="style1Top popupTop"></td><td class="style1RightCorner style1RightBorderWidth popupRightCorner"></td></tr><tr><td class="style1Left popupLeft">&nbsp;</td><td id="PopupContent">'); },
	outputFooter: function(builder) { builder.a('</td><td class="style1Right popupRight">&nbsp;</td></tr><tr><td class="style1LeftBotCorner style1LeftBorderWidth popupLeftBotCorner"></td><td class="style1Bot popupBot"></td><td class="style1RightBotCorner style1RightBorderWidth popupRightBotCorner"></td></tr></table>'); }
};
var it_infoPopupDecorator = {
	outputHeader: function(builder, options) {
		builder.a('<table id="infoPopup" class="infoPopup');
		if (options && options.infoPopupDecoratorClass) {
			builder.a(' ').a(options.infoPopupDecoratorClass).a('"');
		}
		builder.a('"><tr><td colspan="3" id="infoStyle">')
	},
	outputFooter: function(builder) { builder.a('</td></tr></table>'); }
}

//--------------------------------------------------//
//------------------- Popup Library ----------------//
//--------------------------------------------------//
function it_SingletonPopup() {
	var visible = false;
	var currentName = null;
	var currentContent;
	var currentOptions;
	var container;
	
	var self = this;
	
	var getContainer = function() {
		// lazy instanciation because injectInside(document.body) can crash IE
		if (container == null) {
			//console.log("container init");
			container = new Element("div")
				.setProperty("id", "bulle")
				.setStyles({
					"zIndex": "100",
					"position": "absolute",
					"top": "0",
					"left": "0",
					"visibility": "hidden"
				})
				.injectInside(document.body);
			container.onmouseover = it_Utils.delegate(self, self.popupMouseOver);
			container.onmouseout = it_Utils.delegate(self, self.popupMouseOut);
		}
		return container;
	}
	var hide = function() {
		//console.log("hide");
		clearPopupTimeout();
		if (!visible) {
			// can happen if another popup is opened and hide() has already been called
			return;
		}
		getContainer().style.visibility = "hidden";
		visible = false;
		currentName = null;
		if ($type(currentContent) == "element") {
			currentContent.remove(); // to reuse it in IE
		}
		currentContent = null;
	}
	var popupTimeout = function() {
		if (this.timeoutId == null) { // sometimes, we have "trigger out, popup out" , without a "popup over"
			this.timeoutId = setTimeout(hide, currentOptions.closeTimeOut);
		}
	}
	var clearPopupTimeout = function() {
		if (this.timeoutId != null) {
			clearTimeout(this.timeoutId);
			this.timeoutId = null;
		}
	}
	var setContent = function(content) {
		currentContent = content;
		getContainer().innerHTML = "";
		if ($type(content) == "function") {
			// we unwrap the content out of the function
			content = content(currentOptions);
			setContent(content); // content can be another Function, an Element or a String
		} else if ($type(content) == "element") {
			// element
			getContainer().adopt(content);
		} else {
			// string
			if (currentOptions.decorator) {
				var decorator = currentOptions.decorator;
				if ($type(decorator) == "array") {
					decorator.forEach(function(singleDecorator) { content = it_Utils.decorate(content, singleDecorator, currentOptions); });
				} else {
					content = it_Utils.decorate(content, decorator, currentOptions);
				}
			}
			getContainer().innerHTML = content;
		}
	}
	/**
	 * @param name: name of the instance
	 * @param content can be a Function, an Element or a direct String
	 * @param options:
	 *	. all the PositionUtils.alignmentOptions
	 *	. style (optional): appended to the style property
	 *	. closeTimeOut (in ms) (optional, default: 500)
	 *	. allowMouseOverPopup (optional, default: true)
	 *  . repositionOnMouseMove (optional, default: false)
	 *  . decorator (optional, default: null) a decorator or an Array. Not applicable with div content
	 *	. mode (optional, default: null)
	 *		. "info":
	 * 			. anchorY: "trigger"
	 *			. closeTimeOut: 0
	 *			. allowMouseOverPopup: false
	 *			. repositionOnMouseMove: true
	 *			. decorator: it_popupDecorator added
	 * @param event: sent by Firefox. For IE, mootools gets the event using window.event
	 */
	this.triggerMouseOver = function(name, content, options, event) {
		//console.log("trigger over name: " + name + ", currentName: " + currentName + ", visible: " + visible);
		if (visible && name == currentName) {
			clearPopupTimeout();
			return;
		}
		if (visible) {
			// another popup is open
			//console.log("trigger over, hide");
			hide();
		}
		//-- options --//
		currentName = name; // currentContent is set in setContent because it could be a div, but wrapped in a function
		options = options || {}; // if absent, options.treated is useless
		currentOptions = options;
		if (!options.treated) { // we modify the options (not currentOptions), to do it once
			if (options.mode && options.mode == "info") {
				it_Utils.setIfAbsent(options, {
					closeTimeOut: 0,
					allowMouseOverPopup: false,
					repositionOnMouseMove: true,
					anchorY: "trigger"
				});
				// decorator
				var decorator = it_Utils.ensureArray(options.decorator);
				decorator.push(it_infoPopupDecorator);
				decorator.push(it_popupDecorator);
				options.decorator = decorator;
			}
			it_Utils.setIfAbsent(options, {
				closeTimeOut: 500,
				allowMouseOverPopup: true,
				repositionOnMouseMove: false
			});
			// closeTimeOut
			if (options.closeTimeOut < 100) {
				options.closeTimeOut = 100; // sometimes, instead of "over", we have a fast "over, out, over", so have to let the last over call clearTimeOut
			}
			options.treated = true;
		}
		
		var triggerEl = null;
		if (event != null) {
			triggerEl = new Event(event).target;
		}
		visible = true;
		setContent(content);
		PositionUtils.calculateAndSetPos(triggerEl, getContainer(), options);
		getContainer().style.visibility = "visible";
	}
	this.triggerMouseOut = function(name, event) {
		//console.log("trigger out");
		if (name == currentName) {
			//console.log("trigger out start timeout");
			popupTimeout();
		}
	}
	this.triggerMouseMove = function(event) {
		//console.log("trigger move");
		if (currentName == null) {
			// protection because IE can call it before over
			return;
		}
		if (!visible) { // can happen if we have a "popup out" right after a "trigger out"
			this.triggerMouseOver(currentName, currentContent, currentOptions, event);
		} else {
			if (currentOptions.repositionOnMouseMove) {
				if (event != null) {
					event = new Event(event);
				}
				PositionUtils.calculateAndSetPos(event.target, getContainer(), currentOptions);
			}
		}
	}
	this.triggerForceHide = function(name, event) {
		if (name == currentName) {
			hide();
		}
	}
	this.popupMouseOver = function() {
		//console.log("popup over");
		if (currentOptions.allowMouseOverPopup) {
			clearPopupTimeout();
		}
	}
	this.popupMouseOut = function() {
		//console.log("popup out, visible: " + visible);
		// we can have the mouse on the popup even if allowMouseOverPopup is false
		// because the hide timeout is 100 ms min
		if (currentOptions.allowMouseOverPopup && visible) {
			popupTimeout();
		}
	}
	
	this.shortMessage = function(content, options, event) {
		options = options || {};
		options.allowMouseOverPopup = false;
		options.closeTimeOut = 2000;
		this.triggerMouseOver("shortMessage", content, options, event);
		this.triggerMouseOut("shortMessage", event);
	}
}

var it_singletonPopup = new it_SingletonPopup();

function it_PopupUtilsClass() { // all functions are static

	this.link = function(content, triggerEl, options) {
		var triggerFunctions = createTriggerMouseFunctions(content, options);
		triggerEl = $(triggerEl);
		triggerEl.onmouseover = triggerFunctions.mouseOver;
		triggerEl.onmouseout = triggerFunctions.mouseOut;
		triggerEl.onmousemove = triggerFunctions.mouseMove;
	}
	
	/**
	 * @param content can be a Function, an Element or a direct String
	 */
	var createTriggerMouseFunctions = function(content, options) { // :Object containing mouseOver and mouseOut functions
		if ($type(content) == "element") {
			content.remove(); // so that it becomes invisible and that it can be added later
		}
		var name = "popupLink" + it_nextRef();
		return {
			mouseOver: function(event) { it_singletonPopup.triggerMouseOver(name, content, options, event); },
			mouseOut: function(event) { it_singletonPopup.triggerMouseOut(name, event); },
			mouseMove: function(event) { it_singletonPopup.triggerMouseMove(event); }
		};
	}
	
	/**
	 * used double-quotes for attributes
	 */
	this.appendEventAttributes = function(content, options, builder) {
		var triggerFunctions = createTriggerMouseFunctions(content, options);
		builder.a(' onmouseover="it_registry.call(\'').a(it_registry.register(triggerFunctions.mouseOver)).a('\', event)"')
			.a(' onmouseout="it_registry.call(\'').a(it_registry.register(triggerFunctions.mouseOut)).a('\', event)"')
			.a(' onmousemove="it_registry.call(\'').a(it_registry.register(triggerFunctions.mouseMove)).a('\', event)"');
	}
}
var it_PopupUtils = new it_PopupUtilsClass();

//-------------------------------------//
//------------- ref2Object ------------//
//-------------------------------------//
// use with caution: can cause memory leaks
function it_Registry() {
	var refToObject = {};
	
	this.register = register;
	this.getObject = getObject;
	this.call = call;
	
	function register(obj) { // :String
		var ref = "Obj" + it_nextRef();
		refToObject[ref] = obj;
		return ref;
	}
	
	function getObject(ref) { // :Object
		return refToObject[ref];
	}
	
	function call(functionRef, arg0, arg1, arg2) { // :void
		getObject(functionRef).call(window, arg0, arg1, arg2);
	}
}

var it_registry = new it_Registry();



function DockAndPopup(containerDivId, dockDivId, popupDivId, closedSize, openedSize) {
	this.containerDiv = $(containerDivId);
	this.dockDiv = $(dockDivId);
	this.popupDiv = $(popupDivId);
	this.closedSize = closedSize;
	this.openedSize = openedSize;
	
	var self = this;
	var opened = false;
	var opening = false;
	var moving = false;
	
	this.containerDiv.onmouseover = containerEntered;
	this.containerDiv.onmouseout = containerExited;
	
	this.closingTimerId = 0;
	
	function containerEntered() {
		if (self.closingTimerId != 0) {
			clearTimeout(self.closingTimerId);
			self.closingTimerId = 0;
		}
		if (!moving && !opened) {
			open();
		}
	}
	function containerExited() {
		if (opening || opened) {
			self.closingTimerId = setTimeout(close, 500);
		}
	}
	
	function open() {
		moving = true;
		opening = true;
		new Effect.Size(self.containerDiv, openedSize, null, 100, 10, {complete:function() {setOpened(true);}});
		hide(self.dockDiv);
		show(self.popupDiv);
	}
	function close() {
		moving = true;
		new Effect.Size(self.containerDiv, closedSize, null, 100, 10, {complete:function() {setOpened(false);}});
		show(self.dockDiv);
		hide(self.popupDiv);
	}
	function setOpened(openedArg) {
		opened = openedArg;
		opening = false;
		moving = false;
	}
	function show(div) {
		div.style.visibility = "visible";
		new Effect.FadeTo(div, 1, 100, 5);
	}
	function hide(div) {
		new Effect.FadeTo(div, 0, 100, 5, {complete:function() {div.style.visibility = "hidden";}});
	}
}


// needs core.js
/**
 * listener interface:
 * . opened(toggler)
 * . closed(toggler)
 */
function OpenCloseToggler(prefix) {
	var containerDiv = $(prefix + "Container");
	var contentDiv = $(prefix + "Content");
	this.listener = null;
	
	this.toggle = toggle;
	this.open = open;
	this.close = close;
	this.isOpen = isOpen;
	
	containerDiv.style.height = "1px"; // 0px doesn't work in IE
	containerDiv.style.overflow = "hidden";
	containerDiv.it_open = false;
	
	function toggle() {
		if (!this.isOpen()) {
			this.open();
		} else {
			this.close();
		}
	}
	
	function open() {
		if (!this.isOpen()) {
			containerDiv.it_open = true;
			it_Animation.toHeight(containerDiv, contentDiv.offsetHeight);
			if (this.listener != null) {
				this.listener.opened(this);
			}
		} else {
			// height check
			if (containerDiv.offsetHeight != contentDiv.offsetHeight) {
				it_Animation.toHeight(containerDiv, contentDiv.offsetHeight);
			}
		}
	}
	
	function close() {
		if (this.isOpen()) {
			containerDiv.it_open = false;
			it_Animation.toHeight(containerDiv, 1); 
			if (this.listener != null) {
				this.listener.closed(this);
			}
		} else {
			// height check
			if (containerDiv.offsetHeight != 1) {
				it_Animation.toHeight(containerDiv, 1);
			}
		}
	}
	
	function isOpen() {
		return containerDiv.it_open;
	}
}

function it_AnimationClass() {
	this.show = show;
	this.toggle = toggle;
	this.toHeight = toHeight;
	
	function show(parent, child, options) {
		var withAnimation = it_Utils.getProperty(options, "withAnimation", true);
		var parentDiv = $(parent);
		var childDiv = $(child);
		var newHeight = ( childDiv.getTop() + childDiv.offsetHeight ) - parentDiv.getTop();
		this.toHeight(parentDiv, newHeight, withAnimation);
	}
	
	function toggle(parent, child) {
		var parentDiv = $(parent);
		var childDiv = $(child);
		if (parentDiv.it_open) {
			this.toHeight(parentDiv, parentDiv.it_initialHeight);
			parentDiv.it_open = false;
		} else {
			parentDiv.it_initialHeight = parentDiv.offsetHeight;
			this.show(parent, child);
			parentDiv.it_open = true;
		}
		return parentDiv.it_open;
	}

	/**
	 * . withAnimation can be null (default to true)
	 */
	function toHeight(parentDiv, newHeight, withAnimation) {
		withAnimation = (withAnimation != null) ? withAnimation : true;
		if (withAnimation) {
			new Fx.Style(parentDiv, "height", {duration: 500, transition: Fx.Transitions.quartOut})
				.custom(parentDiv.offsetHeight, newHeight);
		} else {
			parentDiv.style.height = newHeight + "px";
		}
	}
}
var it_Animation = new it_AnimationClass();

function it_ShowHideToggler(div, startHeight) {
	div = $(div);
	startHeight = startHeight ? startHeight : 1;
	var parent = it_Utils.createParentDiv(div).setStyles({
		"position": "relative",
		"overflow": "hidden",
		"zIndex": "2", // for opacity purposes
		"height": startHeight + "px"
	});
	div.setStyles({
		"position": "absolute",
		"top": "0px",
		"left": "0px"
	});
	
	this.toggle = toggle;
	
	function toggle() {
		it_Animation.toggle(parent, div);
	}
}
