var ST_ATTR_SORTTABLE_INNERTEXT = "innertext";

/**
 * Obtiene el texto dentro de un elemento
 * @param {Object} element
 */
function getInnerText(element){
    if ((typeof element == "string") || (typeof element == "undefined")) 
        return element;
    if (element.innerText) 
        return element.innerText;
    
    //Verifica que no se haya calculado ya el innerText del element
    var str = element.getAttribute(ST_ATTR_SORTTABLE_INNERTEXT);
    if (str != null && str != "") 
        return str;
    
    str = "";
    
    var cs = element.childNodes;
    var l = cs.length;
    for (var i = 0; i < l; i++) {
        switch (cs[i].nodeType) {
            case 1: //ELEMENT_NODE
                str += getInnerText(cs[i]);
                break;
            case 3: //TEXT_NODE
                str += cs[i].nodeValue;
                break;
        }
    }
    //Se setea el innerText al elemento, para no tener que recorrer 
    //la recursión la próxima vez que se invoque el método con el mismo parámetro
    element.setAttribute(ST_ATTR_SORTTABLE_INNERTEXT, str);
    
    return str;
}

/**
 * Obtiene el elemento padre de otro de un tipo específico
 * @param {HTMLElement} el tag del que se quiere obtener el padre
 * @param {String} pTagName tipo de tag del padre
 */
function getParent(el, pTagName){
    if (el == null) 
        return null;
    else 
        if (el.nodeType == 1 && el.tagName.toLowerCase() == pTagName.toLowerCase()) 
            return el;
        else 
            return getParent(el.parentNode, pTagName);
}

/**
 * Precarga las imágenes
 */
var preloaded = new Array();
function preload_images() {
    for (var i = 0; i < arguments.length; i++){
        preloaded[i] = new Image();
        preloaded[i].src =arguments[i];
    };
}

/**
 * incluye una librería js, permite invocar la inclusión desde otro js
 */
function include(script_filename){
    var html_doc = document.getElementsByTagName('head').item(0);
    var js = document.createElement('script');
    js.setAttribute('language', 'javascript');
    js.setAttribute('type', 'text/javascript');
    js.setAttribute('src', script_filename);
    html_doc.appendChild(js);
    return false;
}

/**
 * Elimina las filas de una tabla a partir de inicio y hasta fin
 * @param {HTMLTable} table, tabla a modificar
 * @param {Number} inicio, primera fila a borrar
 * @param {Number} fin, última fila a borrar, si se omite el parámetro se elimina hasta el final
 */ 
function delRowsTable(table, inicio, fin){
	if(table.tBodies[0]==undefined)
		return;
	if(fin==undefined)
		fin = table.tBodies[0].rows.length-1;
	for(i=inicio; i<= fin; i++){
		table.tBodies[0].deleteRow(inicio);
	}
}

/**
 * Agrega un 'option' a un combo y lo retorna
 */
function addOption(combo){
	option = document.createElement('option');
	try{
		combo.add(option); /*IE*/
	}catch(e){
		combo.add(option, null);/*MOZILLA*/
	}
	return option;
}

/**
 * Elimina todos los options de un combo
 */
function clearCombo(combo){
	combo.options.length = 0;
	var optgs = combo.getElementsByTagName('optgroup');
	for(i=optgs.length-1; i>=0; i-- ){
		combo.removeChild(optgs[i]);
	}
}

/**
 * Retorna el índice de la opción que tiene el valor especificado dentro de un combo
 * @param combo combo donde se buscará el option con un value específico
 * @param value valor del option buscado
 * @return índice del option encontrado, sino -1
 */
function findValue(combo, value){
	for(var i = 0; i < combo.length; i++){
		var val = combo.options[i].value;
		if(val==value)
			return i;
	}
	return -1;
}

/**
 * Ordena el contenido de cada grupo de un comboBox
 * @param {Select} combo a ordenar
 */
function sortComboByGroups(combo){
	try{
		var groups = combo.getElementsByTagName('optgroup');
		for(var i = 0; i< groups.length; i++){
			var group = groups[i];
			var seguir = true;
			//Ordena por burbujeo, debería usarse otro algoritmo
			while(seguir){
				seguir=false;
				var el1;
				var el2;
				if(/MSIE/.test(navigator.userAgent)){ //IE
					el1 = group.firstChild;
				}else{ //Mozilla
					el1 = group.nextSibling;
				}
				el2 = el1.nextSibling;
				while((el2!=null)&&(el2.tagName.toLowerCase()!='optgroup')&&(el2.tagName.toLowerCase()=='option')&&(el1.tagName.toLowerCase()=='option')){
					if(el1.text>el2.text){
						//combo.insertBefore(el2, el1);  //Sólo funciona en Mozilla
						fId = el1.id;
						fText = el1.text;
		          		fValue = el1.value;
		          		fSel = el1.selected;
		 
						el1.id = el2.id;
			            el1.text = el2.text;
		      		    el1.value = el2.value;  
		      		    el1.selected = el2.selected;
		         
		          		el2.id = fId;
		          		el2.text = fText;
		          		el2.value = fValue;
		          		el2.selected = fSel;
						
						seguir = true;
					}
					el1 = el2;
					el2 = el1.nextSibling;
				}
			}
		}
	}catch(e){}
}

/**
 * Deshabilita un elemento html, colocando una capa sobre éste
 * @param element {HTMLElement} elemento a deshabilitar
 * @param color {String} Opcional, color de la capa que se coloca sobre el elemento, por defecto es negro
 * @param opacity {Number} Opcional, porcentaje [0..1] de opacidad, por defecto es 0.3
 * 
 * @return elemento que se ubica sobre el pasado como parámetro, si se quiere volver a habilitar, 
 * 					se debe cambiar su propiedad de visibilidad (result.style.display='none')
 */
function disableElement(element, color, opacity){
	if(color==undefined)
		color='#000000';
	if(opacity==undefined)
		opacity = 0.30;
	var newDiv = document.createElement('div');
	var position = getAbsoluteElementPosition(element);
	document.body.appendChild(newDiv);
	newDiv.style.position='absolute';
	newDiv.style.backgroundColor = color;
	newDiv.style.opacity = opacity; //Standard
	newDiv.style.filter = 'alpha(opacity='+(100*opacity)+')'; //IE
	newDiv.style.zIndex=element.style.zIndex+1;
	newDiv.style.left = position.left + "px";
	newDiv.style.top = position.top + "px";
	newDiv.style.width = element.offsetWidth +  "px";
	newDiv.style.height = element.offsetHeight +  "px";
	return newDiv;
}