function EfluxTable (pData) {
	/**
	 * Establece id
	 * @param pId Id
	 */
	this.setId = function (pId) { setId(pId); }
	/**
	 * Establece numero de estilos css para diferenciar filas
	 * Por defecto 2
	 * @param pN Numero de colores
	 */
	this.setNumFieldColors = function (pN) { setNumFieldColors(pN); }
	/**
	 * Establece numero de estilos css para diferenciar columnas
	 * Por defecto 2
	 * @param pN Numero de colores
	 */
	this.setNumRowColors = function (pN) { setNumRowColors(pN); }
	/**
	 * Retorna elemento para insertar
	 */
	this.getElement = function () { return getElement(); }
	/**
	 * Retorna EfluxDataTable
	 */
	this.getData = function () { return getData(); }
	/**
	 * Actualiza contenido de la tabla para reflejar cambios del EfluxDataTable
	 */
	this.refresh = function () { refresh(); }
	/**
	 * Establece evento Click para cabecera
	 * @param pFunc Funcion que se encarga de manejar el evento.
	 * 	parametros: evt, target, nCelda
	 */
	this.setOnHeadClickEvt = function (pFunc) { setOnHeadClickEvt(pFunc); }
	/**
	 * Establece evento MouseOver para cabecera
	 * @param pFunc Funcion que se encarga de manejar el evento.
	 * 	parametros: evt, target, nCelda
	 */
	this.setOnHeadMouseOverEvt = function (pFunc) { setOnHeadMouseOverEvt(pFunc); }
	/**
	 * Establece evento MouseOut para cabecera
	 * @param pFunc Funcion que se encarga de manejar el evento.
	 * 	parametros: evt, target, nCelda
	 */
	this.setOnHeadMouseOutEvt = function (pFunc) { setOnHeadMouseOutEvt(pFunc); }
	/**
	 * Establece evento MouseOut para cuerpo
	 * @param pFunc Funcion que se encarga de manejar el evento.
	 * 	parametros: evt, target, nCelda, nFila
	 */
	this.setOnCellClickEvt = function (pFunc) { setOnCellClickEvt(pFunc); }
	/**
	 * Establece evento MouseOut para cuerpo
	 * @param pFunc Funcion que se encarga de manejar el evento.
	 * 	parametros: evt, target, nCelda, nFila
	 */
	this.setOnCellMouseOverEvt = function (pFunc) { setOnCellMouseOverEvt(pFunc); }
	/**
	 * Establece evento MouseOut para cuerpo
	 * @param pFunc Funcion que se encarga de manejar el evento.
	 * 	parametros: evt, target, nCelda, nFila
	 */
	this.setOnCellMouseOutEvt = function (pFunc) { setOnCellMouseOutEvt(pFunc); }

	// ================ //

	var cData = pData;
	var cOnHeadClickEvt = null;
	var cOnHeadMouseOverEvt = null;
	var cOnHeadMouseOutEvt = null;
	var cOnCellClickEvt = null;
	var cOnCellMouseOverEvt = null;
	var cOnCellMouseOutEvt = null;
	
	var cId = 'efluxTable'+ Math.random();
	var cDiv = document.createElement('DIV');
	var cTable = null;
	var cTHead = null;
	var cTBody = null;
	
	var cNumFieldColors = 2;
	var cNumRowColors = 2;
	
	var cCssTable = 'EfluxTable';
	var cCssTrN = 'TrN';
	var cCssTrC = 'TrC';
	var cCssTdN = 'TdN';
	var cCssTdC = 'TdC';
	var cCssTdSort = 'TdSort';
	var cCssTdSortr = 'TdSortr';
	
	var setId = function (pId) {
		cId = pId;
		cDiv.setAttribute('id', pId);
	}
	var setNumFieldColors = function (pN) {
		cNumFieldColors = pN;
	}
	
	var setNumRowColors = function (pN) {
		cNumRowColors = pN;
	}
	
	var getElement = function () {
		if (cTable == null) {
			refresh();
		}
		return cDiv;
	}
	
	var getData = function () {
		return cData;
	}

	var setOnHeadClickEvt = function (pFunc) {
		cOnHeadClickEvt = pFunc;
	}

	var setOnHeadMouseOverEvt = function (pFunc) {
		cOnHeadMouseOverEvt = pFunc;
	}

	var setOnHeadMouseOutEvt = function (pFunc) {
		cOnHeadMouseOutEvt = pFunc;
	}
	
	var setOnCellClickEvt = function (pFunc) {
		cOnCellClickEvt = pFunc;
	}

	var setOnCellMouseOverEvt = function (pFunc) {
		cOnCellMouseOverEvt = pFunc;
	}

	var setOnCellMouseOutEvt = function (pFunc) {
		cOnCellMouseOutEvt = pFunc;
	}

	var refresh = function () {
		if (cTable==null) {
			cTable = createTable();
			cDiv.appendChild(cTable);
		}
		if (cTHead!=null) { cTable.removeChild(cTHead); }
		if (cTBody!=null) { cTable.removeChild(cTBody); }
		cTHead = createTHead();
		cTBody = createTBody();
		cTable.appendChild(cTHead);
		cTable.appendChild(cTBody);
		setId(cId);
	}

	var createTable = function () {
		var o = cTable;
		if (o==null) {
			o = document.createElement('TABLE');
			o.className = cCssTable;
		}
		return o;
	}
	var createTHead = function () {
		var o = document.createElement('THEAD');
		var data = getData();
		var tr = document.createElement('TR');
		o.appendChild(tr);
		var head = data.getHeader();
		if (head) {
			var efluxEvent = new EfluxEvent();
			for (var i=0; i<head.getSize(); ++i) {
				var td = document.createElement('TD');
				var valor = head.getCellElement(i);

				if (valor.COLSPAN!=null) {
					td.setAttribute('colspan', valor.COLSPAN);
				}
				td.appendChild(document.createTextNode(valor.VALUE));
				td.className = cCssTdN + i +' '+ cCssTdC + (i%cNumFieldColors);
				if (data.getSortCell()==i) {
					td.className += ' '+ cCssTdSort;
					if (data.isReverseSort()==true) td.className += ' '+ cCssTdSortr;
				}

				tr.appendChild(td);
				createTHeadEvts(efluxEvent, td, i);
			}
		}
		return o;
	}
	var createTBody = function () {
		var o = document.createElement('TBODY');
		var data = getData();
		var efluxEvent = new EfluxEvent();
		for (var i=0; i<data.getSize(); ++i) {
			var tr = document.createElement('TR');
			var row = data.getRow(i);
			tr.className = cCssTrN + i +' '+ cCssTrC + (i%cNumRowColors);
			o.appendChild(tr);
			for (var j=0; j<row.getSize(); ++j) {
				var td = document.createElement('TD');
				var valor = row.getCellElement(j);

				if (valor.COLSPAN!=null) {
					td.setAttribute('colspan', valor.COLSPAN);
				}

				if (typeof valor.VALUE == 'string' || typeof valor.VALUE == 'number') {
					td.appendChild(document.createTextNode(valor.VALUE));
				} else {
					try {
						td.appendChild(valor.VALUE);
					} catch (e) {
						try {
							td.appendChild(valor.VALUE.getElement());
						} catch (e2) {
							td.appendChild(document.createTextNode(valor.VALUE.toString()));
						}
					}
				}

				td.className = cCssTdN + j +' '+ cCssTdC + (j%cNumFieldColors);
				if (data.getSortCell()==j) td.className += ' '+ cCssTdSort;
				tr.appendChild(td);
				createTBodyEvts(efluxEvent, td, j, i);
			}
		}
		return o;
	}
	
	var createTHeadEvts = function (pEfluxEvent, pTd, pX) {
		pEfluxEvent.addListener(pTd, 'click', function (pEvt) { onHeadClickEvt(pEvt, pX); } );
		pEfluxEvent.addListener(pTd, 'mouseover', function (pEvt) { onHeadMouseOverEvt(pEvt, pX); } );
		pEfluxEvent.addListener(pTd, 'mouseout', function (pEvt) { onHeadMouseOutEvt(pEvt, pX); } );
	}
	
	var createTBodyEvts = function (pEfluxEvent, pTd, pX, pY) {
		pEfluxEvent.addListener(pTd, 'click', function (pEvt) { onCellClickEvt(pEvt, pX, pY); } );
		pEfluxEvent.addListener(pTd, 'mouseover', function (pEvt) { onCellMouseOverEvt(pEvt, pX, pY); } );
		pEfluxEvent.addListener(pTd, 'mouseout', function (pEvt) { onCellMouseOutEvt(pEvt, pX, pY); } );
	}
	
	var onHeadClickEvt = function (pEvt, pX) {
		if (cOnHeadClickEvt && cOnHeadClickEvt!=null) {
			var trgt = (pEvt.target)?pEvt.target:pEvt.srcElement;
			cOnHeadClickEvt(pEvt, trgt, pX);
		}
	}
	
	var onHeadMouseOverEvt = function (pEvt, pX) {
		if (cOnHeadMouseOverEvt && cOnHeadMouseOverEvt!=null) {
			var trgt = (pEvt.target)?pEvt.target:pEvt.srcElement;
			cOnHeadMouseOverEvt(pEvt, trgt, pX);
		}
	}
	
	var onHeadMouseOutEvt = function (pEvt, pX) {
		if (cOnHeadMouseOutEvt && cOnHeadMouseOutEvt!=null) {
			var trgt = (pEvt.target)?pEvt.target:pEvt.srcElement;
			cOnHeadMouseOutEvt(pEvt, trgt, pX);
		}
	}
	
	var onCellClickEvt = function (pEvt, pX, pY) {
		if (cOnCellClickEvt && cOnCellClickEvt!=null) {
			var trgt = (pEvt.target)?pEvt.target:pEvt.srcElement;
			cOnCellClickEvt(pEvt, trgt, pX, pY);
		}
	}
	
	var onCellMouseOverEvt = function (pEvt, pX, pY) {
		if (cOnCellMouseOverEvt && cOnCellMouseOverEvt!=null) {
			var trgt = (pEvt.target)?pEvt.target:pEvt.srcElement;
			cOnCellMouseOverEvt(pEvt, trgt, pX, pY);
		}
	}
	
	var onCellMouseOutEvt = function (pEvt, pX, pY) {
		if (cOnCellMouseOutEvt && cOnCellMouseOutEvt!=null) {
			var trgt = (pEvt.target)?pEvt.target:pEvt.srcElement;
			cOnCellMouseOutEvt(pEvt, trgt, pX, pY);
		}
	}
}

// AUTOCARGA DE DEPENDENCIAS
new function () {
	var DEPENDENCIAS = [
		'EfluxDataTable',
		'EfluxEvent',
		];
	var dir = 'js';
	if (typeof EFLUX_JS_DIR != 'undefined') { dir = EFLUX_JS_DIR; }

	for (var i=0; i<DEPENDENCIAS.length; ++i) {
		var d = DEPENDENCIAS[i];
		var js = dir +'/'+ d +'/'+ d +'.js';
		try { eval ('new '+ d +'()'); }
		catch (e) {
			document.writeln('<SCRIPT src="'+ js +'"></SCRIPT>');
		}
	}
}

