// JavaScript Document
//require MyClass.js
//clase con funciones utiles para todo tipo de js.
//  SINGLETON  //
MyUtils = new MyClass({
	CLASS_NAME: "MyUtils",	
	VERSION_NUMBER: "v 1.0.2",
	
	/** 
     * Method: init
     */
	init: function(){
	},
	
	/** 
     * Method: showDiv
     * 	 Muestra un elemento del tipo DIV
     * Parameters:
     *   div - {String | DOMELEMENT} : Acepta tanto el Dom del div como el Id del mismo. 
     */
	showDiv: function(div) {
		if (typeof div == 'string')
			document.getElementById(div).style.display = "block";
		else
			div.style.display = "block";
	},
	
	/** 
     * Method: hideDiv
     * 	 Oculta un elemento del tipo DIV
     * Parameters:
     *   div - {String | DOMELEMENT} : Acepta tanto el Dom del div como el Id del mismo. 
     */
	hideDiv: function(div) {
		if (typeof div == 'string')
			document.getElementById(div).style.display = "none";
		else
			div.style.display = "none";
	},
	
	/** 
     * Method: indexOfArray
     * 	 Retorna el indice de un array en el que se ubico un elemento o bien -1 si no fue encontrado.
     * Parameters:
     *   arrays - {Array} 
	 *	 obj - {Object}
	 * Return:
	 *	{Integer}
     */
	indexOfArray: function(arrays, obj) {
  		for(var i=0; i<arrays.length; i++){
	        if(arrays[i]==obj){
	            return i;
	        }
	    }
	    return -1;
	},
	
	/** 
     * Method: lTrim
     * 	 Elimina todos los espacios en blanco hacia la derecha de un texto.
     * Parameters:
     *   texto - {String} 
	 * Return:
	 *	{String}
     */
	lTrim: function(texto) {
  		var re = /\s*((\S+\s*)*)/;
		return texto.toString().replace(re, "$1");
	},
	
	/** 
     * Method: rTrim
     * 	 Elimina todos los espacios en blanco hacia la izquierda de un texto.
     * Parameters:
     *   texto - {String} 
	 * Return:
	 *	{String}
     */
	rTrim: function(texto) {
  		var re = /((\s*\S+)*)\s*/;
		return texto.toString().replace(re, "$1");
	},
	
	/** 
     * Method: trim
     * 	 Elimina todos los espacios en blanco hacia la derecha e izquierda en un texto.
     * Parameters:
     *   texto - {String} 
	 * Return:
	 *	{String}
     */
	trim: function(texto) {
  		return this.lTrim(this.rTrim(texto));
	},
	
	/** 
     * Method: checkAllOptions
     * 	 Checkea o deschequea una lista de input checkbox..
     * Parameters:
     *   boxName - {String} : Nombre de los input "checkbox" que se desean modificar 
	 *   checkedValue - {booblean} : Valor que se quiere aplicar a los elementos del checkbox 
	 *	 [opt_functionName] - {String} : Nombre de la funcion a evaluar luego de cambiar el valor de cada checkbox. A esta funcion se le pasara como parametro el "checkbox".
     */
	checkAllOptions: function(boxName, checkedValue, opt_functionName){
		var fields = document.getElementsByName(boxName);
		for (i = 0; i < fields.length; i++){
			if (fields[i].checked!=checkedValue){
				fields[i].click();
				if( opt_functionName!=null)
					call(opt_functionName)(fields[i]);
				}
			}
	},
	
	/** 
     * Method: isFirebugActive
     * 	 Detecta si firebug esta activo en el browser y retorna true en caso afirmativo.
	 * Return:
	 *	{boolean}
     */
	isFirebugActive: function() {
  		if (window.console && window.console.firebug) 
			return true;
		return false;
	},

	 /** 
     * Method: getElementsByClassName
     * 	 Homologo a getElementsByTagName, busca elementos del DOM por el atributo Class y los retorna en forma de Array. Para acotar la busqueda, de forma opcional
	 *	 puede parametrizarse el nombre del Tag en donde se debe buscar la classname.
     * Parameters:
     *   clsName - {String} : Nombre de la clase de los elementos a buscar.
	 *   [tagName] - {String} : Nombre de los tags en donde buscar (div|span|img|input|iframe|etc.) 
     */
	getElementsByClassName: function(clsName, tagName){
    	var retVal = new Array();
		var elements;
		if (tagName!=null)
	    	elements = document.getElementsByTagName(tagName);
		else
			elements = document.getElementsByTagName('*');
    	for(var i=0; i < elements.length; i++){
        	if(elements[i].className.indexOf(" ") >= 0){
            	var classes = elements[i].className.split(" ");
            	for(var j = 0;j < classes.length;j++){
                	if(classes[j] == clsName)
                    	retVal.push(elements[i]);
            	}	
        	}
        	else if(elements[i].className == clsName)
            	retVal.push(elements[i]);
    	}
    	return retVal;
	},
	
	/** 
     * Method: addOptionToSelect
     * 	 Crea y agrega una opcion a un select input
	 * Params:
     *   selector - {DomElement | String} : Elemento del DOM o Id del select input al que se quiere agregar una option.
	 *   label - {String} : Nombre de la opcion a agregar
	 *	 value - {String | Integer | boolean} : Valor de la opcion a agregar
	 * Return:
	 *	 {DomElement: Option} - Elemento agregado al selector.
     */
	addOptionToSelect: function(selector, label, value){
    	label = label.toString();
		if (this.typeOf(selector)=='string')
  			selector = document.getElementById(selector);
	    var newOption = document.createElement('option');
		newOption.value = value;
		newOption.text = label;
		try {
    		selector.add(newOption, null); // para todos los browsers (STANDART)
		}
		catch(ex) {
			selector.add(newOption); // para IE
		}	
		return newOption;
	},
	
	/** 
     * Method: getChildById
     * 	 Retorna un DOMELEMENT que coincida con un id especifico y se encuentre dentro de un Source especifico.
	 * Params:
     *   source - {DomElement} : Elemento del DOM en el que se quiere buscar un elemento.
	 *   id - {String} : Id del elemento que se quiere encotrar
	 * Return:
	 *	 {DomElement | null}
     */
	getChildById: function(source, id){
    	var childs = source.childNodes;		
		for (var i=0; i<childs.length; i++){
			if (childs[i].id == id)
				return childs[i];
			else {
				var tmp = this.getChildById(childs[i],id);
				if (tmp!=null)
					return (tmp);
			}				
		}
		return null;
	},
	
	/** 
     * Method: getChildsByName
     * 	 Retorna un arreglo de DOMELEMENT que coincida con un nombre especifico y se encuentre dentro de un Source especifico.
	 * Params:
     *   source - {DomElement} : Elemento del DOM en el que se quiere buscar un elemento.
	 *   name - {String} : Nombre del elemento que se quiere encotrar
	 * Return:
	 *	 {array DomElement | null}
     */
	getChildsByName: function(source, name){
    	var res = new Array();
    	var childs = source.childNodes;
    	for (var i=0; i<childs.length; i++)
		{
			res = res.concat(this.getChildsByName(childs[i],name));
			if (childs[i].name == name)
				res.push(childs[i]);
		}
		return res;
	},
	
	/** 
     * Method: typeOf
     * 	 Extiende y completa la funcionalidad "typeof" de JS. etorna un string en lowercase con el tipo del elemento recibido por parametro
	 * Params:
     *   vExpression - {Cualquier objeto} : Elemento JS cualquiera del que se quiere saber su tipo.
	 * Return:
	 *	 {String} - en lowercase - values: function | regexp | object | null | window | event | array | date | regex | jsobject | error | etc!
     */
	typeOf: function( vExpression )
	{	
		var sTypeOf = typeof vExpression;
		if( sTypeOf == "function" )
		{
			var sFunction = vExpression.toString();
			if( ( /^\/.*\/$/ ).test( sFunction ) )
			{
				return "regexp";
			}
			else if( ( /^\[object.*\]$/i ).test( sFunction ) )
			{
				sTypeOf = "object"
    	    }
		}	
		if( sTypeOf != "object" )
		{
			return sTypeOf;
		}		
		switch( vExpression )
		{
			case null:
				return "null";
			case window:
				return "window";
			case window.event:	
				return "event";
		}
		if( window.event && ( event.type == vExpression.type ) )
		{
			return "event";
		}
		var fConstructor = vExpression.constructor;
    	if( fConstructor != null )
		{
			switch( fConstructor )
			{																	
				case Array:
					sTypeOf = "array";
					break;
				case Date:
					return "date";
				case RegExp:
					return "regexp";
				case Object:
					sTypeOf = "jsobject";
					break;
				case ReferenceError:
					return "error";
				default:
					var sConstructor = fConstructor.toString();
					var aMatch = sConstructor.match( /\s*function (.*)\(/ );
					if( aMatch != null )
					{
						return aMatch[ 1 ];
					}
			
			}
		}
		var nNodeType = vExpression.nodeType;
		if( nNodeType != null )
		{	
			switch( nNodeType )
			{
				case 1:
					if( vExpression.item == null )
					{
						return "domelement";
					}
					break;
				case 3:
					return "textnode";
			}
		}	
		if( vExpression.toString != null )
		{
			var sExpression = vExpression.toString();
			var aMatch = sExpression.match( /^\[object (.*)\]$/i );
			if( aMatch != null )	
			{
				var sMatch = aMatch[ 1 ];
				switch( sMatch.toLowerCase() )
				{
					case "event":
						return "event";
					case "math":
						return "math";
					case "error":	
						return "error";
					case "mimetypearray":
						return "mimetypecollection";
					case "pluginarray":
						return "plugincollection";
					case "windowcollection":
						return "window";
					case "nodelist":
					case "htmlcollection":
					case "elementarray":
						return "domcollection";
				}
			}
		}	
		if( vExpression.moveToBookmark && vExpression.moveToElementText )
		{
			return "textrange";
		}
		else if( vExpression.callee != null )
		{
			return "arguments";
		}
		else if( vExpression.item != null )	
		{
			return "domcollection";
		}	
		return sTypeOf;
	},
	
	/** 
     * Method: addClass
     * 	 Agrega una clase a un elemento del dom
	 * Params:
     *   el - {DomElement} : Elemento del DOM al que se quiere agregar una clase (className).
	 *   className - {String} : Nombre de la clase a agregar
     */
	addClass:function(el,className){
		var c = el.className.split(" ");
		for(var i=0;i<c.length;i++)	{
			if(c[i]==className){
				return;
			}
		}
		if(c.length>0){
			el.className = this.trim(el.className + " " +className);
		}
		else{
			el.className = this.trim(className);
		}
	},

	/** 
     * Method: removeClass
     * 	 Remueve una clase de un elemento del dom
	 * Params:
     *   el - {DomElement} : Elemento del DOM al que se quiere remover el nombre una clase (className).
	 *   className - {String} : Nombre de la clase a remover
     */
	removeClass:function(el, className){
		var c = el.className.split(" ");
		for(var i=0;i<c.length;i++)	{
			if(c[i]==className){
				c[i]="";
			}
		}
		el.className = this.trim(c.join(" "));	
	},
	
	/** 
     * Method: hasClass
     * 	 Busca un nombre de clase appendeado a un ClassName y retorna true en caso de encontrarlo
	 * Params:
     *   el - {DomElement} : Elemento del DOM en el que se quiere buscar el className.
	 *   className - {String} : Nombre de la clase a encontrar
	 * Return:
	 *   {boolean}
     */
	hasClass: function (el, className){
	 	var c = el.className.split(" ");
		for(var i=0;i<c.length;i++)	{
			if(c[i] == className){
				return true;
			};
		}
		return false;
	},
	
	/** 
     * Method: isHashTable
     * 	 Retorna true o false si detecta que un elemento es del tipo hashtable.
	 * Params:
     *   element - {Cualquier objeto} : Elemento JS cualquiera del que se quiere saber si es del tipo HashTable.
	 * Return:
	 *	 {Boolean} 	 
     */
	isHashTable: function(element){
		if(typeof element=='object'){
			if ((this.typeOf(element.put)!='undefined')&&
				(this.typeOf(element.get)!='undefined')&&
				(this.typeOf(element.containsKey)!='undefined')&&
				(this.typeOf(element.containsValue)!='undefined')&&
				(this.typeOf(element.clear)!='undefined')&&
				(this.typeOf(element.isEmpty)!='undefined')&&
				(this.typeOf(element.keys)!='undefined')&&
				(this.typeOf(element.values)!='undefined')&&
				(this.typeOf(element.remove)!='undefined')&&
				(this.typeOf(element.size)!='undefined'))
						return true;
		}
		return false;
	},
	
	/** 
     * Method: getActualStyleProp
     * 	 Retorna el valor actual de una propiedad de estilo de un elemento (ex.: background, padding-left, etc.).
	 * Params:
     *   source - {DomElement} : Elemento JS del DOM del que se requiere saber el valor de una propiedad de su estilo actual.
	 *   styleProp - {String} : Nombre de la propiedad de estilo de la que se quiere saber su valor.
	 * Return:
	 *	 {Boolean} 
	 * DOCS: 
	 *	  http://www.quirksmode.org/dom/getstyles.html
     */
	getActualStyleProp: function(source, styleProp){
		if (source.currentStyle)
        	var st = source.currentStyle[styleProp];
    	else if (window.getComputedStyle)
    			var st = document.defaultView.getComputedStyle(source, null).getPropertyValue(styleProp);
	    return st;
	},
	
	/** 
     * Method: detectDoctype
     * 	 Detecta la definicion del tipo de documento (HTML, XHTML, etc.). Si no esta especificado, retorna null.
	 * Return:
	 *	 {JSObject | null} - Retorna un objeto JS con las siguientes properties: {xhtml, version, importance} 
	 * DOCS:
	 *    http://bytes.com/topic/javascript/answers/520145-doctype-detector
	 *    http://www.jr.pl/www.quirksmode.org/js/doctypes.html
     */
	detectDoctype: function(){
		var re=/\s+(X?HTML)\s+([\d\.]+)\s*([^\/]+)*\//;
		var res = false;
		if(typeof document.namespaces != "undefined")
			res = document.all[0].nodeType==8 ? re.test(document.all[0].nodeValue) : false;
		else
			res = document.doctype != null ? re.test(document.doctype.publicId) : false;		
		if(res){
			res = new Object();
			res['xhtml']=RegExp.$1;
			res['version']=RegExp.$2;
			res['importance']=RegExp.$3;
			return res;
		}
		else
			return null;
	}		
});

//DECLARO VARIABLE PARA UTILIZAR LA CLASE (SINGLETON)
myUtils = new MyUtils();

