function ListaJS (
	id_tabla,  			//el id de la tabla de contenidos
	nro_columna_clave, 	//nro de la columna clave
	cf_seleccion, 		//funcion de callback al seleccionar una fila debe aceptar un parametro: fila (tr)
	nro_fila_ini, 		//nro de la fila inicial (opcional, por defecto = 0)
	nro_fila_fin		//nro de la fila final (opcional, por defecto = fin_de_tabla)
	) {
	this.tabla = document.getElementById(id_tabla); //tabla con los datos
	this.nroColumnaClave = nro_columna_clave; //posicion de la columna con la clave
	if (nro_fila_ini) { //nro de la primera fila de la tabla
		this.nroFilaIni = nro_fila_ini;
	} else {
		this.nroFilaIni = 0;
	}
	if (nro_fila_fin) { //nro. de la ultima fila de la tabla
		this.nroFilaFin = nro_fila_fin;
	} else {
		this.nroFilaFin = this.tabla.rows.length - 1;
	}
	if (cf_seleccion) {
		this.cfSeleccion = cf_seleccion;
	} else {
		this.cfSeleccion = null;
	}
	this.rowCursor = "pointer"; //cursor de las filas
	this.colorOver = "#CCCCEE"; //color de fondo en mouseover de una fila
	this.colorOut = ""; //color de fondo en mouseout de una fila
	this.colorSelect = "#AAAACC"; //color de una fila seleccionada
	this.row = null; //fila seleccionada, por defecto ninguna
	this.deseleccionar = false; //true, si se pueden deseleccionar filas
	var instance = this; //puntero a esta instancia
	
	this.inicializar = function() {
		//setea los eventos sobre las filas de la tabla
		for(var i = this.nroFilaIni; i <= this.nroFilaFin; i++) {
			this.tabla.rows[i].style.cursor = this.rowCursor;
			this.tabla.rows[i].onmouseover = function() {
				if (this == instance.row) {
					this.style.backgroundColor = instance.colorSelect;
				} else {
					this.style.backgroundColor = instance.colorOver;
				}
			}
			this.tabla.rows[i].onmouseout = function() {
				if (this == instance.row) {
					this.style.backgroundColor = instance.colorSelect;
				} else {
					this.style.backgroundColor = instance.colorOut;
				}
			}
			this.tabla.rows[i].onclick = function() {
				if ((instance.row != this) && (instance.row != null)) {
					instance.row.style.backgroundColor = instance.colorOut;
				}
				if ((instance.deseleccionar) && (instance.row == this)) {
					this.style.backgroundColor = instance.colorOver;
					instance.row = null;
				} else {
					this.style.backgroundColor = instance.colorSelect;
					instance.row = this;
					if (instance.cfSeleccion != null) {
						try {
							instance.cfSeleccion(instance.getRow());
						} catch(e) {alert(e.message)};
					}
				}
			}
		}
	}
	
	this.getRow = function() {
		//devuelve la fila seleccionada
		return this.row;
	}
	
	this.getRows = function() {
		var arr = new Array();
		var j = 0;
		for (var i = this.nroFilaIni; i <= this.nroFilaFin; i++) {
			arr[j] = this.tabla.rows[i];
			j++;
		}
		return arr;
	}
	
	this.getId = function() {
		//devuelve el valor del campo clave de la fila seleccionada
		if (this.row == null) {
			return null;
		}
		return row.cells[this.nroColumnaClave].innerHTML;
	}
	
	this.setRowByIndex = function(ind, noDispararEvento) {
		//selecciona una fila, if noDispararEvento es true no se ejecuta la funcion cfSeleccion
		if ((ind >= this.nroFilaIni) && (ind <= this.nroFilaFin)) {
			if (this.row != null) {
				this.row.style.backgroundColor = instance.colorOut;
			}
			this.row = this.tabla.rows[ind];
			this.row.style.backgroundColor = this.colorSelect;
			if (!noDispararEvento) {
				if (this.cfSeleccion != null) {
					try {
						this.cfSeleccion(this.getRow());
					} catch(e) {alert(e.message)};
				}
			}
		}
	}
	
	this.setRowByKey = function(key, noDispararEvento) {
		//selecciona una fila segun la clave
		this.setRowByIndex(this.getIndexByKey(key));
	}
	
	this.getRowByIndex = function(ind) {
		//devuelve una fila de la tabla segun el indice, null si se sale de rango
		if ((ind >= this.nroFilaIni) && (ind <= this.nroFilaFin)) {
			return this.tabla.rows[ind];
		}
		return null;
	}
	
	this.getIndexByKey = function(key) {
		//devuelve el indice de la fila segun la clave
		for (var i = this.nroFilaIni; i <= this.nroFilaFin; i++) {
			if (this.tabla.rows[i].cells[this.nroColumnaClave].innerHTML == key) {
				return i;
			}
		}
		return -1;
	}
	
	this.getRowByKey = function(key) {
		//devuelve una fila de la tabla segun la clave, nulo si no la encuentra
		for (var i = this.nroFilaIni; i <= this.nroFilaFin; i++) {
			if (this.tabla.rows[i].cells[this.nroColumnaClave].innerHTML == key) {
				return this.tabla.rows[i];
			}
		}
		return null;
	}
	
	this.makeColInvisible = function(ind) {
		//hace invisible a una columna (segun el indice 0..N
		for (var i = this.nroFilaIni; i <= this.nroFilaFin; i++) {
			if (this.tabla.rows[i].cells[ind]) {
				this.tabla.rows[i].cells[ind].style.display = "none";
			}
		}
	}
	this.insRow = function(cells, al) {
		//inserta una fila
		var tr = this.tabla.insertRow(), td;
		tr.style.height = "25px";
		for(var i = 0; i < cells.length; i++) {
			td = tr.insertCell(); 
			if (i == 0) td.style.display = "none";
			td.innerHTML = cells[i];
			if (al) {
				td.align = al;
			}
		}
		this.nroFilaFin++;
		this.inicializar();	
	}
	
	this.delRow = function(clave) {
		//borra una fila
		var ind = this.getIndexByKey(clave);
		this.tabla.deleteRow(ind);
		this.nroFilaFin--;
		this.inicializar();	
	}
	
	this.inicializar();
}