function QW_AJAX() {
	var currentXhr = null;
	var currentIsResponseXml = false;

	/**
	* Télécharge un fichier et déclenche un méthode à l'arrivée du fichier
	*
	* @param url           URL
	* @param callback      Nom de fonction (string) ou null. Si null, la fonction sera bloquante et renverra le contenu du fichier.
	* @param isResponseXml true ou false
	*/
	this.get = function( url, callback, isXml ) {
		var synchron = (callback == null);
		this.send( url, synchron, callback, "GET", null, isXml );
		if ( this.currentXhr && synchron )
			return isXml ? this.currentXhr.responseXML : this.currentXhr.responseText;
		return null;
	}

	/**
	* Emet une requête
	*
	* @param url           URL
	* @param synchron      true ou false
	* @param callback      Nom de fonction (string)
	* @param method        "POST" ou "GET"
	* @param data          String, objet javascript, ou null
	* @param isResponseXml true ou false
	*/
	this.send = function ( url, synchron, callback, method, data, isResponseXml ) {
		var xhr = this.getXMLHttpRequest();
		this.currentXhr = xhr;
		this.currentIsResponseXml = isResponseXml;
		if ( xhr ) {
			xhr.open( method, url, !synchron );
			xhr.onreadystatechange = function() {
				if ( xhr.readyState == 4 ) {
					if ( callback != null ) {
						var resp = isResponseXml ? xhr.responseXML : xhr.responseText;
						eval( callback+'(resp);' );
					}
				}
			};
			xhr.send( data );
		}
		else {
			return false;
		}
	}

	/**
	* Renvoie les données téléchargées
	*/
	this.getData = function () {
		return this.currentIsResponseXml ? this.currentXhr.responseXML : this.currentXhr.responseText;
	}

	/**
	* Renvoie un objet de requetes Http
	*/
	this.getXMLHttpRequest = function () {
		var xhr = null;

		if( window.XMLHttpRequest ) // Firefox et autres
			xhr = new XMLHttpRequest();
		else if ( window.ActiveXObject ){ // Internet Explorer
			try {
				xhr = new ActiveXObject("Msxml2.XMLHTTP");
			} catch (e) {
				try {
					xhr = new ActiveXObject("Microsoft.XMLHTTP");
				} catch (e1) { }
			}
		}
		// else : XMLHttpRequest non supporté par le navigateur
		return xhr;
	}
}

var theQW_ComboBox = null;
function QW_ComboBox( id, onSelect ) {
	this.id = id;
	this.activeIndex = -1;
	this.visible = false;
	this.onSelect = onSelect;

	this.getDiv = function ()  {
		return document.getElementById(id);
	}

	this.show = function () {
		this.getDiv().style.display = 'block';
		this.visible = true;
	}

	this.hide = function() {
		this.getDiv().style.display = 'none';
		this.visible = false;
	}

	this.clear = function () {
		this.getDiv().innerHTML = '<div style="position: absolute;" class="QW_ComboBox"><\/div>';
	}

	this.addItem = function ( item ) {
		var div = this.getDiv().childNodes[0];
		var index = div.childNodes.length;
		div.innerHTML += '<div><a href="#" onclick="theQW_ComboBox.onSelect(this.innerHTML); return false;" style="display:block; color: black; text-decoration: none">'+item+'<\/a><\/div>';
	}

	this.setItems = function( items ) {
		this.clear();
		for ( var i = 0; i < items.length; i++ )
			this.addItem( items[i] );
		if ( items.length > 1 || (items.length == 1 && items[0] != '') ) {
			this.show();
			this.setActiveItem(-1);
		}
		else
			this.hide();
	}

	this.setActiveItem = function( index ) {
		var prevDiv = this.getItem(this.activeIndex);
		if ( prevDiv != null )
			prevDiv.className = '';

		this.activeIndex = index;
		var newDiv = this.getItem(index);
		if ( newDiv == null )
			this.activeIndex = -1;
		else
			newDiv.className = 'QW_ComboBox_Active';
	}

	this.getItem = function( index ) {
		if ( index < 0 )
			return null;

		var items = this.getDiv().childNodes[0].childNodes;
		if ( index >= items.length )
			return null;
		return items[index];
	}

	this.countItems = function() {
		return theQW_ComboBox.getDiv().childNodes[0].childNodes.length;
	}

	this.getCurrentIndex = function() {
		return this.activeIndex;
	}

	function onKeydown(event) {
		if( !event && window.event )
			event = window.event;

		if ( theQW_ComboBox.visible ) {
			var index = theQW_ComboBox.getCurrentIndex();
			switch ( event.keyCode ) {
				case 13 /*entree*/: theQW_ComboBox.onSelect( theQW_ComboBox.getItem(index).childNodes[0].innerHTML ); return;
				case 38 /*haut*/  : index--; break;
				case 40 /*bas */  : index++; break;
				default           : return;
			}
			var count = theQW_ComboBox.countItems();
			if ( index == -1 )
				index = count-1;
			else if ( index >= count )
				index = 0;
			theQW_ComboBox.setActiveItem( index );
		}
	}

	this.create = function() {
		theQW_ComboBox = this;
		this.hide();
		this.getDiv().style.position = 'relative';
		this.clear();
		QW_EVENT_addOnkeydown( onKeydown, document );
	}

	this.create();
}

