function formatNumberFunction(num,dec,thou,pnt,curr1,curr2,n1,n2) {
		var x = Math.round(num * Math.pow(10,dec));
		if (x >= 0) 
			n1=n2='';
		var y = (''+Math.abs(x)).split('');
		var z = y.length - dec; 
		if (z<0) 
			z--; 
		for(var i = z; i < 0; i++) 
			y.unshift('0');
		y.splice(z, 0, pnt); 
		while (z > 3) {
			z-=3; 
			y.splice(z,0,thou);
		}
		var r = curr1+n1+y.join('')+n2+curr2;
		return r;
}

function formatDecimalNumber (number) {
	return formatNumberFunction (number,2,locale.signoMiles,locale.signoDecimal,'','','-','');
}



var GridView = Class.create();
GridView.prototype = {
	initialize: function (tablaId,cols,loadFromHtml) {
		this._tabla = $(tablaId);
		// Propiedades internas
		this._numRows = 99;
		this._index = 0;
		this._data = [];
		this._deleted = [];
		this._cols = cols;
		this._numColumns = cols.length;
		this._colOrder = 1;
		this._asc = [false,false];
		this._newData = [];
		// Propiedades parametrizables
		this._evenStyle = "evenStyle";
		this._oddStyle = "oddStyle";
		this._sortAscStyle = "sortAscStyle";
		this._sortDescStyle = "sortDescStyle";
		this._editable = false;
		this._deletable = false;
		this._copyable = false;
		this._editableCols = [];
		this._saveFunction = null;
		this._fillEditRow = null;
		this._addFunction = null;
		this._cancelEditRow = null;
		this._indicesEditLink = null;
		this._colStyles = [];
		this._colStylesFunctions = [];
		this._formatColFunctions = [];
		this._orderable = [];
		this._editHtml ="<a href='#'>Editar</a>";
		this._deleteHtml ="<a href='#'>Borrar</a>";
		this._acceptHtml ="<a href='#'>Aceptar</a>";
		this._cancelHtml ="<a href='#'>Cancelar</a>";
		this._copyHtml ="<a href='#'>Duplicar</a>";
		this._pageInfoString ="P&aacute;gina #1 de #2";
		this._pageInfoShowers = [];
		this._forwardPageTriggers = [];
		this._backPageTriggers = [];
		this._noShowWhenNoPages = false;
		this._adding = false;
		//Event.observe($(avanzarPag), 'click', this.avanzarPagina.bindAsEventListener(this));
		//Event.observe($(retrocederPag), 'click', this.retrocederPagina.bindAsEventListener(this));
		//this._pedirPagina(this,this._index, this._numRows);
		if (loadFromHtml) {
			this.loadDataFromHtml();
		}
			
	},
	
	addRow: function() {
		this._adding = true;
		this.pintar();
	},
	
	// Funciones 
	save: function() {
		this._saveFunction();
		this._data[this._rowEdit][this._numColumns+1] = true;
		this._rowEdit = -1;
		this.sortColumnNoChange(this._colOrder);
		this.pintar();
	},
	
	// Funciones 
	add: function() {
		this._addFunction();
		this._adding = false;
		this._data[this._data.length] = this._newData[0];
		this._data[this._data.length-1][this._numColumns+2] = true;
		this._newData = [];
		this.setCurrentPage(this.getTotalPages());
	},
	
	cancelEdit: function(tabla,rowEdit) {
		if (!this._adding) {
			this._rowEdit = rowEdit;
		} else {
			this._adding = false;
		}
		this._rowEdit = -1;
		if (this._cancelEditRow != null) {
			this._cancelEditRow();
		}
		//this.sortColumnNoChange(this._colOrder);
		this.pintar();
	},
	
	edit: function(tabla,rowEdit) {
		if (this._adding) {
			this._adding = false;
		}
		if (this._rowEdit != -1){
			this.cancelEdit(this,this._rowEdit);
		}
		this._rowEdit = rowEdit;
		//this.sortColumnNoChange(this._colOrder);
		this.pintar();
		if (this._fillEditRow != null) {
			this._fillEditRow();
		}
	},
	
	delRow: function(tabla,rowEdit) {
		this._deleted[this._deleted.length] = this._data[rowEdit];
		this._data[rowEdit] = undefined;
		this._data = this._data.compact();		
		this.pintar();
	},
	
	copyRow: function(tabla, rowEdit) {
		this._data[this._data.length] = this._data[rowEdit];
		this._data = this._data.compact();
		this.pintar();
	},
	
	setPageInfoString: function (string) {
		this._pageInfoString = string;
	},
	
	setPageInfoShowers: function (string) {
		this._pageInfoShowers = string;
	},
	
	setForwardPageTriggers: function (triggers) {
		for (i = 0; i < triggers.length; i++) {
			Event.observe($(triggers[i]), 'click', this.avanzarPagina.bindAsEventListener(this));
			$(triggers[i]).hide();
		}
		this._forwardPageTriggers = triggers;
	},
	
	setBackPageTriggers: function (triggers) {
		for (i = 0; i < triggers.length; i++) {
			Event.observe($(triggers[i]), 'click', this.retrocederPagina.bindAsEventListener(this));
			$(triggers[i]).hide();
		}
		this._backPageTriggers = triggers;
	},
	
	setNoShowWhenNoPages: function(bool) {
		this._noShowWhenNoPages = bool;
	},
	
	setEditHtml: function (html) {
		this._editHtml = html;
	},
	setDeleteHtml: function (html) {
		this._deleteHtml = html;
	},
	setAcceptHtml: function (html) {
		this._acceptHtml = html;
	},
	setCancelHtml: function (html) {
		this._cancelHtml = html;
	},
	setCopyHtml: function (html) {
		this._copyHtml = html;
	},
	
	setFormatColFunctions: function (formatFunctions) {
		this._formatColFunctions = formatFunctions;
	},
	setColStyles: function (styles) {
		this._colStyles = styles;
	},
	setColStylesFunctions: function (styles) {
		this._colStylesFunctions = styles;
	},
	
	setEvenStyle: function (evenStyle) {
		this._evenStyle = evenStyle;
	},
	
	setOddStyle: function (oddStyle) {
		this._oddStyle = oddStyle;
	},
	
	setSortAscStyle: function (style) {
		this._sortAscStyle = style;
	},
	
	setSortDescStyle: function (style) {
		this._sortDescStyle = style;
	},
		
	setEditable: function (editable) {
		this._editable = editable;
	},
	setDeletable: function (deletable) {
		this._deletable = deletable;
	},
	
	setCopyable: function (copyable) {
		this._copyable = copyable;
	},	
	
	setEditableCol: function (col, innerHtml) {
		this._editableCols[col] = innerHtml;
	},
	setEditableCols: function (cols) {
		this._editableCols = cols;
	},
	
	setSaveFunction: function (funcion) {
		this._saveFunction = funcion;
	},
	
	setAddFunction: function (funcion) {
		this._addFunction = funcion;
	},

	setFillEditRow: function (funcion) {
		this._fillEditRow = funcion;
	},
	setCancelEditRow: function (funcion) {
		this._cancelEditRow = funcion;
	},
	setPageRows: function(rows) {
		this._numRows = rows;
	},
	getDeleted:  function () {
		return this._deleted;
	},
	getUpdated:  function () {
		var updated = [];
		for (i = 0; i < this._data.length; i++) {
			if (this._data[i][this._numColumns+1] == true) {
				updated[updated.length] = this._data[i];
			}
		}
		return updated;
	},
	
	getAdded:  function () {
		var added = [];
		for (i = 0; i < this._data.length; i++) {
			if (this._data[i][this._numColumns+2] == true) {
				alert("AKI");
				added[added.length] = this._data[i];
			}
		}
		return added;
	},
	
	getCurrentPage: function () {
		currentPage = Math.floor(this._index / (this._numRows + this._newData.length));
		return currentPage+1;
	},
	
	setCurrentPage: function (page) {
		this._index = (page-1) * this._numRows;
		while (this._index >= this._data.length) {
			this._index -= this._numRows;
		}
		if (this._index < 0) {
			this._index = 0;
		}
		this.pintar();
	},
	
	getTotalPages: function() {
		numPages = Math.floor((this._data.length / this._numRows))  ;
		if (this._data.length % this._numRows != 0) {
			numPages++;
		}
		return numPages;
	},
	
	avanzarPagina: function() {
		if ((this._index + this._numRows) < this._data.length) {
			this._index += this._numRows;
			this.pintar();
		}
	},
	
	
	retrocederPagina: function() {
		this._index -= this._numRows;
		if (this._index < 0) {
			this._index = 0;
		}
		this.pintar();
	},
	
	pintar: function() {
		
		if ((!this._noShowWhenNoPages) || (this.getTotalPages() > 1)){
			this.paintPageShowers();
			for (i = 0; i<this._forwardPageTriggers.length;i++){
				$(this._forwardPageTriggers[i]).show();
			}
			for (i = 0; i<this._backPageTriggers.length;i++){
				$(this._backPageTriggers[i]).show();
			}
		}
		else{
			for (i = 0; i<this._forwardPageTriggers.length;i++){
				$(this._forwardPageTriggers[i]).hide();
			}
			for (i = 0; i<this._backPageTriggers.length;i++){
				$(this._backPageTriggers[i]).hide();
			}
			for (i = 0; i < this._pageInfoShowers.length; i++) {
				$(this._pageInfoShowers[i]).hide();
			}
			this._index = 0;
		}
		

		
		for (i = this._tabla.rows.length -1; i >= 1;i--) {
			if (this._tabla.rows[i].id != "editRow") {
				this._tabla.deleteRow(i);
			}
		}
		
		/*while (this._tabla.rows.length > 2) {
			
		}*/
		k = 0;
		// Modifica la cabecera
		for (j = 0; j < this._cols.length; j++) {
			if (this._cols[j] != "invisible") {
				Element.removeClassName(this._tabla.rows[0].cells[k],this._sortAscStyle);
				Element.removeClassName(this._tabla.rows[0].cells[k],this._sortDescStyle);
				if (j == this._colOrder) {
					if (this._asc[j] == true) {
						Element.addClassName(this._tabla.rows[0].cells[k],this._sortDescStyle);
					} else if (this._asc[j] == false) {
						Element.addClassName(this._tabla.rows[0].cells[k],this._sortAscStyle);
					}
				}
				k++;
			}
			
		}
		
		
		for (i = this._index; (i < this._index + this._numRows) && (i < this._data.length); i++) {
			if ((i>= 0) &&(i != this._rowEdit)) {
				row = this._tabla.insertRow(i+1-this._index);
			}
			
			
			if ((i - this._index) % 2 == 0) {
				Element.addClassName(row,this._evenStyle);
				
			} else {
				Element.addClassName(row,this._oddStyle);
				
			}
			
			if (this._rowEdit != i) {
				for (j = 0; j < this._cols.length; j++) {
					if (this._cols[j] != "invisible") {
						if ((this._editableCols[j] != undefined) && (this._rowEdit == i)) {
								cell = row.insertCell(-1);
								cell.innerHTML=this._editableCols[j];
						} else {
							cell = row.insertCell(-1);
							if ((this._colStyles[j] && (!this._colStylesFunctions[j]))) {
								Element.addClassName(cell,this._colStyles[j]);
							} else if (this._colStylesFunctions[j]) {
								Element.addClassName(cell,this._colStylesFunctions[j](this._data[i][j]));
							}
							
							if (this._formatColFunctions[j] != null) {								
								cell.innerHTML=this._formatColFunctions[j](this._data[i][j]);
							} else {
								cell.innerHTML=this._data[i][j];
							}
						}
					}
				}
			}
			if (this._editable) {
				if ((this._rowEdit >= 0) && (this._rowEdit == i)) {
					row = this._tabla.rows[i+1-this._index];
				}

				var editableCell1 = row.insertCell(-1);
				var editableCell2 = row.insertCell(-1);
				if (this._rowEdit != i) {
				
					// If the rows are copyable, show the option
					if(this._copyable) {
						editableCell1.innerHTML= this._copyHtml;
						if (this._colStyles[j+1]) {
							Element.addClassName(editableCell1,this._colStyles[j+2]);
						}
						Event.observe(editableCell1, 'click', this.copyRow.bindAsEventListener(this,i));
					}
					
					editableCell2.innerHTML= this._deleteHtml;
					if (this._colStyles[j]) {
						Element.addClassName(editableCell2,this._colStyles[j+1]);
					}
					Event.observe(editableCell2, 'click', this.delRow.bindAsEventListener(this,i));
					
					// The edit action is link by the data rows of the table, the attribute indicesEditLink
					// can be used to determine how many colums are used as the edit link
					for(u = 0; (u < row.cells.length) && ((this._indicesEditLink == null) || (u < this._indicesEditLink)); u++) {
						Event.observe(row.cells[u], 'click', this.edit.bindAsEventListener(this,i));
						row.cells[u].innerHTML = "<a href='#'>" + row.cells[u].innerHTML + "</a>";
					}
					
				} else {
					editableCell1.innerHTML= this._acceptHtml;
					if (this._colStyles[j]) {
						Element.addClassName(editableCell1,this._colStyles[j]);
					}
					Event.observe(editableCell1, 'click', this.save.bindAsEventListener(this));
					if (this._colStyles[j+1]) {
						Element.addClassName(editableCell2,this._colStyles[j+1]);
					}					
					editableCell2.innerHTML= this._cancelHtml;
					Event.observe(editableCell2, 'click', this.cancelEdit.bindAsEventListener(this));
				}
				
			} else if (this._deletable) {
				var editableCell2 = row.insertCell(-1);
				if (this._colStyles[j]) {
						Element.addClassName(editableCell2,this._colStyles[j]);
				}
				editableCell2.innerHTML= this._deleteHtml;
				Event.observe(editableCell2, 'click', this.delRow.bindAsEventListener(this,i));
			}
		}
		
		if (this._adding) {
			row = this._tabla.insertRow(-1);
			if ((i - this._index) % 2 == 0) {
				Element.addClassName(row,this._evenStyle);
				
			} else {
				Element.addClassName(row,this._oddStyle);
				
			}
			for (j = 0; j < this._cols.length; j++) {
				if (this._cols[j] != "invisible") {
					if ((this._editableCols[j] != undefined)) {
							cell = row.insertCell(-1);
							cell.innerHTML=this._editableCols[j];
					} else {
						cell = row.insertCell(-1);
						if ((this._colStyles[j] && (!this._colStylesFunctions[j]))) {
							Element.addClassName(cell,this._colStyles[j]);
						} else if (this._colStylesFunctions[j]) {
							Element.addClassName(cell,this._colStylesFunctions[j](this._data[i][j]));
						}
					}
				}
			}
			var editableCell1 = row.insertCell(-1);
			var editableCell2 = row.insertCell(-1);
			if (this._colStyles[j]) {
				Element.addClassName(editableCell1,this._colStyles[j]);
			}	
			if (this._colStyles[j+1]) {
				Element.addClassName(editableCell2,this._colStyles[j+1]);
			}	
			editableCell1.innerHTML= this._acceptHtml;
			Event.observe(editableCell1, 'click', this.add.bindAsEventListener(this));
			editableCell2.innerHTML= this._cancelHtml;
			Event.observe(editableCell2, 'click', this.cancelEdit.bindAsEventListener(this));
			
			
		}
		if (this._rowEdit == -1) {
			var numColsNoInv = 0;
			for (j = 0; j < this._cols.length; j++) {
				if (this._cols[j] != "invisible") {
					numColsNoInv++;
				}
			}
			row = this._tabla.rows[this._tabla.rows.length-1];
			if (row.cells.length > numColsNoInv) {
				row.deleteCell(row.cells.length-1);
				row.deleteCell(row.cells.length-1);
			}
		}
		//this._tabla.innerHTML+=('');		
		
	},
	
	/**
	 * Set the number of columns that will be used as edit link
	 */
	setEditLink: function(index) {
		this._indicesEditLink = index;
	},
	
	paintPageShowers: function() {
		numPages = this.getTotalPages();
		currentPage = this.getCurrentPage();
		
		mostrar = this._pageInfoString.replace("#1", currentPage);
		mostrar = mostrar.replace("#2", numPages);
		for (i = 0; i < this._pageInfoShowers.length; i++) {
			$(this._pageInfoShowers[i]).innerHTML = mostrar;
			$(this._pageInfoShowers[i]).show();
		}
	},
	sortColumn: function (column) {
		this._rowEdit = -1;
		if (this._colOrder != column) {
			this._asc[this._colOrder] = undefined;
			this._asc[column] = false;
			this._index = 0;
		}
		this._colOrder = column;
		if (this._cols[column] == "string")
			var secuencia = new Function("x","y","return ( x[" + column + "] < y[" + column + "] ) ? -1 : ( x[" + column + "] > y[" + column + "] ) ? 1 : 0;");
		else if (this._cols[column] == "integer")
			var secuencia = new Function("x","y","return ( parseInt(x[" + column + "]) < parseInt(y[" + column + "]) ) ? -1 : ( parseInt(x[" + column + "]) > parseInt(y[" + column + "] )) ? 1 : 0;");
		else if (this._cols[column] == "float")
			var secuencia = new Function("x","y","return ( parseFloat(x[" + column + "]) < parseFloat(y[" + column + "]) ) ? -1 : ( parseFloat(x[" + column + "]) > parseFloat(y[" + column + "] )) ? 1 : 0;");			
		else if (this._cols[column] == "date")
			var secuencia = new Function("x","y","return ( string2fecha(x[" + column + "]) < string2fecha(y[" + column + "]) ) ? -1 : ( string2fecha(x[" + column + "]) > string2fecha(y[" + column + "] )) ? 1 :0;");
		if (!(this._asc[column])) {
			this._data.sort(secuencia);
			this._asc[column] = true;
			this._index = 0;
		} else {
			this._data.sort(secuencia).reverse();
			this._asc[column] = false;
			this._index = 0;
		}
		this.pintar();
	},
	sortColumnNoChange: function (column) {
		if (this._cols[column] == "string")
			var secuencia = new Function("x","y","return ( x[" + column + "] < y[" + column + "] ) ? -1 : ( x[" + column + "] > y[" + column + "] ) ? 1 : 0;");
		else if (this._cols[column] == "integer")
			var secuencia = new Function("x","y","return ( parseInt(x[" + column + "]) < parseInt(y[" + column + "]) ) ? -1 : ( parseInt(x[" + column + "]) > parseInt(y[" + column + "] )) ? 1 : 0;");
		else if (this._cols[column] == "float")
			var secuencia = new Function("x","y","return ( parseFloat(x[" + column + "]) < parseFloat(y[" + column + "]) ) ? -1 : ( parseFloat(x[" + column + "]) > parseFloat(y[" + column + "] )) ? 1 : 0;");
		else if (this._cols[column]== "date")
			var secuencia = new Function("x","y","return ( string2fecha(x[" + column + "]) < string2fecha(y[" + column + "]) ) ? -1 : ( string2fecha(x[" + column + "]) > string2fecha(y[" + column + "] )) ? 1 :0;");
		if (!(this._asc[column])) {
			this._data.sort(secuencia);
		} else {
			this._data.sort(secuencia).reverse();
		}
	},
	loadDataFromHtml: function() {
		for (i = 1; i < this._tabla.rows.length; i++) {
			dataRow = [];
			for (j = 0; j < this._tabla.rows[i].cells.length; j++) {
				dataRow[j] = this._tabla.rows[i].cells[j].innerHTML;
			}
			this._data[i-1] = dataRow;
		}
	}
}

	