/**
 * Javascript cLibrary
 * cLibrary.js
 * ------------------------------------------------------------------------------------------------------------
 * @author ciscodelgado http://www.ciscodelgado.com
 * @version Lite
 * 
 */

var cLibrary = {
	Version : 'Lite'
};

/**
 * Clase Ajax
 * 
 */
function Ajax()
{
	this.container = null;
	this.timer = null;
}

/**
 * Crea y devuelve un objeto XMLHttpRequest
 */
Ajax.prototype.httpRequest = function()
{	
	var http_request = false;
	if (window.XMLHttpRequest) 
	{ 
		// Mozilla, Safari,...
	    http_request = new XMLHttpRequest();
	    if (http_request.overrideMimeType) 
		{
	        http_request.overrideMimeType('text/xml');
	    }
	} 
	else if (window.ActiveXObject) 
	{ 
		// IE
	    try {
	        http_request = new ActiveXObject("Msxml2.XMLHTTP");
	    } catch (e) {
	        try{ 
	            http_request = new ActiveXObject("Microsoft.XMLHTTP");
	        } catch (e) {}
	    }
	}	
	return http_request;
};
Ajax.prototype.READY_STATE_UNINITIALIZED = 0;
Ajax.prototype.READY_STATE_LOADING = 1;
Ajax.prototype.READY_STATE_LOADED = 2;
Ajax.prototype.READY_STATE_INTERACTIVE = 3;
Ajax.prototype.READY_STATE_COMPLETE = 4;

Ajax.prototype.defaultError = function()
{
	alert("error fetching data!"
	+"\n\nreadyState:"+this.oXmlHttp.readyState
	+"\nstatus: "+this.oXmlHttp.status
	+"\nheaders: "+this.oXmlHttp.getAllResponseHeaders());

}
/**
 * Realiza una consulta al servidor
 * @param {String} theUrl
 * @param {Object} [options]
 */
Ajax.prototype.request = function(theUrl)
{
	try {
		var url = theUrl; 
		var sendData = "";
		var isUpdate = !(this.container === null);
		var options = arguments[1] || {};
		var rMethod = options.method || "get";
		var asynchronous = options.asynchronous || true;
		var execScripts = options.execScripts || false;
		this.oXmlHttp = this.httpRequest();
		var params = options.params || '';
		if(params.length > 0) {params += '&_='+Math.random(999);}
		
		if(rMethod == "post"){
			sendData = (params != '') ? params : "";
		}else if(rMethod == "get" && params.length > 0){
			sendData = (params.length > 0) ? "?"+params : "";
			url += sendData;
		}
		this.onInteractive = options.onInteractive || null;
		this.onLoading = options.onLoading || null;
		this.onLoaded = options.onLoaded || null;
		this.onError = (typeof options.onError == "function") ? function(r){ options.onError(r); } : function() { this.defaultError; };
		this.onComplete = (typeof options.onComplete == "function") ? function(r){ options.onComplete(r); } : null;

		this.oXmlHttp.open(rMethod, url, asynchronous);
		
		this.oXmlHttp.setRequestHeader('Cache-Control', 'no-cache');
		this.oXmlHttp.setRequestHeader('Pragma', 'no-cache');
		this.oXmlHttp.setRequestHeader('Request-Type', 'XMLHttpRequest');
		
		if(rMethod == "post"){
			this.oXmlHttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
			if(this.oXmlHttp.overrideMimeType){
				this.oXmlHttp.setRequestHeader("Connection", "close");
			}
		}	
		var oSelf = this;
	    this.oXmlHttp.onreadystatechange = function ()
		{
	        try {
				if (oSelf.oXmlHttp.readyState == oSelf.READY_STATE_LOADING) // Cargando
				{
					if(typeof oSelf.onLoading == "function") { oSelf.onLoading.call(oSelf); }
				}
				else if(oSelf.oXmlHttp.readyState == oSelf.READY_STATE_INTERACTIVE)
				{
				//	oSelf.timer = setTimeout(function()  { oSelf.oXmlHttp.abort(); oSelf.onError.call(oSelf); alert('cancelado') }, 15000);
					if(typeof oSelf.onInteractive == "function") { oSelf.onInteractive.call(oSelf); }
				}
	            else if (oSelf.oXmlHttp.readyState == oSelf.READY_STATE_COMPLETE) // Completado
				{
					clearTimeout(oSelf.timer);
					oSelf.timer = null;
					var httpStatus = oSelf.oXmlHttp.status;
	                if (httpStatus == 200 || httpStatus == 0) // Recurso encontrado
					{ 	
						var oHead = document.getElementsByTagName('head')[0];
						var sResponse = oSelf.oXmlHttp.responseText;
						if(oSelf.oXmlHttp.getResponseHeader('Content-type').match(/^text\/css/i))
						{
							var oNewStyle = document.createElement('style');
							oHead.appendChild(oNewStyle);
							oNewStyle.type = 'text/css';
							var oContentCSS = document.createTextNode(sResponse);
        					oNewStyle.appendChild(oContentCSS);
							/*
							if(isIE){
						        var arrContentCSS = sResponse.split("{");
								document.styleSheets
								
						        var oLastStyleTag = document.styleSheets[document.styleSheets.length-1];
						        oLastStyleTag.addRule(arrContentCSS[0], "{"+arrContentCSS[1]);
							} else{
								var oContentCSS = document.createTextNode(sResponse);
        						oNewStyle.appendChild(oContentCSS);
							}
							*/
						}						
						else if(oSelf.oXmlHttp.getResponseHeader('Content-type').match(/^application\/x-javascript/i))
						{  
							var oNewScript = document.createElement("script");
							oHead.appendChild(oNewScript);
							oNewScript.type = "text/javascript";
							oNewScript.text = sResponse;	
						}
						else if(oSelf.oXmlHttp.getResponseHeader('Content-type').match(/^text\/html/i))
						{
							if(isUpdate) 
							{ 
								var sCleanResponse = sResponse.stripScripts();
								Elements.update(oSelf.container.id, sCleanResponse.replace('\n', ''));
							}
							if(execScripts)
							{
								executeScripts(sResponse);
							}
						}
						if(oSelf.onComplete)
						{
							oSelf.onComplete.call(oSelf.caller, oSelf.oXmlHttp);	
						} 
	                }
					else if(httpStatus == 404)
					{
						oSelf.onError.call(oSelf, oSelf.oXmlHttp);	
					} 
					else if(httpStatus >= 500)
					{
						oSelf.onError.call(oSelf, oSelf.oXmlHttp);	
					} 
	            }
	        } catch (oException) {
	            oSelf.onError.call(oSelf);
	        }
	    };
	    this.oXmlHttp.send((rMethod == "post") ? sendData : null);
	} catch(oException) { alert("Error:\n--------------\nMETHOD: "+rMethod+"\nPARAMETROS:"+ params +"\nURL: "+url+" / "+sendData+"\n"+oException.message); }
};

/**
 * Realiza una consulta al servidor y actualiza el contenedor con la respuesta
 * @param {String} theUrl
 * @param {Object} oContainer
 */
Ajax.prototype.update = function(theUrl, oContainer)
{
	this.container = oContainer;
	var options = arguments[2] || {};
	this.request(theUrl, options);
};

/**
 * Realiza una consulta al servidor y devuelve la respuesta en formato XML
 * @param {String} theUrl
 */
Ajax.prototype.xml = function (theUrl)
{
	var options = arguments[1] || {};

	var oXmlDom = zXmlDom.createDocument();
	oXmlDom.onreadystatechange = function()
	{
		if(oXmlDom.readyState == 4)
		{
			
			if(oXmlDom.parseError.errorCode === 0)
			{
				
				options.onComplete(oXmlDom);
			}
			else
			{
				if(typeof options.onError == "function")
				{
					options.onError(oXmlDom);	
				}	
			}
		}
	};
	oXmlDom.load(theUrl);
};
// Fin clase Ajax
/**
 * Creamos el objeto Elements
 */

var Elements = {
	/**
	 * Actualiza el contenido de un elemento
	 * @param {String} sContent Nuevo contenido
	 */
	update : function(sId, sContent)
	{
		var oObj = $(sId);
		if(!oObj) {return;}
		
		oObj.innerHTML = sContent;
	}
};
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// * Fin clase Elements
////////////////////////////////////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// * Añado métodos a la clase Array
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
 * Devuelve el indice de la primera ocurrencia del elemento pasado dentro del array, si no se encuentra devuelve -1
 * @param {String, Object, Number, Array} vItem
 * @return {Number} 
 */
Array.prototype.indexOf = function (vItem) 
{
	for (var i=0; i < this.length; i++) 
	{
		if (vItem === this[i]) 
		{
			return i;
		}
	}
	return -1;
};
/**
 * Comprueba si el elemento pasado existe en el array. Devuelve true si lo encuentra o false en caso contrario
 * @param {String, Object, Number, Array} vItem
 * @return {Boolean}
 */
Array.prototype.inArray = function(vItem)
{
	return (this.indexOf(vItem) > -1);
};

////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// * Añado métodos a la clase String
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
 * Decodifica una cadena en formato URL
 * @return {String} Cadena decodificada
 */
String.prototype.urldecode = function()
{
	var sInputString = unescape(this);
	return sInputString.replace(/\+/gi," "); // Se substituye el signo + que deja unescape por espacio en blanco
};

/**
 * Elimina los espacios en blanco de una cadena
 */
String.prototype.trim = function () 
{
	var reExtraSpace = /^\s*(.*?)\s*$/;
	return this.replace(reExtraSpace, "$1");
};

String.prototype.toObject = function()
{
	var oObject = {};
	var aStringParts = this.split('&');
	var aPairs = null;
	for(i = 0; i < aStringParts.length; i++)
	{
		aPairs = aStringParts[i].split('=');
		oObject[aPairs[0]] = aPairs[1];
	}
	return oObject;
};

String.prototype.stripScripts = function()
{
	return this.replace(/(<script.*?>)((\n|\r|\t|.)*?)(?:<\/script>)/gi, function(sMatch){return "";});
}

String.prototype.isEmpty = function()
{
	var str_value = this.trim();
	if(str_value === "" || str_value === null)
	{
		return true;
	}
	return false;
};


////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// * Funciones globales
////////////////////////////////////////////////////////////////////////////////////////////////////////////////

/**
 * Devuelve la/s referencia/s al/los objeto/s
 * @param {String} Id del objeto (atributo id)
 * @return {String || Array} 
 */
function $()
{
	var element;
	var idElements = [];
	for(var i=0; i<arguments.length; i++)
	{
		if(typeof arguments[i] == "string")
		{
			element = document.getElementById(arguments[i]);
		}
		else if(typeof arguments[i] == "object")
		{
			element = arguments[i];
		}
		idElements.push(element);
	}
	if(idElements.length === 0)
	{
		return false;
	}
	else
	{
		return (idElements.length < 2) ? idElements[0] : idElements;
	}
}
