/*
 * (c) Copyright Trilog Group 2004-2012. All Rights Reserved.
 */

/**************************Class Column***************************************
			Will be used to create the grid definition, which will
			include the number of olumns and several functionalities
			for the grid
		*/
		
		/*	Each Column must have:
			1- ID 
			2- label, 
			3- Default value(in case a cellin the grid was not given an initial value), 
			4- Type(list,boolean,integer,double,text,date,icon,label),
			5- Size,
			6-Required( boolean to state whether all the fields within that column have to be filled
			7-URL
			8- Optional icon-dimensions ( if not specified, by default the icon will be 16x16)
		*/
		function Column(id, label, value, type, size, required,popupURL , iconWidth , iconHeight, displayType, isPrimaryKey, subtype, title, pickerid, checkboxheaderenable,displaypickertype)
		{
			this.type = type; 
			this.label = label;
			this.value = value+"";
			this.id = id;
			this.size = size;
			this.required = required;
			this.iconWidth = iconWidth;
			this.iconHeight = iconHeight;
			this.popupURL = popupURL;
			this.displayType = displayType;
			this.columnFunction; 		// When we have a column of type list, this variable will hold the function that executes when we change values in the list
			this.isPrimaryKey = isPrimaryKey;
			this.subtype = subtype;
			this.title = title;			
			this.pickerid = pickerid;
			this.checkboxheaderenable = checkboxheaderenable;
			this.displaypickertype = displaypickertype;
			this.gridNls;
			
			this.className;
			
			this.setClassName = function(_className) {
				this.className = _className;
			}	
		}		
		
		/********************************Class Grid*****************************************/
		
		//localizationLanguage : initials of the country code, e.g: fr, en, en-US, zh-TW, etc...
		function dynamictable2(contextPath,localizationLanguage,_tableName)
		{	
			this.mouseSortable = false;		//Initially, drag and drop is disabled
			this.footerEnabled = false;		//Initilally, the footer is disabled
			this.addRowEvent = false ; 		//Initialize the addRowEvent to false
			this.insertRowEvent = false;	//Initialize the inserRowEvent to false
			this.moveRowDownEvent = false;	//Initialize the moveRowDownEvent to false
			this.moveRowUpEvent = false;	//Initialize the moveRowUpEvent to false
			this.deleteRowEvent = false;	//Initialize the deleteRowEvent to false
			this.deleteRowPickerEvent = false;
			this.checkAllEvent = false      //Initialize the checkAllEvent to false
			this.datePickerEvent = false;   //Initialize the datePickerEvent to false
			this.imagePickerEvent = false;   //Initialize the imagePickerEvent to false
			this.mouseClickEvent = false;
			this.popupCalendar = false;
			this.datePickerEventStatus = false;
			this.dojoCalendar = false;
			this.datePickerWidth = false;
			this.datePickerHeight = false;
			this.altMode = false;
			this.tableName = _tableName;
			this.initialRowCount = "";
			this.onChangeEvent = false;
			this.contextPath = contextPath;
			this.datePickerExist = false;
			this.linkPickerExist = false;
			this.listDropDownExist = false;
			this.moveRowDowExist = false;
			this.moveRowUpExist = false;	
			this.insertRowExist = false;				
			this.deleteRowExist = false;
			this.intCellExist = false;
			this.doubleCellExist = false;
			this.validateIntEvent = false;
			this.validateDoubleEvent = false;
			this.enableDoubleFormat = false;		
			if (localizationLanguage) {
				this.localizationLanguage = localizationLanguage;
			} else {
				this.localizationLanguage = "";
			}
				
			//Gets if the footer is enabled
			this.getFooterEnabled = function()
			{
				return this.footerEnabled;
			}			
		
			this.getAddRowEvent = function()
			{
				return this.addRowEvent;
			}
			
			this.getInsertRowEvent = function()
			{
				return this.insertRowEvent;
			}

			this.getOnChangeEvent = function()
			{
				return this.onChangeEvent;
			}
			
			this.getMoveRowDownEvent = function()
			{
				return this.moveRowDownEvent;
			}
			
			this.getMoveRowUpEvent = function()
			{
				return this.moveRowUpEvent;
			}
			
			this.getDeleteRowEvent = function()
			{
				return this.deleteRowEvent;
			}
			
			this.getDeleteRowPickerEvent = function()
			{
				return this.deleteRowPickerEvent;
			}
			
			this.getDatePickerExist = function()
			{
				return this.datePickerExist;
			}
			
			this.getLinkPickerExist = function()
			{
				return this.linkPickerExist;
			}
			
			this.getListDropDownExist = function(){
				return this.listDropDownExist;
			}
			
			this.getMoveRowDowExist = function(){
				return this.moveRowDowExist;
			}
			
			this.getMoveRowUpExist = function(){
				return this.moveRowUpExist;
			}

			this.getInsertRowExist = function(){
				return this.insertRowExist;
			}

			this.getEnableDoubleFormat = function(){
				return this.enableDoubleFormat;
			}


			this.getDeleteRowExist = function(){
				return this.deleteRowExist;
			}

			this.getIntCellExist = function(){
				return this.intCellExist;
			}
			
			this.getDoubleCellExist = function(){
				return this.doubleCellExist;
			}			
			
			this.getCheckAllEvent = function()
			{
				return this.checkAllEvent;
			}
			
			this.getDatePickerEvent = function()
			{
				return this.datePickerEvent;
			}
			
			this.getValidateIntEvent = function()
			{
				return this.validateIntEvent;
			}

			this.getValidateDoubleEvent = function()
			{
				return this.validateDoubleEvent;
			}
			
			this.getImagePickerEvent = function()
			{
				return this.imagePickerEvent;
			}
			
			this.getMouseClickEvent = function()
			{
				return this.mouseClickEvent;
			}
			
			this.getPopupCalendar = function()
			{
				return this.popupCalendar;
			}
			
			this.getDatePickerEventStatus = function()
			{
				return this.datePickerEventStatus;
			}
			
			this.getdojoCalendar = function()
			{
				return this.dojoCalendar;
			}
			
			this.getDatePickerWidth = function()
			{
				return this.datepickerWidth;
			}
			
			this.getDatePickerHeight = function()
			{
				return this.datepickerHeight;
			}
			
			this.getRowAlternationMode = function()
			{
				return this.altMode;
			}
			
			// return the class to set for the row in case of row alternation true
			this._getRowAlternationClass = function(rowIndex) {
				if(this.getRowAlternationMode() && rowIndex%2!=0){
					return "tgDynamicTableBorderTopColor tgDynamicTableAltRow";
				} else {
					return "tgDynamicTableBorderTopColor";
				}
			}		

			this.getTableName = function()
			{
				return this.tableName;
			}
			
			
			this.setRowAlternationMode = function(enableMode)
			{
				this.altMode = enableMode;
			}
			
			this.setInitialRowCount = function(_initialRowCount)
			{				
				this.initialRowCount = _initialRowCount;
			}
			
			this.getInitialRowCount = function()
			{
				return this.initialRowCount;
			}
					
				
			//Gets the localizationLanguage
			this.getLocalizationLanguage = function()
			{
				return localizationLanguage;
			}
			
			//Sets the given function to the column with given Index
			//Will be used in the method 'onChangeEvent()'
			this.setColumnChangeEvent = function(columnIndex, func)
			{			
				//if(dojo.isIE < 8)
					//columnIndex = columnIndex +1 ;
				this.columns[columnIndex].columnFunction = func;
			}
			
			this.setDatePickerExist = function(_datePickerExist)
			{
				this.datePickerExist = _datePickerExist;
			}

			this.setLinkPickerExist = function(_linkPickerExist)
			{
				this.linkPickerExist = _linkPickerExist;
			}			
			
			this.setListDropDownExist = function(_listDropDownExist){
				this.listDropDownExist = _listDropDownExist;
			}
						
			this.setMoveRowDowExist = function(_moveRowDowExist){
				this.moveRowDowExist = _moveRowDowExist;
			}
			
			this.setMoveRowUpExist = function(_moveRowUpExist){
				 this.moveRowUpExist = _moveRowUpExist;
			}

			this.setInsertRowExist = function(_insertRowExist){
				this.insertRowExist = _insertRowExist;
			}

			this.setDeleteRowExist = function(_deleteRowExist){
				this.deleteRowExist = _deleteRowExist;
			}

			this.setIntCellExist = function(_intCellExist){
				this.intCellExist = _intCellExist;
			}
			
			this.setDoubleCellExist = function(_doubleCellExist){
				this.doubleCellExist = _doubleCellExist;
			}	
			
			this.setEnableDoubleFormat = function(_enableDoubleFormat){
				this.enableDoubleFormat = _enableDoubleFormat;				
			}	
			
			this.getRowsCount = function(){
				var ID = this.id;
				var rows = dojo.query("#"+ID+ " > table > tbody > tr");
				var numOfRows = rows.length;				
				if(this.footerEnabled)
				{
					numOfRows--;
				}
				if (numOfRows < 0) numOfRows = 0;
				return numOfRows;
			}	
			
			/*Grid Definition*/
			/*	 - This is the main grid definition
				 - Each time we add a column, the array of columns in the
				Grid class gets incremented by one, and the added column gets 
				concatenated with the rest of the array.
			*/	
			
			//Array containing all the columns in the grid
			//Initially, the size of the array is 0
			this.columns = new Array(0);															
			
			/*Method that adds a column*/
			this.addColumn = function(id, label, value, type, size,required, popupURL,iconWidth, iconHeight, displayType, isPrimaryKey, subtype, title, pickerid, checkboxheaderenable, displaypickertype, className){	
				if(!iconWidth){	iconWidth = 16;}													//If not specified, iconWidth by default will be 16
				if(!iconHeight){ iconHeight = 16;}													//If not specified, iconHeight by default will be 16
				var newCol = new Column(id, label, value, type, size,required,popupURL, iconWidth, iconHeight,displayType, isPrimaryKey, subtype, title, pickerid, checkboxheaderenable, displaypickertype);
				if (className)
					newCol.setClassName(className);
					
				/*Concatinate the new column with the columns array*/
				this.columns = this.columns.concat(newCol);	
			};
			
			this.setMoveUpDownAlt = function(){				
				var ID = this.id;
				var moveUpObjects = dojo.query(".tg_pe_moveup_icon",document.getElementById(this.id));
				var moveDownObjects = dojo.query(".tg_pe_movedown_icon",document.getElementById(this.id));
				
				for(var j=0;j<moveUpObjects.length;j++){
					if(j==0)
						moveUpObjects[j].style.display = "none";
					else 
						moveUpObjects[j].style.display = "block";
				}
				
				for(var j=0;j<moveDownObjects.length;j++){
					if(j==moveDownObjects.length-1)
						moveDownObjects[j].style.display = "none";
					else
						moveDownObjects[j].style.display = "block";
				}					
			}
			
			this.setAltRow = function(){
				var ID = this.id;
				var numOfRows = 0;
				var rows = dojo.query("#"+ID+ " > table > tbody > tr");
				numOfRows = rows.length;				
				if(this.footerEnabled)
				{
					numOfRows--;
				}
				for(i=1;i<numOfRows;i++){
					var tr = dojo.query(" > ",rows[i]);	
					for(j=0;j<tr.length;j++){
						dojo.addClass(tr[j],"tgDynamicTableBorderTopColor");						
						if(this.getRowAlternationMode() && i%2!=0){							
							dojo.addClass(tr[j],"tgDynamicTableAltRow");				
						} else {						
							dojo.removeClass(tr[j],"tgDynamicTableAltRow");																																			
						}
					}
				}				
			}
			
			//Method to open the popup window of the given URL in the specified column
			//column_index : Index of the column in which the URL will be enabled
			this.enableColumnURL = function(column_index) {	
				var rows = dojo.query("#"+this.id+ " > table > tbody > tr");
				var numOfRows = rows.length - 1 ;
				
				var ID = this.id;
				if(this.footerEnabled)
				{
					numOfRows--;
				}
				//'var cell' will hold a grid cell at each iteration in the following for loop
				var cell;
				
				//Putting the URL coming from the column definition in a variable
				var URL = this.columns[column_index].popupURL;
				
				//Make sure the URL is not empty before opening a window
				if(this.columns[column_index].popupURL)
				{
					//Loop over the  each cell belonging to the column and assign the URL to it
					for (var j=0; j < numOfRows;j++)
					{	
						cell = this.getCell(j,column_index);
						
						//dojo on ready
						//dojo.addOnload(function(){
							dojo.query(cell).onclick( function(){
								var rowIndex = dojo.indexOf(rows,this);//Getting the index of the tr
								var resetURL = URL;//Saving the URL in resetURL for the next iteration, because there is concatination
								URL += "?tg_grid_row="+rowIndex+"tg_grid_col="+column_index;//Add the row index and column index to the URL
								window.open(URL,'','width=300,height=200,menubar=yes,status=yes,location=yes,toolbar=yes,scrollbars=yes');	//Open the URL on the click of the cell
								URL = resetURL;		//Resetting the URL to the original one	
							});
						//});		
					}
				}
			}
			
			
			
			/*	Action Columns:
				- They are columns used for moving rows up and down, and deleting rows
				- They are also placed in an array, and each time a Action column
				is created, the actionColumns array gets incremented by one, and
				the new manipualtion column gets concatinated to the array8?
			*/
			this.actionColumns = new Array(0);
			/*
				To add a action column, it has to have : 
					1 - ID
					2 - Label/Title
					3 - Icon
					4 - Functionality: moveUp,moveDown,delete,insertRow,dragAndDrop
					5 - Column Size
					6 - Icon Dimensions
			*/
			
			/*Add a action Column)*/
			this.addActionColumn = function(id, label, icon, functionality, size, iconWidth, iconHeight){
				if(!iconWidth){	iconWidth = 16;	}			//If not specified, iconWidth by default will be 16
				if(!iconHeight){ iconHeight = 16; }			//If not specified, iconHeight by default will be 16
				if(!size) { size = 25; }
				var newManCol = new Column(id, label, icon, functionality, size,false,"", iconWidth, iconHeight);
				//If the column is a 'drag-and-drop', the mouseSortable boolean is changed
				if(functionality == "dragAndDrop"){
					if(icon == ""){
						newManCol.value = contextPath+"/tgweb20/media/grippy.png";
					}
					var newActionColumn = new Array(1);
					newActionColumn[0] = newManCol;
					this.actionColumns = newActionColumn.concat(this.actionColumns);
					this.mouseSortable = true;
				}
				//Move Up
				else if(functionality == "moveUp"){
					if(icon == ""){
						//Set the icon to Up.gif
						newManCol.value = contextPath+"/tgweb20/media/Up.gif";
					}
					this.actionColumns = this.actionColumns.concat(newManCol);					
				}
				//Move Down
				else if(functionality == "moveDown"){
					if(icon == ""){
						//Set the icon to Down.gif
						newManCol.value = contextPath+"/tgweb20/media/Down.gif";
					}
					this.actionColumns = this.actionColumns.concat(newManCol);
				}
				//Delete
				else if(functionality == "delete"){
					if(icon == ""){
						//Set the icon to delete.gif
						//newManCol.value = contextPath+"/tgweb20/media/delete.gif";
						newManCol.value = contextPath+"/tgweb20/stylesheet/oneui/images/blank.gif";
					}
					this.actionColumns = this.actionColumns.concat(newManCol);
				}
				//Insert Row
				else if(functionality == "insertRow"){
					if(icon == ""){
						//Set the icon to New.gif
						newManCol.value = contextPath+"/tgweb20/media/New.gif";
					}
					this.actionColumns = this.actionColumns.concat(newManCol);
				}
			};
			
			//Gets the index of the column with the given ID
			this.getColumnIndexById = function(ID){
				for (var i=0; i< this.columns.length;i++){
					if(this.columns[i].id ==ID){
						return i;
					}
				}
				return null;
			}
			
			/*
				Selection Column is the left most column which contains
				the checboxes to select rows
			*/
			this.selectionColumnEnabled = false;		//Initially, selectionColumnEnabled is set to false
			
			/*
				Method to add the selection column
				***N.B: Do not add more than 1 selection column***
	
				To add a selection column, you hav eto specify :
					1- ID
					2- Label/Title
			*/
			this.addSelectionColumn = function(){				
				if(!this.selectionColumnEnabled){	//Make sure that NOT more than 1 selection column is added				
					var selectionColumn = new Column("tg_grid_selection_column", "", "", "selectionColumn", 25,false);
					
					//If drag-and-drop is enabled, the selection column is not the left most column
					if(this.mouseSortable){
						this.actionColumns.splice(1, 0, selectionColumn);
					}else{
						this.actionColumns.splice(0, 0, selectionColumn)
					}
					this.selectionColumnEnabled = true;
				}				
			}
			
			//Boolean to change editablity of grid
			this.edit = true;
			//Function to activate the 'editability' of the grid 
			this.editable = function(bool){				
				this.edit = bool;
				var ID = this.id;
				//Disable the whole grid, Make it read-only
				//This method used the html attribure "disabled"
				//Unlike the disableCell(cell_x,cell_y), it doesnt change to a label,
				//but rather disables the whole grid
				if(!this.edit){
					if(this.getSelectionColumnEnabled()){
						var colHeader = dojo.query("#"+ID+" > table > tbody > tr > th > *")[0];
						dojo.attr(colHeader,"disabled","disabled");
						dojo.addClass(colHeader,"tgDisabledInput");
					}
									
					//dojo.addOnLoad( function() {
						dojo.forEach(this.getDatePickerEvent(),function(x){
							dojo.disconnect(x);			
						});
						dojo.forEach(this.getImagePickerEvent(),function(x){
							dojo.disconnect(x);			
						});
						dojo.forEach(this.getValidateIntEvent(),function(x){
							dojo.disconnect(x);
						});						
						dojo.forEach(this.getValidateDoubleEvent(),function(x){
							dojo.disconnect(x);			
						});	

						dojo.forEach(this.getDeleteRowEvent(),function(x){	
							dojo.disconnect(x);			
						});	
						
						dojo.forEach(this.getDeleteRowPickerEvent(),function(x){
							dojo.disconnect(x);
						});	
						
						var allTd = dojo.query("#"+ID+" > table > tbody > tr > td > *");
						for (var i=0; i < allTd.length;i++)	
						{
				 			dojo.attr(allTd[i],"disabled","disabled");														
							if(allTd[i].nodeName.toLowerCase() =="input" || allTd[i].nodeName.toLowerCase() =="select")
								dojo.addClass(allTd[i],"tgDisabledInput");
						}
						
						var allLinkButton = dojo.query("#"+ID+" > table > tbody > tr > td > table > tbody > tr > td > a[func='deletepickerlink']");
						for (var i=0; i < allLinkButton.length;i++){							
							allLinkButton[i].onclick = "";
						}
					//});
				}else{
					if(this.getSelectionColumnEnabled()){
						var colHeader = dojo.query("#"+ID+" > table > tbody > tr > th > *")[0];
						dojo.removeAttr(colHeader,"disabled");
						dojo.removeClass(colHeader,"tgDisabledInput");
					}
					//dojo.addOnLoad(function(){
						var allTd = dojo.query("#"+ID+" > table > tbody > tr > td > *");
						for(var i=0; i < allTd.length;i++)
						{
							dojo.removeAttr(allTd[i],"disabled");
							if(allTd[i].nodeName.toLowerCase() =="input" || allTd[i].nodeName.toLowerCase() =="select")
								dojo.removeClass(allTd[i],"tgDisabledInput");
						}
					//});
					_initializeDatePicker(this,1);
					_initializeIntInputValidation(this,1);
				}
			};
			
			//Array that will hold information cominf from an XML file
			//Will contain the information from the XML string passed to the method setData(xml)
			this.gridData = new Array(0);
			
			//Array that will hold information coming to insert XML Row
			//Will contain the information from the XML string passed to the method setDataRow(xml)			
			this.gridData_row = new Array(0);
			
			/*
				- Method to set the data in the grid from an XML string passed to it
				- Fills the array 'gridData' with the information from the XML string
				and sets this information in the grid when it is loaded
			*/
			
			/* XML file for setData() should have the following format : 
			
				"<grid><row><value></value></row></grid>"
				
				***N.B : You can have as much row and value tags as you want,
						on the condition that the number of value tags in each row
						is equal.
						
						*If there is no data to put in the value tag, provide an empty value tag
			*/
			this.setData = function(xml){				
				//Code for IE				
				try{
					var xmlDoc=new ActiveXObject("Microsoft.XMLDOM");
  					xmlDoc.async="false";
  					xmlDoc.loadXML(xml);
				}catch(e){
					//Code for Firefox, Opera, Safari,etc...
					try {
    					var parser=new DOMParser();
    					xmlDoc=parser.parseFromString(xml,"text/xml");
   					}catch(e){
						alert(e.message);
					}
				}
				
				//Get all the rows from the XML string
				var allRowsTags = xmlDoc.getElementsByTagName("row");
				var numOfRows = allRowsTags.length;
				if(numOfRows > 0){	
					//Get the number of columns in the grid from the XML string(assuming correct XML format)
					var numOfCol = xmlDoc.getElementsByTagName("row")[0].getElementsByTagName("value").length;
				}else{	
					//If there are no rows, the number of columns is by default set to 0
					//This will be the case of an empty grid
					numOfCol = 0;
				}
				//data_array will hold the grid data from the XML string in an array
				var data_array= new Array(numOfRows);
				
				
				/*Putting the data coming from the XML string in the array*/
				/*
					Each entry in the array can have any of the following formats:
					
					1 - value
					2 - type///value
					3 - type///value///options
					4 - type///value///function body
					
				*/
				for(var i = 0; i < numOfRows; i++){
					data_array[i] = new Array(numOfCol);	//Specifying the row size in each iteration
					for(var j = 0; j < numOfCol; j++){
						//Get the type of cell from the type attribute given in the XML
						var cellType = allRowsTags[i].getElementsByTagName("value")[j].getAttribute("type");
						//Get the list of options if the type of the cell is a list
						var xmlOptions = decodeURIComponent(allRowsTags[i].getElementsByTagName("value")[j].getAttribute("options"));						
						//Get the function definition from the function attribute gicen in the XML in case  the type was a 'listFormula'
						var func = decodeURIComponent(allRowsTags[i].getElementsByTagName("value")[j].getAttribute("function"));
						//Get the defaultvalue of options if the type of the cell is a list // Added by Hady
						var xmlOptionsDefault = decodeURIComponent(allRowsTags[i].getElementsByTagName("value")[j].getAttribute("defaultvalue"));
						//Get linkOptions if the cellType is link // Added by Hady
						var linkOptions = allRowsTags[i].getElementsByTagName("value")[j].getAttribute("linkoptions");
						//If the value tag is non-empty, we get its value
						try{
							var cellValue = decodeURIComponent(allRowsTags[i].getElementsByTagName("value")[j].childNodes[0].nodeValue);
							if(cellValue == 'nbsp')
							cellValue = '';
						}catch(e){
							//If the value tag is empty, we get the default value in the column and give it to the cell
							cellValue = decodeURIComponent(this.columns[j].value);
						}
						
						//If the cellType is empty, assign to data_array[i][j] the column type
						if(cellType == null){
							data_array[i][j] = cellValue;
							if(this._isListFormula(this.columns[j].type)){
								data_array[i][j] = "listFormula///"+cellValue+ "///" + this.columns[j].value;
							}
						}
						//If the cellType is non-empty,  assign to data_array[i][j] the cellType
						else{
							//Saving the values in the array using the different pre-mentioned formats, depending on each case
							data_array[i][j] = cellType;							
							if(this._isListFormula(cellType)){
								data_array[i][j] += "///" + cellValue + "///" + func;
							}else if(this._isList(cellType)){
								data_array[i][j] += "///" + cellValue + "///" + xmlOptions+"///"+xmlOptionsDefault;
							}else if(this._isMultipleList(cellType)) {
								data_array[i][j] += "///" + cellValue + "///" + xmlOptions+"///"+xmlOptionsDefault;
							}else if(this._isLink(cellType)){
								data_array[i][j] += "///" + cellValue + "///" + xmlOptions+"///"+xmlOptionsDefault+"///"+linkOptions;
							} else if(this._isLabel(cellType)){
								data_array[i][j] += "///" + cellValue + "///" + xmlOptionsDefault;
							} else{
								data_array[i][j] += "///" + cellValue;
							}
						}						
						//Resetting the cellValue, cellType, and func variables to re-use on next iteration
						cellValue = "";
						cellType = null;
						func = null;
					}
				}
				this.setInitialRowCount(numOfRows);
				//Assign the values in data_array to gridData, so the grid now contains the data
				this.gridData = data_array;
			};
			
			//Initially, events are not triggered, so the boolean representing them is false
			var eventRowDelete = false;
			this.deleteRowFunction;
			this.onEventDeleteRow = function(bool, callbackFunction){
				eventRowDelete = bool;
				if(bool == true){
					this.deleteRowFunction = callbackFunction;	//Assigning the callBack function to the deleteRowFunction
				}
			}
			
			this.deleteAllRow = function(){
				if(this.edit){
					var ID = this.id;	
				
					//dojo Code
					var rows = dojo.query("#"+ID+" > table > tbody > tr");
					var numOfRows = rows.length - 1;
					
					if(this.footerEnabled){
						numOfRows--;
					}
					
					for(var i=0;i<numOfRows;i++){
						dojo.destroy(rows[i + 1]);
					}					
					
					dojo.forEach(this.getCheckAllEvent(),function(x){
						dojo.disconnect(x);
					});
					_checkAll(this);
				
					if(!this.deleteRowFunction){
						this.deleteRowfunction = false;
					}
					if(eventRowDelete && this.deleteRowFunction){
						this.deleteRowFunction();
					}
				}
				if(this.getRowAlternationMode){
					this.setAltRow();
				}
				this.setMoveUpDownAlt();
				_initializeGridActions(this,4);
			}
			
			//Delete the row with the given rowIndex
			this.deleteRow = function(rowIndex)	{
				if(this.edit){
					//dojo Code
					var rows = dojo.query("#"+this.id+" > table > tbody > tr");
					var numOfRows = rows.length - 1;
					
					if(this.footerEnabled){
						numOfRows--;
					}
				
					if(rowIndex >=0 && rowIndex < numOfRows){
						dojo.destroy(rows[rowIndex + 1]);
					}
					dojo.forEach(this.getCheckAllEvent(),function(x){
						dojo.disconnect(x);
					});
					_checkAll(this);
				
					if(!this.deleteRowFunction){
						this.deleteRowfunction = false;
					}
					if(eventRowDelete && this.deleteRowFunction){
						this.deleteRowFunction();
					}
				}
				if(this.getRowAlternationMode){
					this.setAltRow();
				}
				this.setMoveUpDownAlt();
				_initializeGridActions(this,4);
				_onChangeEvent(this,2);
				
			};
			
			var eventRowRemove = false;		//To hold enabling/disabling the function on the event
			this.removeRowFunction;			//To hold the callback function
			//Do something when the function removeRow is called
			/*
				bool: set it to true if you want to enable the callback function when removeRow is called
				callbackFunction : Function to call when removeRow is called
			*/
			this.onEventRemoveRow = function(bool, callbackFunction){
				eventRowRemove = bool;
				if(bool == true){
					this.removeRowFunction = callbackFunction;
				}
			}
			
			//Removes the last row from the grid
			this.removeRow = function(){
				//dojo
				var rows = dojo.query("#"+this.id+" > table > tbody > tr");
				var numOfRows = rows.length - 1;
				
				if(this.footerEnabled){
					numOfRows--;
				}
				
				this.deleteRow(numOfRows-1);
				
				if(!this.removeRowFunction){
					this.removeRowfunction = false;
				}
				if(eventRowRemove && this.removeRowFunction){
					this.removeRowFunction();
				}
			}
		
			var eventInsertRow = false;	//To hold enabling/disabling the function on the event
			this.insertRowFunction;		//To Hold the callback function
			//Do something when the InsertRow is triggered
			/*
				bool : set it 0to true if you want to enable the callback function when insertRow is called
			*/
			this.onEventInsertRow = function(bool, callbackFunction){
				eventInsertRow = bool;
				if(bool == true){
					this.insertRowFunction = callbackFunction;
				}
			}			
		
			//Inserts a row after the given parameter "rowIndex"
			this.insertRow = function(rowIndex){
				if(this.edit){		//Make sure the grid is editable before doing anything	
					var ActionColumnIndex = 0;
					var newRowHtml = "<tr>";
					
					if(this.mouseSortable) {		//Draw the drag-and-drop Column		
						newRowHtml += "<td class='"+this._getRowAlternationClass(rowIndex)+"' ";
						newRowHtml += "style='background-image:url("+this.actionColumns[ActionColumnIndex].value+"); background-repeat:no-repeat; background-position:center 7px; padding: 3px; cursor:move; vertical-align: top; overflow:hidden;' class='' func='dragAndDrop' width=5px>";		
						newRowHtml += "&nbsp</td>";	
						ActionColumnIndex++;
					}

					if(this.selectionColumnEnabled)	{ //Draw the selection Column						
						var tdWidth = this.actionColumns[ActionColumnIndex].size;
						newRowHtml += "<td func='selectionColumn' class='"+this._getRowAlternationClass(rowIndex)+"' ";
						if(tdWidth && tdWidth!='')
							newRowHtml += "style='overflow:hidden; padding: 3px; vertical-align: top;' width="+tdWidth+">";	
						else
							newRowHtml += "style='overflow:hidden; padding: 3px; vertical-align: top;'>";	
						newRowHtml += "<input type='checkbox' func='selectionColumn' class='tgInputBorder' style='vertical-align:top'></input>";
						newRowHtml += "</td>";							
						ActionColumnIndex++;
					}

					//Build a data row
					//At each cell, we take its type from the column definition
					for(var i = 0; i < this.columns.length; i++){							
						// draw cell (td)
						newRowHtml += this._createHtmlCell(this.columns[i], "", this.columns[i].type, this.columns[i].value, rowIndex);
					}

					//Drawing the action Columns
					newRowHtml += this._createHtmlActionColumns(rowIndex, ActionColumnIndex);
						
					newRowHtml += "</tr>";	//Close the <tr> tag
					ActionColumnIndex = 0;	//Resetting the actionColumnIndex					
					var rows = dojo.query("#"+this.id+" > table > tbody > tr"); 							
					numOfRows = rows.length - 1 ; 

					if(this.footerEnabled){
						numOfRows--;
					}
				
					if(numOfRows == 0 && rowIndex == 0)	{ //If the table is empty	
						dojo.query(rows[rowIndex]).addContent(newRowHtml,"after");
					}else{			
						if(rowIndex >= 0 && rowIndex < numOfRows){
							dojo.query(rows[rowIndex]).addContent(newRowHtml,"after");
						}else if(rowIndex == numOfRows){
							dojo.query(rows[rowIndex]).addContent(newRowHtml,"after");
						}
					}
					/*Re-initialize the events after drawing the grid(in case a change in order occurs)*/
					_initializeGridActions(this,5);
					this.initializeDND(this);
					dojo.forEach(this.getDatePickerEvent(),function(x){
						dojo.disconnect(x);			
					});
					dojo.forEach(this.getImagePickerEvent(),function(x){
						dojo.disconnect(x);			
					});
					dojo.forEach(this.getValidateIntEvent(),function(x){
						dojo.disconnect(x);
					});						
					dojo.forEach(this.getValidateDoubleEvent(),function(x){
						dojo.disconnect(x);			
					});						
					if(this.getDatePickerExist()){
						_initializeDatePicker(this,2);
					}
					//_validateInt(this);
					_initializeIntInputValidation(this,2);
					//validateDouble(this);
					_initializeDoubleInputValidation(this,2);
					_enableURL(this);
					if(this.getLinkPickerExist()){
						_intializeDeletePickerRow(this);
					}
					
					dojo.forEach(this.getCheckAllEvent(),function(x){
						dojo.disconnect(x);
					});

					_checkAll(this);
					if(this.getListDropDownExist()){
						_onChangeEvent(this,2);
					}
					
					if(!this.insertRowFunction)	{
						this.insertRowfunction = false;	//By default, set the boolean to false
					}
					if(eventInsertRow && this.insertRowFunction){
						var strFunc = this.insertRowFunction + "";
						strFunc = strFunc.substring(strFunc.indexOf("{")+1, strFunc.length-1);	//Get the function body
						
						//dojo Code
						strFunc = 'dojo.query("#'+this.id+' > table > tbody > tr > td").onclick(function(){'+strFunc+'});'; //Put the function body in a dojo call
						var newFunc = new Function(strFunc);		//Create the new function, containing old function body in a jQuery context
						newFunc();									//Call The new function
					}					

				if(this.getRowAlternationMode()){
					this.setAltRow();
				}
				this.setMoveUpDownAlt();
				}			
			};
			
			
			
			var eventAddRow = false;
			this.addRowFunction;
			//Call a function when addRow() is called
			/*
				bool : set it to true if you want the callbackFunciton to be executed whena row is added
				callbackFunction : Function you want to call
			*/
			this.onEventAddRow = function(bool, callbackFunction)
			{
				eventAddRow = bool;
				if(bool == true)
				{
					this.addRowFunction = callbackFunction;
				}
			}
			
			
			//Added by Hady
			// Get Number of Rows in the table

			this.getNumofRows = function()
			{
				var ID = this.id;
				var numOfRows = 0;
				//jQuery Code
				//var rows = jQuery("#"+ID+ " > table > tbody > tr:gt(0)");
				//dojo Code
				var rows = dojo.query("#"+ID+ " > table > tbody > tr");
				numOfRows = rows.length;
				if(this.footerEnabled)
				{
					numOfRows--;
				}				
				return numOfRows;
			}
			//Finish Added by Hady 
			
			//Adds a row at the bottom of the table
			this.addRow = function(rowsToAdd){				
				if(!rowsToAdd && rowsToAdd!=0){
					rowsToAdd = 1;
				}
				var ID = this.id;
				var numOfRows = 0;
				/*
					Changed Done by Hady
					enhancement done to change from jQuery to dojo
					Get all the rows elements by dojo using dojo.query
				*/
				var rows = dojo.query("#"+ID+ " > table > tbody > tr"); // dojo

				numOfRows = rows.length - 1 ; // dojo
				
				/*
					Change Finish - Hady
				*/
				if(this.footerEnabled){
					numOfRows--;
				}

				//Calls insert rows on the index of last row
				for(var i = 0; i < rowsToAdd; i++){
					this.insertRow(numOfRows);			
				}
				
				if(eventAddRow && this.addRowFunction){
					this.addRowFunction();
				}
			};
			
			var eventSwitchRows = false;
			this.switchRowsFunction;
			
			//Call a certain function when 2 rows are sitched
			/*
				bool :  set it to true if you want to execute the callbackFunction
				callbackfunction :  function to be executed if 2 rows are switched
			*/
			this.onEventSwitchRows = function(bool, callbackFunction){
				eventSwitchRows = bool;
				if(bool == true){
					this.switchRowsFunction = callbackFunction;
				}
			}
			
			//Switches the positions of the rows with the given indeces
			this.switchRows = function (rowAindex, rowBindex){
				//Make sure the grid is editable before trying to switch
				if(this.edit){
					/*
						Switch the indeces if rowA has a larger index
						because of the jQuery call 'jQuery(rowB).after(rowA);'.
						This call always places rowA after rowB, so in the case where 
						rowA has the higher index, we switch the indeces so that the
						'after' function will accomplish the switching correctly.
					*/
					if(rowAindex != rowBindex){						
						if(rowAindex > rowBindex){
							var tempIndex = rowBindex;
							rowBindex = rowAindex;
							rowAindex = tempIndex;
						}
					/*****************End of index switching**********/
						
						//Get all the rows in the grid, except the 1st one,
						//beacause it is header containing only labels,
						//This is done by the case tr:gt(0) => greater than (0)
						//dojo Code
						var rows = dojo.query("#"+this.id+" > table > tbody > tr");
						var numOfRows = rows.length;
						
						//If the footer is present, it should not as grid data
						//so we decrement the number of rows
						if(this.footerEnabled){
							numOfRows--;
						}
						rowAindex++;
						rowBindex++;
						
						//Check the boundaries of the selected indeces, make sure they are within the grid boundaries
						if(rowAindex >= 0 && rowAindex < numOfRows && rowBindex >= 0 && rowBindex < numOfRows){							
							var rowA = dojo.query(rows[rowAindex]);
							var rowB = dojo.query(rows[rowBindex]);
							dojo.query(rows[rowBindex]).addContent(rows[rowAindex],"after");
							if(rowBindex != rowAindex+1){							
								rows = dojo.query("#"+this.id+" > table > tbody > tr");
								dojo.query(rows[rowAindex]).addContent(rows[rowBindex],"before");																
								
							}
						}
						
						//Reinitialize the events after a switch is done
						dojo.forEach(this.getDatePickerEvent(),function(x){
							dojo.disconnect(x);
						});
						dojo.forEach(this.getImagePickerEvent(),function(x){
							dojo.disconnect(x);			
						});
						dojo.forEach(this.getValidateIntEvent(),function(x){
							dojo.disconnect(x);			
						});
						dojo.forEach(this.getValidateDoubleEvent(),function(x){
							dojo.disconnect(x);			
						});
						_initializeDatePicker(this,2);
						//_validateInt(this);
						_initializeIntInputValidation(this,2);
						validateDouble(this);
						_intializeDeletePickerRow(this);
						
						dojo.forEach(this.getCheckAllEvent(),function(x){
							dojo.disconnect(x);
						});
						
						_checkAll(this);
						
						if(eventSwitchRows && this.switchRowsFunction){
							this.switchRowsFunction();
						}
					} 
				}
				if(this.getRowAlternationMode()){
					this.setAltRow();
				}
				
				this.setMoveUpDownAlt();
			}
			
			var eventMoveRowUp = false;
			this.moveRowUpFunction;
			//Call a certain function when a row is moved up
			/*
				bool :  set it to true if you want to execute the callbackFunction
				callbackfunction :  function to be executed if a row is moved up
			*/
			this.onEventMoveRowUp = function(bool, callbackFunction){
				eventMoveRowUp = bool;
				if(bool == true){
					this.moveRowUpFunction = callbackFunction;
				}
			}
			
			//Move the row with the given index up one row
			this.moveRowUp = function(rowIndex){
				if(this.edit){
					//dojo Code
					var numOfRows = dojo.query("#"+this.id+ " > table > tbody > tr").length - 1 ;// We substract -1 because in jQuery where are getting all elments afte 0 gt(0)
					if(this.footerEnabled){
						numOfRows--;
					}
					//Check if the row is in the any of the rows except the 1st one
					if(rowIndex > 0 && rowIndex < numOfRows){
						this.switchRows(rowIndex, rowIndex-1);
					}
					//Check if rowIndex refers to row 0, and makes it the last row
					else if(rowIndex == 0){
						this.switchRows(rowIndex, numOfRows-1);
					}
					//Call events and validations after moving a row up
					_initializeGridActions(this,3);				
					_onChangeEvent(this,2);
					_validateInt(this);
					validateDouble(this);
					
					dojo.forEach(this.getCheckAllEvent(),function(x){
						dojo.disconnect(x);
					});

					_checkAll(this);
					
					if(!this.moveRowUpFunction){
						this.moveRowUpfunction = false;
					}
					if(eventMoveRowUp && this.moveRowUpFunction){
						this.moveRowUpFunction();
					}
				}
				if(this.getRowAlternationMode()){
					this.setAltRow();
				}
				this.setMoveUpDownAlt();
			}
			
			var eventMoveRowDown = false;
			this.moveRowDownFunction;
			
			//Call the function callbackFunction when moving a row down
			/*
				callbackFunction : function you want to call when a row is moved down
				bool 			 : set it to true to enable the function when the event is triggered
			*/
			this.onEventMoveRowDown = function(bool, callbackFunction){
				eventMoveRowDown = bool;
				if(bool == true){
					this.moveRowDownFunction = callbackFunction;
				}
			}
			
			//Moves the row with the given index down one level
			//rowIndex : Index of the row you want to move down
			this.moveRowDown = function(rowIndex){
				if(this.edit){
					var numOfRows = 0;					 
					//dojo Code
					numOfRows = dojo.query("#"+this.id+ " > table > tbody > tr").length - 1 ;//we substract -1 because in jQuery we are getting all elements after position 0 gt(0)
					if(this.footerEnabled){
						numOfRows--;
					}
					
					//Check if the row is any row except the bottom one
					if(rowIndex >= 0 && rowIndex < numOfRows-1){
						this.switchRows(rowIndex, rowIndex+1);
					}
					//Check if the selected row is the bottom-most row and switch it with the 1st row in the grid
					else if(rowIndex == numOfRows-1){
						this.switchRows(rowIndex, 0);
					}
					
					//Enable the events on the new ordering of the rows
					_initializeGridActions(this,2)
					_onChangeEvent(this,2);
					_validateInt(this);
					validateDouble(this);
					
					dojo.forEach(this.getCheckAllEvent(),function(x){
						dojo.disconnect(x);
					});

					_checkAll(this);
					
					if(!this.moveRowDownFunction){
						this.moveRowDownfunction = false;
					}
					//Call the function if the event is set to true
					if(eventMoveRowDown && this.moveRowDownFunction){
						this.moveRowDownFunction();
					}
				}
				if(this.getRowAlternationMode()){
					this.setAltRow();
				}
				this.setMoveUpDownAlt();
			};
			
			
			//Changes the type of the cell with coordinates cell_x,cell_y to a label, preserving the value that was originally in the cell
			this.disableCellColumn = function(cell_x,cell_y){
			 	var cell = this.getCell(cell_x, cell_y);
				if(dojo.attr(dojo.query(" > ",cell[0])[0],"type")=="checkbox"){
					dojo.attr(dojo.query("#"+this.id+" > table > tbody > tr > th > input[type='checkbox']")[0],"disabled","disabled");
				}
				dojo.attr(dojo.query(" > ",cell[0])[0],"disabled","disabled");
			}
			
			this.enableCellColumn = function(cell_x,cell_y){
			 	var cell = this.getCell(cell_x, cell_y);
				if(dojo.attr(dojo.query(" > ",cell[0])[0],"type")=="checkbox"){
					dojo.removeAttr(dojo.query("#"+this.id+" > table > tbody > tr > th > input[type='checkbox']")[0],"disabled");
				}
				dojo.removeAttr(dojo.query(">",cell[0])[0],"disabled");
			}
			
			this.disableCell = function(cell_x,cell_y){
			 	var cell = this.getCell(cell_x, cell_y);
				dojo.attr(dojo.query(" > ",cell[0])[0],"disabled","disabled");
			}
			
			//Enable a disabled cell
			/*
				cell_x : x_position of the cell
				cell_y : y_position of the cell
				cellType : The type you want the cell to be
				cellValue : The value to be put by default when the cell's type is changed
			*/
			this.enableCell = function(cell_x, cell_y, cellType, cellValue){
				var cell = this.getCell(cell_x, cell_y);
				dojo.removeAttr(dojo.query(">",cell[0])[0],"disabled");
			}
			
			//Disables the whole column by making it a label
			this.disableColumn = function(column_index){
				//dojo Code
				var rows = dojo.query("#"+this.id+" > table > tbody > tr");
				var numberOfRows = rows.length - 1;				
				if(this.footerEnabled){
					numberOfRows--;
				}				
				for( var i =0 ; i < numberOfRows ; i++ ){					
					this.disableCellColumn(i+2,column_index);
				}
			}
			
			//Disables the whole column by making it a label
			this.enableColumn = function(column_index){
				var rows = dojo.query("#"+this.id+" > table > tbody > tr");
				var numberOfRows = rows.length - 1;				
				if(this.footerEnabled){
					numberOfRows--;
				}				
				for( var i =0 ; i < numberOfRows ; i++ ){					
					this.enableCellColumn(i+2,column_index);
				}
			}
			
			//Gets the rows whose checkboxes are checked in the selection column
			this.getSelectedRows = function(){
				var selectedRows = new Array(0);				
				var ID = this.id;
				var i =0;
				dojo.forEach(dojo.query("#"+this.id+" > table > tbody > tr > td > input[type='checkbox'][func='selectionColumn']"),function(){
					var cellsCheckBox = dojo.query("#"+ID+" > table > tbody > tr > td > input[type='checkbox']");
					if(dojo.attr(cellsCheckBox[i],"checked")==true){
						var rowIndex = dojo.indexOf(dojo.query("#"+ID+" > table > tbody > tr > td > input[func='selectionColumn']"),
										cellsCheckBox[i]);
						selectedRows.push(rowIndex);
					}
					i++;
   			    });				
				return selectedRows;				

			}
			
			//Deletes the rows whose checkbox in the selection column are checked
			this.deleteSelectedRows = function(){
				var selectedRows = this.getSelectedRows();
				for(var i = selectedRows.length-1; i >=0; i--){
					this.deleteRow(selectedRows[i]);
				}
			}
			
			//Switches the 2 rows whose checkboxes are selected in the selection column
			/* N.B : You cannot select more or less than 2 rows to switch */
			this.switchSelectedRows = function(){
				var selectedRows = this.getSelectedRows();
				if(selectedRows.length == 2){
					this.switchRows(selectedRows[0], selectedRows[1]);
				}else if(selectedRows.length < 2){
					alert(this.gridNls.lessThan2Rows);//'lessThan2Rows' comes from translation files
				}else{
					alert(this.gridNls.moreThan2Rows);//'moreThan2Rows' comes from translation files
				}
			}
			
			//Gets the type of the specified cell
			/*
				row : which row the cell belongs to
				column : which column the cell belongs to
				
				The method returns a string containing the cell type
				Possible output values : list,boolean,text,label,ineteger,double,listFormula,date,icon
			*/
			this.getCellType = function(row, column){
				var cell=this.getCell(row, column);
				if (!cell || !cell[0]) return null; //No types are matched, return null
				cell=cell[0];
				var firstChild=dojo.query(">",cell)[0];// cell.firstChild is not always an element
				
				var tag = firstChild.tagName;

				//Go through cases
				//Case input
				if(tag == "INPUT"){
					cellType = dojo.attr(firstChild,"type");
					if(cellType == "text"){
						cellType = dojo.attr(firstChild,"textType");
					}
				}
				//Case Select
				else if(tag == "SELECT"){
					cellType = dojo.attr(firstChild,"listType");
				}
				//Case icon
				else if(tag == "IMG"){
					cellType = "icon";		//return 'icon'
				}else{
					cellType = tag.toLowerCase();	//return the tag
				}
				return cellType;
			}
						
			
			//Gets a cell without its  value, or inside content
			//This function is mainly used in other functions
			/* WARNING:
				cell_x : row
				cell_y : column
				
				WARNING: return null or a collection containing 1 td element.
				 (it would be too easy to just return the element!)
			*/
			this.getCell = function(cell_x,cell_y){
				//dojo Code
				var numOfRows = dojo.query("#"+this.id+ " > table > tbody > tr").length;				
				if(this.footerEnabled){
					numOfRows--;
				}
				
				var initialUncountedColumns = 0;
				if(this.mouseSortable){
					initialUncountedColumns++;
				}
				if(this.selectionColumnEnabled){
					initialUncountedColumns++;
				}
			
				//Check if required cell is within grid boundaries
				if(cell_x >= 0 && cell_y >= 0 && cell_x <= numOfRows && cell_y < (this.columns.length+initialUncountedColumns))	{
					var rowArray=dojo.query("#"+this.id+ " > table > tbody > tr:nth-child("+cell_x+")");
					if (rowArray.length>0) {
						
						// remark: we do not query directly "#"+this.id+ " > table > tbody > tr:nth-child("+cell_x+") > td"
						//         because there is a bug with chrome the first time on some tables (unexplained)
						var cells=rowArray[0].cells;
						return dojo.query(cells[cell_y]); // we do not just return cells[cell_y]; as it would break existing code
					}
					
					/*
					var cells= dojo.query("#"+this.id+ " > table > tbody > tr:nth-child("+cell_x+") > td");
					//Return the required cell
					return dojo.query(cells[cell_y]);
					*/
				}
				return null;
			}
			
			/*
				Gets the required value of the cell in row=row, and column=column
			*/
			this.getCellValue = function(row, column, type){
				var cell=this.getCell(row, column);
				if (!cell || !cell[0]) return null;
				cell=cell[0];
					
				var cellType = this.getCellType(row, column);	//get the type of the cell
				var firstChild=dojo.query(">",cell)[0];// cell.firstChild is not always an element
				var cellValue = "";

				//In case of a label, return the innerHTML
				if(cellType == "LABEL" || cellType == "label"){
					cellValue = firstChild.innerHTML;
				}
				//in case of icon, return the 'src' attribute
				else if(cellType == "icon" || cellType == "Icon"){
					cellValue = dojo.attr(firstChild,"src");
				}
				//in case of link
				else if(cellType == "table"){
					labels = dojo.query("label",firstChild);
					inputs = dojo.query("input",firstChild);
					if(labels.length > 0){
						for(i=0;i<labels.length;i++){
							if(i==0){
								if(type=="label"){
									cellValue += labels[i].innerHTML;
								} else if(type=="value"){
									cellValue += labels[i].getAttribute('value');
								} else {
									cellValue += labels[i].getAttribute('value')+";"+labels[i].innerHTML;
								}									
							}else {
								if(type=="label"){
									cellValue += "|" +labels[i].innerHTML;
								} else if(type=="value"){
									cellValue += "|" + labels[i].getAttribute('value');
								} else {
									cellValue += "|" + labels[i].getAttribute('value')+";"+labels[i].innerHTML;
								}									
							}
						}
					} else if(inputs.length > 0){
						for(i=0;i<inputs.length;i++){
							if(i==0){									
								cellValue += inputs[i].getAttribute('value');
							}else {
								cellValue += "|" + inputs[i].getAttribute('value');
							}
						}
					}
					
				}		
				//in case of checkbox, return the 'checked' attribute
				else if(cellType == "checkbox"){						
					if (firstChild) {
						cellValue = dojo.attr(firstChild,"checked");
					}
				}			
				//in case of double, return the value
				else if(cellType == "double"){						
					cellValue = convertDoubleToPrimitive(trim(firstChild.value));						
				}
				//any other case, return the value of the cell
				else {
					cellValue = firstChild.value;
				}
				
				return cellValue;
			}
			
			
			//Sets the type of the cell with row=cell_x, column=cell_y to type, and gives a default value
			/* 	defaultValue is optional
				cell_x,cell_y,and type are obligatory
			*/
			this.setCellType = function(cell_x,cell_y,type,defaultValue, linktype,linklabel,linktitle, pickerid,selectedValue, displaypickertype, inputpickersize){
				if(this.edit){
					//If there is no defaultValue, set it to be the empty string
					if(!defaultValue){
						defaultValue = "";
					}
					//Get the array of rows
					var rows = dojo.query("#"+this.id+" > table > tbody > tr");
					//Get the number of rows
					var numOfRows = rows.length - 1;					
					//Decrement the number of rows if the footer is enabled
					if(this.footerEnabled){
						numOfRows--;
					}
					//Check how many action columns we have initially
					var initialUncountedColumns = 0;
					if(this.mouseSortable){
						initialUncountedColumns++;
					}
					if(this.selectionColumnEnabled){
						initialUncountedColumns++;
					}
					
					var col= dojo.query(" > ",rows[cell_x]);

					//Make sure the required cell is within the grid's boundaries
					if(cell_x >=0 && cell_x <= numOfRows && cell_y >=0 && cell_y < (this.columns.length+initialUncountedColumns)){
						//Check for types
						
						//Case Boolean
						if(this._isBoolean(type)){
							if(defaultValue == "true" || defaultValue == true){
								dojo.html.set(col[cell_y],"<select class='tgInputBorder' listType='boolean' style='vertical-align:top'><option selected='selected'>"+this.gridNls.boolYes+"</option><option>"+this.gridNls.boolNo+"</option></select>");
							}else{
								dojo.html.set(col[cell_y],"<select class='tgInputBorder' listType='boolean' style='vertical-align:top'><option>"+this.gridNls.boolYes+"</option><option selected='selected'>"+this.gridNls.boolNo+"</option></select>");
							}
						}
						//Case CheckBox
						else if(this._isCheckbox(type)){
							if(defaultValue == "true" || defaultValue == true){								
								dojo.html.set(col[cell_y],"<input textType='checkbox' type='checkbox' func='selectionColumn' class='tgInputBorder' style='vertical-align:top' checked='true'></input>");						
							} else {
								dojo.html.set(col[cell_y],"<input textType='checkbox' type='checkbox' func='selectionColumn' class='tgInputBorder' style='vertical-align:top'></input>");						
							}
						}
						//Case Text
						else if(this._isText(type)){
							dojo.html.set(col[cell_y],"<input style='vertical-align:top' class='tgInputBorder' size="+this.columns[cell_y - initialUncountedColumns].iconWidth+" type='text' textType='text' value=\""+defaultValue.replace(/"/g, "&quot;")+"\" ></input>");						
						}
						//Case TypeAhead
						else if(this._isTypeAhead(type)){
							dojo.html.set(col[cell_y],"<input style='vertical-align:top' class='tgInputBorder' size="+this.columns[cell_y - initialUncountedColumns].iconWidth+" type='text' textType='typeahead' value=\""+defaultValue.replace(/"/g, "&quot;")+"\" ></input>")
						}
						//Case Icon
						else if(this._isIcon(type)){
							var imgHtml = "<img class='' width="+this.columns[cell_y].iconWidth+"px height="+this.columns[cell_y - initialUncountedColumns].iconHeight+"px src="+defaultValue+"></img>"
							dojo.html.set(col[cell_y],imgHtml);
						}
						//Case List Multiple
						else if(this._isMultipleList(type)){
							var optionsArray = defaultValue.split("||");
							var innerValues = new Array(optionsArray.length);
							var displayValues = new Array(optionsArray.length);
							
							for(var entry = 0; entry < optionsArray.length; entry++){
								var entrySplit = optionsArray[entry].split(";");
								innerValues[entry] = entrySplit[0];
								displayValues[entry] = entrySplit[1];
							}
							
							var listSize = '';
							var columnSize = this.columns[cell_y].size;
							if(columnSize && parseInt(columnSize)){
								listSize = columnSize - ((columnSize*5)/100);							
							}
							
							var str = "";
							var selectedValueArray = '';
							if(selectedValue && selectedValue != '')
								selectedValueArray = selectedValue.split("||");
								for (var i=0;i<optionsArray.length;i++){
									var listValue = innerValues[i]+";"+displayValues[i];
									var valueAdded = false;
									for(var j=0;j<selectedValueArray.length;j++){
										if(listValue == selectedValueArray[j]){
											str += "<option selected='selected' value=\""+innerValues[i]+"\">"+ displayValues[i].replace(/"/g, "&quot;")+"</option>";
											valueAdded = true;
											continue;
										} 							
									}
									if(!valueAdded)
									str += "<option value=\""+innerValues[i]+"\">"+ displayValues[i].replace(/"/g, "&quot;")+"</option>";									
								}
							
							dojo.html.set(col[cell_y],"<select class='tgInputBorder' listType='multiplelist' style='vertical-align:top;' multiple>"+str+"</select>");
						}
						//Case List
						else if(this._isList(type) || this._isSelect(type)){
							var optionsArray = defaultValue.split("||");
							var innerValues = new Array(optionsArray.length);
							var displayValues = new Array(optionsArray.length);
							
							for(var entry = 0; entry < optionsArray.length; entry++){
								var entrySplit = optionsArray[entry].split(";");
								innerValues[entry] = entrySplit[0];
								displayValues[entry] = entrySplit[1];
							}
							
							var listSize = '';
							var columnSize = this.columns[cell_y].size;
							if(columnSize && parseInt(columnSize))
								listSize = columnSize - ((columnSize*5)/100);							
							
							var str = "";
							for (var i=0;i<optionsArray.length;i++){
								var listValue = innerValues[i]+";"+displayValues[i];
								if(listValue == selectedValue){
									str += "<option selected='selected' value=\""+innerValues[i]+"\">"+ displayValues[i].replace(/"/g, "&quot;")+"</option>";
								} else {
									str += "<option value=\""+innerValues[i]+"\">"+ displayValues[i].replace(/"/g, "&quot;")+"</option>";									
								}								
							}
							col[cell_y].width = '';
							dojo.html.set(col[cell_y],"<select class='tgInputBorder' listType='list' style='vertical-align:top;'>"+str+"</select>");
							this.setListDropDownExist(true);
						}
						//Case Link
						else if(this._isLink(type)){
							var optionsArray = defaultValue.split("||");
							var innerValues = new Array(optionsArray.length);
							var displayValues = new Array(optionsArray.length);
							
							for(var entry = 0; entry < optionsArray.length; entry++){
								var entrySplit = optionsArray[entry].split(";");
								innerValues[entry] = entrySplit[0];
								displayValues[entry] = entrySplit[1];
							}							
							
							var rowNumber = this.getInitialRowCount();
							var position = cell_y - initialUncountedColumns;
							var id = this.tableName+'_'+this.columns[position].id+'_'+rowNumber;
							var newRowHtml = "<table id=\""+id+"\" style='width:100%'>";
							newRowHtml += "<tbody>";
							newRowHtml += "<tr>";
							if(!this.displayLinkCont){
								newRowHtml += "<td style='border:0px;padding:0px;vertical-align:top;display:none';>";
							} else{
								newRowHtml += "<td style='border:0px;padding:0px;vertical-align:top'>";
							}
			    						  
							newRowHtml += "<table>";
							newRowHtml += "<tbody>";			
							for(var j = 0; j < optionsArray.length; j++){
								newRowHtml += "<tr id=\""+this.tableName+'_'+this.columns[position].id+'_sub_'+j+"\"><td style='border:0px;padding:0px;vertical-align:top;width:100%'>";
								if(innerValues[j] != ''){
									if(displaypickertype == "input"){
										newRowHtml += "<input value=\""+innerValues[j]+"\" style='' class='tgInputBorder' size="+inputpickersize+">";										
									}else if(displaypickertype == "label"){
										newRowHtml += "<label value=\""+innerValues[j]+"\" style=''>"+displayValues[j].replace(/"/g, "&quot;")+"</label>";
									} else {
										newRowHtml += "<label value=\""+innerValues[j]+"\" style=''>"+displayValues[j].replace(/"/g, "&quot;")+"</label>";
									}
									newRowHtml += "&nbsp<a class='lotusDelete'><img height=12 width=12 aria-label='delete button' alt='' src=\""+contextPath+"/tgweb20/stylesheet/oneui/images/blank.gif\" func='deletepicker'><span class='lotusAltText'>X</span></a>";							
								}
								newRowHtml +="</td></tr>";
								
							}
							newRowHtml += "</tbody>";
							newRowHtml += "</table>";
							
							newRowHtml += "</td>";
							newRowHtml += "<td style='border:0px;padding:0px;vertical-align:top;text-align:right'>";
							var script ='';
							if(pickerid && pickerid != ''){
								script = "setDynamicTablePickerTableId(\""+id+"\");";
								script += "if(document.getElementById(\""+pickerid+"\")){document.getElementById(\""+pickerid+"\").click();}else{eval(\""+pickerid+"\")}";
							}
							if(linktype == 'link'){
								newRowHtml += "&nbsp<a class='lotusAction' title=\""+linktitle.replace(/"/g, "&quot;")+"\" onclick='"+script+"' func='deletepickerlink'>"+linklabel.replace(/"/g, "&quot;")+"</a>";						
							}
							else if(linktype == 'image'){
								newRowHtml += "&nbsp<img imgtype='picker' align='absmiddle' width=12 height=12 src=\""+contextPath+"/tgweb20/media/picker.gif\" title=\""+linktitle.replace(/"/g, "&quot;")+"\" onclick='"+script+"' func='deletepickerlink'></img>";											
							}
							newRowHtml += "</td>";			
							newRowHtml += "</tr>";			
							newRowHtml += "</tbody>";							
							newRowHtml += "</table>";				
							dojo.html.set(col[cell_y],newRowHtml);		
							rowNumber++; 
							this.setInitialRowCount(rowNumber);  					
							this.setLinkPickerExist(true);
						}
						//Case listFormula
						else if(this._isListFormula(type)){
							defaultValue += "";
							var defaultFunction = defaultValue;
							defaultValue = defaultValue.substring(defaultValue.indexOf("{")+1, defaultValue.length-1);	//Get the function body alone
							var func = new Function(defaultValue);		//Create a new function containing only the function body
							var optionsArray = func();					//Let the function return its values to the optionsArray
							optionsArray = optionsArray.split("||");	//Start splitting the array
							
							var innerValues = new Array(optionsArray.length);
							var displayValues = new Array(optionsArray.length);
							
							//Split inner and display values
							for(var entry = 0; entry < optionsArray.length; entry++){
								var entrySplit = optionsArray[entry].split(";");
								innerValues[entry] = entrySplit[0];
								displayValues[entry] = entrySplit[1];
							}
							
							var str = "";
							for (var i=0;i<optionsArray.length;i++){
									str += "<option value=\""+innerValues[i]+"\">"+ displayValues[i].replace(/"/g, "&quot;")+"</option>";
							}
							dojo.html.set(col[cell_y],"<select class='tgInputBorder' listType='listFormula' function=\""+defaultFunction+"\" style='vertical-align:top'>"+str+"</select>");
						}
						//Case Label
						else if(this._isLabel(type)){
							if(defaultValue ==""){
								defaultValue = "&nbsp;";
							}
							dojo.html.set(col[cell_y],"<label>"+defaultValue.replace(/"/g, "&quot;")+"</label>");
						}
						//Case Integer
						else if(this._isInteger(type)){
							dojo.html.set(col[cell_y],"<input style='vertical-align:top' class='tgInputBorder' size="+this.columns[cell_y - initialUncountedColumns].iconWidth+" type='text' textType='integer' value=\""+defaultValue+"\" ></input>");
							this.setIntCellExist(true);
						}
						//Case Date
						else if(this._isDate(type)){
							dojo.html.set(col[cell_y],"<input style='vertical-align:top' class='tgInputBorder' type='text' textType='date' size="+10+" value =\""+defaultValue +"\">&nbsp<img imgtype='date' align='absmiddle' width=16 height=16 src=\""+contextPath+"/tgweb20/media/Calendar.gif\"></img>");
							this.setDatePickerExist(true);
						}
						//Case Double
						else if(this._isDouble(type)){
							var className = this.columns[cell_y - initialUncountedColumns].className;
							if (className)
								className += " tginputBorder";
							else className = "tginputBorder";
							
							
							var doubleValue = '';
							if(this.getEnableDoubleFormat()){
								doubleValue = dojo.number.format(defaultValue,{places:2});
							} else{ 
								doubleValue = defaultValue;
							}
							dojo.html.set(col[cell_y],"<input style='vertical-align:top' class='"+className+"' size="+this.columns[cell_y - initialUncountedColumns].iconWidth+" type='text' textType='double' value=\""+doubleValue+"\" onChange='validateDoubleInput(this,\""+this.gridNls.invalidDouble+"\")'></input>");
							this.setDoubleCellExist(true);
						}
					}
				}
				//Re-initialize the events after drawing the grid(in case a change in order occurs)				
				if(this.getDatePickerExist()){
					_initializeDatePicker(this,2);
				}
				//_validateInt(this);
				_initializeIntInputValidation(this,2);
				//validateDouble(this);
				_initializeDoubleInputValidation(this,2);
				if(this.getListDropDownExist()){
					_onChangeEvent(this,2);
				}
				if(this.getDatePickerExist()){
					_intializeDeletePickerRow(this);
				}
			};
			
			this.addToCellsValue = function(cell_y,value){
				for(var i=0;i<this.getNumofRows();i++){
					this.addToCellValue(i,cell_y,value);
				}
			}
			
			//add the value of the required cell of row=cell_x and column=cell_y to 'value'
			/**N.B : All 3 parameters are obligatory**/
			this.addToCellValue = function(cell_x,cell_y,value){
				//Make sure the grid is editable
				if(this.edit){
					//Get all the rows in the grid except the header
					/*
						By writing 'jQuery("#"+this.id+" > table > tbody > tr:gt(0)");' , we are getting all the rows of index greater than 0
						In this way, we are skipping the header
					*/
					var rows  = dojo.query("#"+this.id+" > table > tbody > tr");
					var numOfRows = rows.length - 1 ;
														
					//Number of rows
					//Decrement the number of rows if the footer is enabled
					if(this.footerEnabled){
						numOfRows--;
					}
					//See how many action columns there are before the 1st data cell
					var initialUncountedColumns = 0;
					if(this.mouseSortable){
						initialUncountedColumns++;
					}
					if(this.selectionColumnEnabled){
						initialUncountedColumns++;
					}
					//Check if the required cell is within the grid boundaries
					if(cell_x >=0 && cell_x <= numOfRows && cell_y >=0 && cell_y <(this.columns.length+initialUncountedColumns)){
						//Get the columns starting with the 1st data column
						var col = dojo.query(">",rows[cell_x]);

						//Get the type of the cell
						var cellType = dojo.query(">",col[cell_y]);
						//Case Select tag was encountered, we get the attribute 'listType'
						if(dojo.query(cellType).filter("select").length>0){							
							//Get the attribute 'listType'
							var listType = dojo.attr(cellType[0],"listType");
						
							//If the listType is a 'listFormula' or a list:
							//seperate the inner and display values and give the wanted valuethe attribute  'selected'							
							if(this._isList(listType) || this._isListFormula(listType)){
								var dataSplit = value.split("||");
								
								for( var j = 0 ; j < dataSplit.length ; j++){					
								
									//Get the options array
									var opArray = dojo.query(">",cellType[0]);								
									//Split inner and display values
									var valueSplit = dataSplit[j].split(";");
									var innerValue = valueSplit[0];
									var displayValue = valueSplit[1];
									
									//Compare the 'value' parameter to the values in the options Array
									for(var i = 0 ; i < opArray.length ; i++){
										var optionInnerValue = dojo.query(opArray[i])[0].value;
										var optionDisplayValue = opArray[i].innerHTML;
	
										/*If both inner and display values of an entry in the options
										array match both inner and display values in the value paramter,
										give this option the attribute 'selected'*/
										if(optionInnerValue == innerValue && optionDisplayValue == displayValue){
											//dojo.attr(opArray[i],"selected","selected");
											//When the 1st match is found, break from the loop because there shouldn't be any two identical options in the list
											break;
										} else if(i==(opArray.length-1)) { // add to the list at the end of the loop to be sure that the value added doesn't exist before
											var optionNew = document.createElement('option');
											optionNew.innerHTML = displayValue;
											optionNew.value = innerValue;				
											dojo.query(cellType)[0].appendChild(optionNew);
										}
									}
								}
							}
						}
					}
				}
				//Re-initialize the events after drawing the grid(in case a change in order occurs)
				//_validateInt(this);
				_initializeIntInputValidation(this,2);
				//validateDouble(this);
				_initializeDoubleInputValidation(this,2);
				_initializeDatePicker(this,2);	
				_intializeDeletePickerRow(this);
			}
			
			this.checkPrimaryDataExist = function(value){
				for(var i=0;i<this.columns.length;i++){
					if(this.columns[i].isPrimaryKey){
						for(var j =0 ;j<this.getNumofRows();j++){
							if(j!=0){	
								if(value == this.getCellValue(j+1,i)){
									return true;
								}
							}
						}
					}
				}
				return false;				
			}
			
			this.checkColumnDataDuplication = function(index,value){
				for(var i=0;i<this.columns.length;i++){						
					if(i==parseInt(index)){
						for(var j =0 ;j<this.getNumofRows();j++){
							if(j!=0){	
								if(value == this.getCellValue(j+1,i)){
									return true;
								}
							}
						}
					}
				}
				return false;				
			}	
			
			this.checkColumnCellsDataDuplication = function(index){		
				for(var i=0;i<this.columns.length;i++){ 
					if(i==parseInt(index)){
						for(var j=0 ;j<this.getNumofRows();j++){
							if(j!=0){ 								
								for(var k =j+1 ;k<this.getNumofRows();k++){
									var cell1 = this.getCellValue(k+1,i);
									var cell2 = this.getCellValue(j+1,i);
									if(cell1.toLowerCase() == cell2.toLowerCase()){
										if(cell1 != "")
											return true;
									}
								}

							}		
						}
					}
				}
				return false; 
			} 
			
			this.getColumnIndexDataDuplication = function(index){		
				var columIndex = parseInt(index);
				var arrayList = new Array();
				for(var i =1 ;i<this.getNumofRows();i++){
					arrayList[i-1] = this.getCellValue(i+1,columIndex);
				}
			 
				for(var i =0 ;i<arrayList.length;i++){
					var cell1 = arrayList[i];
					for(var k =i+1 ;k<arrayList.length;k++){					
						cell2 = arrayList[k];
						if(cell1.toLowerCase() == cell2.toLowerCase()){
							if(cell1 != "")
							return k+1;
						}				
					}
				}
				return false;
			}
				
			this.checkIfEmptyValue = function(index){		
				var columIndex = parseInt(index);
				for(var i =1 ;i<this.getNumofRows();i++){
					if (this.getCellValue(i+1,columIndex) == ''){
					return true;
					}
					
				}
				return false;
			}
			
			this.checkIfColumnContainsSpecialCharacters = function(index){
				//console.log("checkIfColumnContainsSpecialCharacters ", index);
				var columIndex = parseInt(index);
				var iChars = ['!','@','#','$','%','^','&','*','(',')','+','=','-','[',']','\\','\'',';',',','.','/','{','}','|','\"',':','<','>','?','~','_','"',' ']; 
				for(var i =1 ;i<this.getNumofRows();i++){
					var retrievedValue = this.getCellValue(i+1,columIndex);
					//console.log("..check ", retrievedValue);
					for (var j=0; j<iChars.length; j++) {
						if (retrievedValue.indexOf(iChars[j]) != -1) {
							return true;
						}
					}
				}				
				return false;
			}
			
			this.columnStartsWithNumber = function(index){			
					var columIndex = parseInt(index);
					for(var i =1 ;i<this.getNumofRows();i++){
						var firstCharacter = this.getCellValue(i+1,columIndex).charAt(0);
						if ( firstCharacter == '0' || firstCharacter == '1' ||firstCharacter == '2' ||firstCharacter == '3' ||firstCharacter == '4' ||firstCharacter == '5' ||firstCharacter == '6' ||firstCharacter == '7' ||firstCharacter == '8' || firstCharacter == '9'){
							return true;
					}
				}
				return false;
			}
			
			
			
			this.getColumnData = function(index){
				var data = new Array();
				for(var i=0;i<this.columns.length;i++){						
					if(i==parseInt(index)){
						for(var j =0 ;j<this.getNumofRows();j++){
							if(j!=0){
								var length = data.length;
								data[length]  = this.getCellValue(j+1,i);
							}
						}
					}
				}				
				return data;							
			}
			
			this.getColumnDataByPipe = function(index){
				var strSeparatedPipe = "";
				for(var i=0;i<this.columns.length;i++){						
					if(i==parseInt(index)){
						for(var j =0 ;j<this.getNumofRows();j++){
							if(j!=0){
								if (j!=1) strSeparatedPipe = strSeparatedPipe + "|" + this.getCellValue(j+1,i) ;
								else strSeparatedPipe+= this.getCellValue(j+1,i) ;
							}
						}
					}
				}
				return strSeparatedPipe;							
			}
			
			this.getRowData = function(index){
				var data = new Array();				
				for(var j =0 ;j<this.getNumofRows();j++){					
					if(j==parseInt(index)){						
						for(var i=0;i<this.columns.length;i++){																							
							var length = data.length;
							data[length]  = this.getCellValue(j+2,i);															
						}
					}
				}
				return data;	
			}
			
			var deleteFunction; //Delete Function String			
			this.setDeleteFunction = function(_deleteFunction){				
				this.deleteFunction = _deleteFunction;
			}
			
			this.getDeleteFunction = function(){
				return this.deleteFunction;
			}
			
			
			
			//Sets the value of the required cell of row=cell_x and column=cell_y to 'value'
			/**N.B : All 3 parameters are obligatory**/
			this.setCellValue = function(cell_x,cell_y,value,type,linktype,linklabel,linktitle,pickerid,displaypickertype,inputpickersize){													
				//Make sure the grid is editable
				if(this.edit){				
					//Get all the rows in the grid except the header
					/*
						By writing 'jQuery("#"+this.id+" > table > tbody > tr:gt(0)");' , we are getting all the rows of index greater than 0
						In this way, we are skipping the header
					*/
					var rows  = dojo.query("#"+this.id+" > table > tbody > tr");
					var numOfRows = rows.length - 1 ;

					//Number of rows
					//Decrement the number of rows if the footer is enabled
					if(this.footerEnabled){
						numOfRows--;
					}
					//See how many action columns there are before the 1st data cell
					var initialUncountedColumns = 0;
					if(this.mouseSortable){
						initialUncountedColumns++;
					}
					if(this.selectionColumnEnabled){
						initialUncountedColumns++;
					}

					//Check if the required cell is within the grid boundaries
					if(cell_x >=0 && cell_x <= numOfRows && cell_y >=0 && cell_y <(this.columns.length+initialUncountedColumns)){
						//Get the columns starting with the 1st data column
						var col= dojo.query(">",rows[cell_x]);

						//Get the type of the cell
						var cellType = dojo.query(">",col[cell_y]);						
						if(dojo.query(cellType).filter("table").length>0){							
							//Get the options
							var rowNumber = this.getInitialRowCount();
							var entries = value;
							if(entries && entries != ''){
								entries = value.split("||");
							}

							//Seperate the inner value from the display value in the list
							var displayValues = new Array(entries.length);
							var innerValues = new Array(entries.length);
							for(var entry = 0; entry < entries.length; entry++){
								var entrySplit = entries[entry].split(";");
								innerValues[entry] = entrySplit[0];
								displayValues [entry] = entrySplit[1];
							}							
							
							var contentHtml = "";
							contentHtml += "<tbody>";
							contentHtml += "<tr>";
							if(!this.displayLinkCont){
								contentHtml += "<td style='border:0px;padding:0px;vertical-align:top;display:none'>";
							} else{
								contentHtml += "<td style='border:0px;padding:0px;vertical-align:top'>";							
							}
							contentHtml += "<table>";
							contentHtml += "<tbody>";
							for(var l = 0; l < entries.length; l++){
								contentHtml += "<tr id=\""+this.tableName+'_'+cell_y+'_sub_'+l+"\"><td style='border:0px;padding:0px;vertical-align:top;width:100%'>";
								if(innerValues[l] != ''){
									if(displaypickertype == "input"){
										contentHtml += "<input value=\""+innerValues[l]+"\" style='' class='tgInputBorder' size="+inputpickersize+">";											
									} else{
										contentHtml += "<label value=\""+innerValues[l]+"\" style=''>"+displayValues[l]+"</label>";
									}
									contentHtml += "&nbsp<a class='lotusDelete'><img height=12 width=12 aria-label='delete button' alt='' src=\""+contextPath+"/tgweb20/stylesheet/oneui/images/blank.gif\" func='deletepicker'><span class='lotusAltText'>X</span></a>";							
								} else{
									contentHtml += "<img src=\""+contextPath+"/tgweb20/stylesheet/oneui/images/blank.gif\">";
								}
								contentHtml +="</td></tr>";
							}							
							contentHtml += "</tbody>";							
							contentHtml += "</table>";
							contentHtml += "</td>";
							contentHtml += "<td style='border:0px;padding:0px;vertical-align:top;text-align:right'>";
							var script ='';
							var j = cell_y - initialUncountedColumns;
							var tableId ='';
							if(dojo.query(cellType)[0])				
								tableId = dojo.query(cellType)[0].id;			
							if(pickerid && pickerid != ''){
								script = "setDynamicTablePickerTableId(\""+tableId+"\");";								
								script += "if(document.getElementById(\""+pickerid+"\")){document.getElementById(\""+pickerid+"\").click();}else{eval(\""+pickerid+"\")}";		
							}
							if(linktype == 'link'){			
								contentHtml += "&nbsp<a class='lotusAction' title=\""+linktitle+"\" onclick='"+script+"' func='deletepickerlink'>"+linklabel+"</a>";						
							}
							else if(linktype == 'image'){
								contentHtml += "&nbsp<img imgtype='picker' align='absmiddle' width=12 height=12 src=\""+contextPath+"/tgweb20/media/picker.gif\" title=\""+linktitle+"\" onclick='"+script+"' func='deletepickerlink'></img>";					
							}
							contentHtml += "</td>";			
							contentHtml += "</tr>";			
							contentHtml += "</tbody>";														

							//Close the list tag	
							dojo.html.set(dojo.query(cellType)[0], contentHtml);
							this.setLinkPickerExist(true);
						}
						//Case Select tag was encountered, we get the attribute 'listType'
						else if(dojo.query(cellType).filter("select").length>0){							
							//Get the attribute 'listType'
							var listType = dojo.attr(cellType[0],"listType");
							if(this._isBoolean(listType)){
								//If the value in the parameter is true, set the value of the <select> tag to true
								if(value=="true"){
									dojo.attr(dojo.query("option",cellType[0]),"selected",true);
								}else{
									dojo.attr(dojo.query("option",cellType[0]),"selected",false);
								}
							}
							//If the listType is a 'listFormula' or a list:
							//seperate the inner and display values and give the wanted valuethe attribute  'selected'
							else if(listType=="list" || listType=="listFormula" || listType=="multiplelist"){
								//Get the options array
								var opArray = dojo.query(">",cellType[0]);								
								//Split inner and display values
								var valueSplit = value.split(";");
								var innerValue = valueSplit[0];
								var displayValue = valueSplit[1];
								
								//Compare the 'value' parameter to the values in the options Array
								for(var i = 0 ; i < opArray.length ; i++){
									var optionInnerValue = dojo.query(opArray[i])[0].value;
									var optionDisplayValue = opArray[i].innerHTML;

									//If both inner and display values of an entry in the options
									//array match both inner and display values in the value paramter,
									//give this option the attribute 'selected'
									if(optionInnerValue == innerValue && optionDisplayValue == displayValue){
										dojo.attr(opArray[i],"selected","selected");
										//When the 1st match is found, break from the loop because there shouldn't be any two identical options in the list
										break;
									} else if(i==(opArray.length-1)) {
										var optionNew = document.createElement('option');
									    optionNew.innerHTML = displayValue;
									    optionNew.value = innerValue;	
										optionNew.setAttribute("value",innerValue);
										dojo.query(cellType)[0].appendChild(optionNew);
										break;
									}
								}
								this.setListDropDownExist(true);
							}							
						}
					 	//Case Input => Just get the value of the textbox
						else if(dojo.query(cellType).filter("input").length>0){
							if(dojo.attr(cellType[0],"type")=="checkbox"){
								if(value == true || value == "true"){
									cellType[0].checked = true;
								}else{
									cellType[0].checked = false;							  	
								}
							} else {
								if(dojo.attr(cellType[0],"texttype")=="double"){
									var doubleValue = '';
									if(this.getEnableDoubleFormat()){
										doubleValue = dojo.number.format(value,{places:2});
									} else{ 
										doubleValue = value;
									}
									cellType[0].value = doubleValue;	
									cellType[0].setAttribute('value',doubleValue);
								} else {
									cellType[0].value = value;	
									cellType[0].setAttribute('value',value);
								}
							}
						}
						//Case label => just get the html(), in this case it will return the value of this label
						else if(dojo.query(cellType).filter("label").length>0){
							cellType[0].innerHTML = value;
						}
						//Case img => return the source of the image
						else if(dojo.query(cellType).filter("img").length>0){
							dojo.query(cellType[0],"src",value);
						}
					}
				}
				//Re-initialize the events after drawing the grid(in case a change in order occurs)
				//_validateInt(this);
				_initializeIntInputValidation(this,2);
				//validateDouble(this);
				_initializeDoubleInputValidation(this,2);
				if(this.getDatePickerExist()){
					_initializeDatePicker(this,2);
				}
				if(this.getLinkPickerExist()){
					_intializeDeletePickerRow(this);
				}
			}
				
				
			//This method chooses the cell with row=cell_x, and column=cell_y, and opens a popup for this cell
			this.setCellDataFromPopup = function(cell_x,cell_y,url){
				//Add the row and column index to the URL of the chosen cell
				var newURL = url+ "?tg_grid_row="+cell_x+"tg_grid_col="+cell_y;
				var numOfCols = this.columns.length;				//Gets the number of columns
				var ID = this.id;						//ID is needed later in the jQuery call
				var footerIsEnabled = this.footerEnabled;			//footerEnabled is needed later in the jQuery call
				var isMouseSortable = this.mouseSortable;			//drag-and-drop enabled is needed later in the jQuery call
				var selectionColumnIsEnabled = this.selectionColumnEnabled;	//selection column enabled is needed later in the jQuery call
				//dojo.addOnLoad(function(){	  
				
					//Get all the rows with index > 0 (i.e : without the header)
					var rows  = dojo.query("#"+ID+" > table > tbody > tr");
					var numOfRows = rows.length - 1;		//Number of rows
					//If the footer is enabled decrement the number of rows
					if(footerIsEnabled)	{
						numOfRows--;
					}
					//Get how many action columns we have before the 1st data cell
					var initialUncountedColumns = -1;
					if(isMouseSortable){
						initialUncountedColumns++;
					}
					if(selectionColumnIsEnabled){
						initialUncountedColumns++;
					}
				
					var col;
					//Get the columns
					if(initialUncountedColumns == -1){
						col = dojo.query(" > td",rows[cell_x]);
					}else{
						col = dojo.query(" > td",rows[cell_x]);
					}
					//Make sure the cell is within grid boundaries
					if(cell_x >=0 && cell_x < numOfRows && cell_y >= 0 && cell_y < numOfCols){
						var cellType = dojo.query(" > ",col[cell_y]);
						dojo.query(cellType).onclick(function(){
					    	window.open(newURL,'','width=300,height=200,menubar=yes,status=yes,location=yes,toolbar=yes,scrollbars=yes');
						});
					}
				//});
			}
			
			
			this.getSelectionColumnEnabled = function(){	
				return this.selectionColumnEnabled;	//Returns true if the selection column is enabled
			}
			
			this.getMouseSortable = function(){	
				return this.mouseSortable;		//Returns true if the drag-and-drop column is enabled
			}
			

			/*
				Function thats get the data from the grid and generated an XML string of the data
				The XML will be returned in the form : 
				<grid><row><value></value></row></grid>
			*/			
			this.getData = function(type){
				//The XML string will be concatinated in xmlString throughout the method
				var xmlString = "<grid>";
				var rowArray = dojo.query("#"+this.id+" > table > tbody > tr");
				//Check if footer is enabled
				//If it is, we don't need to get its XML
				if(this.footerEnabled){
					var numOfRows = rowArray.length-1;
				}else{
					var numOfRows = rowArray.length;
				}
				
				for (var i = 1; i < numOfRows; i++){
					//Create a row tag at the beginning of each loop
					xmlString +="<row>";					
					//The array of columns can be thought of as the children of the row array
					var colArray = dojo.query(" > td",rowArray[i]);
					var j = 0;
					var column = 0;
					var numberOfColumns = this.columns.length;
					
					if(this.mouseSortable){
						numberOfColumns++;
						j++;
					}
					if(this.selectionColumnEnabled){
						numberOfColumns++;
						j++;
					}
					//Loop over the columns
					for(;j<numberOfColumns;j++, column++){
						//Label Checking
						//Case : List						
						var childElement = dojo.query(" > ",colArray[j]);
						var columnType = this.columns[column].type.toLowerCase();
						if(dojo.query(childElement).filter("select").length>0){							
							var listType = dojo.attr(childElement[0],"listType"); //Get the List type					
							//Check if the columnType != from listType
							//If yes, add an attribue 'type' to the xml
							if(columnType != "boolean" && listType == "boolean"){
								xmlString +="<value type='boolean'>"+xmlencode(childElement[0].value)+"</value>";
							}
							//If no, just leave the <value>value</value>
							else if(columnType == "boolean" && listType == "boolean"){
								xmlString +="<value>"+xmlencode(childElement[0].value)+"</value>";
							}
							//If column Type and listType DON"T MATCH
							else if(columnType != "multiplelist" && listType == "multiplelist"){	
								
								var childOptions = dojo.query(" > ",childElement[0]);
								var optionsValues = new Array(childOptions.length);
								var innerValues = new Array(childOptions.length);
								var displayValues = new Array(childOptions.length);		
								
								var  listValue = '';
								for (var x = 0; x < childElement[0].options.length; x++){
									if (childElement[0].options[ x ].selected){
										if(x==0){
											if(type == "label"){
												listValue += childElement[0].options[x].innerHTML;
											} else if(type == "value"){
												listValue += childElement[0].options[x].value;
											} else {
												listValue += childElement[0].options[x].value+";"+childElement[0].options[x].innerHTML;
											}
										} else {
											if(type == "label"){
												listValue += "||"+childElement[0].options[x].innerHTML;
											} else if(type == "value"){
												listValue += "||"+childElement[0].options[x].value;
											} else {
												listValue += "||"+childElement[0].options[x].value+";"+childElement[0].options[x].innerHTML;
											}
										}
									}
								}								
								listValue = xmlencode(listValue);									
								xmlString +="<value type='multiplelist'>"+listValue+"</value>";
							} 							
							//If column Type and listType DON"T MATCH
							else if(columnType != "list" && listType == "list"){	
								
								var childOptions = dojo.query(" > ",childElement[0]);
								var optionsValues = new Array(childOptions.length);
								var innerValues = new Array(childOptions.length);
								var displayValues = new Array(childOptions.length);		
								
								var selectedInnerValue = childElement[0].value;
								var selectedDisplayValue = childElement[0].options[childElement[0].selectedIndex].innerHTML;

								for(var k = 0; k < childOptions.length; k++){
									innerValues[k] = childOptions[k].value;
									displayValues[k] = childOptions[k].innerHTML;
									optionsValues[k] = innerValues[k]+";"+displayValues[k]						
								}
								xmlOptions = optionsValues.join("||");
								var  listValue = "";										
								if(type=="label"){
									listValue = selectedDisplayValue;
								} else if(type="value"){
									listValue = selectedInnerValue;
								} else {
									listValue = selectedInnerValue+";"+selectedDisplayValue;
								}
									
								//Add a 'type' attribute and the additional options
								xmlOptions = xmlencode(xmlOptions);
								listValue = xmlencode(listValue);									
								xmlString +="<value type='list' options='"+xmlencode(xmlOptions)+"'>"+listValue+"</value>";

							} 
							//If column Type and listType DON"T MATCH
							else if(columnType == "multiplelist" && listType == "multiplelist"){	
								
								var childOptions = dojo.query(" > ",childElement[0]);
								var optionsValues = new Array(childOptions.length);
								var innerValues = new Array(childOptions.length);
								var displayValues = new Array(childOptions.length);		
								
								var  listValue = '';
								for (var x = 0; x < childElement[0].options.length; x++){
									if (childElement[0].options[ x ].selected){
										if(x==0){
											if(type=="label"){
												listValue += childElement[0].options[x].innerHTML;
											} else if(type=="value"){
												listValue += childElement[0].options[x].value;
											} else {
												listValue += childElement[0].options[x].value+";"+childElement[0].options[x].innerHTML;
											}											
										} else {
											if(type=="label"){
												listValue += "||"+childElement[0].options[x].innerHTML;
											} else if(type=="value"){
												listValue += "||"+childElement[0].options[x].value;												
											} else {
												listValue += "||"+childElement[0].options[x].value+";"+childElement[0].options[x].innerHTML;												
											}
										}
									}
								}								
								listValue = xmlencode(listValue);									
								xmlString +="<value type='multiplelist'>"+listValue+"</value>";
							} 								
							//If column Type and listType  MATCH
							else if(columnType == "list" && listType == "list"){								
								var childOptions = dojo.query(" > ",childElement[0]);								
								var optionsValues = new Array(childOptions.length);
								var innerValues = new Array(childOptions.length);
								var displayValues = new Array(childOptions.length);
								var selectedInnerValue = childElement[0].value;
								var selectedDisplayValue = childElement[0].options[childElement[0].selectedIndex].innerHTML;
								
								for(var k = 0; k < childOptions.length; k++){
									innerValues[k] = childOptions[k].value;
									displayValues[k] = childOptions[k].innerHTML;
									//Concatinate the inner and display values with a semi-colon ';'
									optionsValues[k] = innerValues[k] + ";" + displayValues[k];
								}
								xmlOptions = optionsValues.join("||");			
								
								//Check if the options MATCH
								if(xmlOptions != this.columns[column].value){
									//Add the 'options' attribute
									//xmlString +="<value type='list' options='"+xmlOptions+"'>"+selectedInnerValue+";"+selectedDisplayValue+"</value>";
									var  listValue = selectedInnerValue+";"+selectedDisplayValue;										
									if(type=="label"){
										listValue = selectedDisplayValue;										
									} else if(type=="value"){
										listValue = selectedInnerValue;										
									} else {
										listValue = selectedInnerValue+";"+selectedDisplayValue;										
									}
									xmlOptions = xmlencode(xmlOptions);
									listValue = xmlencode(listValue);									
									xmlString +="<value type='list' options='"+xmlencode(xmlOptions)+"'>"+listValue+"</value>";

								}else{
									//Don't add the options attribute
									if(type=="label"){
										xmlString +="<value>"+xmlencode(selectedDisplayValue)+"</value>";
									} else if(type=="value"){
										xmlString +="<value>"+xmlencode(selectedInnerValue)+"</value>";
									} else {
										xmlString +="<value>"+xmlencode(selectedInnerValue+";"+selectedDisplayValue)+"</value>";
									}									
								}										
							}
							//If lisType and ColumnType DON'T MATCH
							else if(columnType != "listformula" && listType == "listFormula"){
								var innerValue = childElement[0].value;
								var displayValue = dojo.query(" > [selected='selected']",childElement[0])[0].innerHTML;
								//Concatinate inner and display values with a semi-colon
								if(type=="label"){
									xmlString +="<value type='listFormula' function='"+dojo.attr(childElement[0],"function")+"'>"+xmlencode(displayValue)+"</value>";
								} else if(type=="value"){
									xmlString +="<value type='listFormula' function='"+dojo.attr(childElement[0],"function")+"'>"+xmlencode(innerValue)+"</value>";
								} else {
									xmlString +="<value type='listFormula' function='"+dojo.attr(childElement[0],"function")+"'>"+xmlencode(innerValue+";"+displayValue)+"</value>";
								}								
							}				
							//If lisType and ColumnType MATCH
							else if(columnType == "listformula" && listType == "listFormula"){
								var displayValue = dojo.query(" > [selected='selected']",childElement[0])[0].innerHTML;
								//if it has a function attribue and its value DOES NOT MATCH the column function attribute
								if(dojo.attr(childElement[0],"function") && this.columns[column].value != dojo.attr(childElement[0],"function") ){
									var innerValue = childElement[0].value;
									//provide the function body in the function attribute
									if(type=="label"){
										xmlString +="<value type='listFormula' function='"+ dojo.attr(childElement[0],"function")+"'>"+xmlencode(displayValue)+"</value>";
									} else if(type=="value"){
										xmlString +="<value type='listFormula' function='"+ dojo.attr(childElement[0],"function")+"'>"+xmlencode(innerValue)+"</value>";
									} else {
										xmlString +="<value type='listFormula' function='"+ dojo.attr(childElement[0],"function")+"'>"+xmlencode(innerValue+";"+displayValue)+"</value>";
									}
								}
								//If column function attribute and function attribute match, don't provide fuction body
								else{
									var innerValue = childElement.value;
									if(type=="label"){
										xmlString +="<value>"+xmlencode(+displayValue)+"</value>";
									} else if(type=="value"){
										xmlString +="<value>"+xmlencode(innerValue)+"</value>";
									} else {
										xmlString +="<value>"+xmlencode(innerValue+";"+displayValue)+"</value>";
									}									
								}					
							} else {
								var innerValue = childElement.value;
								var displayValue = dojo.query(":selected",childElement)[0].innerHTML;
								//Concatinate inner and display values with  semi-colon
								if(type=="label"){
									xmlString +="<value>"+xmlencode(displayValue)+"</value>";
								} else if(type=="value"){
									xmlString +="<value>"+xmlencode(innerValue)+"</value>";
								} else {
									xmlString +="<value>"+xmlencode(innerValue+";"+displayValue)+"</value>";
								}								
							}				
						}
						//Case:label
						else if(dojo.query(childElement).filter("label").length>0){
							var labelObj = dojo.query(" > ",colArray[j])[0];
							var data = labelObj.innerHTML;
							var key  = labelObj.getAttribute("key");
							if(key && key != "")
								data = key;
							if(data =='&nbsp;')	data = '';
							if(convertDoubleToPrimitive(data))
								data = convertDoubleToPrimitive(data);
							//If column type DOES NOT MATCH the cell type
							if(columnType != "label"){
								//Provide the type attribute in the xml								
								xmlString +="<value type='label'>"+xmlencode(data)+"</value>";							
							}
							//If column type MATCHES the cell type
							else {
								//Don't provide the type attribute in the xml
								xmlString +="<value>"+xmlencode(data)+"</value>";
							}				
						}
						//case Link
						else if(dojo.query(childElement).filter("table").length>0){
							var childOptions = dojo.query(" > tbody > tr > td > table > tbody > tr",childElement[0]);							
							var data = '';
							for(x=0;x<childOptions.length;x++){
								if(childOptions[x].firstChild.childNodes[0]){
									if(x == 0){
										if(childOptions[x].firstChild.childNodes[0].tagName.toLowerCase() == "label"){
											if(childOptions[x].firstChild.childNodes[0].innerHTML!= ''){
												label = childOptions[x].firstChild.childNodes[0].innerHTML;
												value = childOptions[x].firstChild.childNodes[0].value;
												if(value == undefined || value == 'undefined')
													value = childOptions[x].firstChild.childNodes[0].getAttribute('value');	
												if(type=="label"){
													data +=  label;	
												} else if(type=="value"){
													data += value;	
												} else {
													data += value + ";" + label;	
												}												
											}
										} else if(childOptions[x].firstChild.childNodes[0].tagName.toLowerCase() == "input"){
											value = childOptions[x].firstChild.childNodes[0].value;
											if(value == undefined || value == 'undefined')
												value = childOptions[x].firstChild.childNodes[0].getAttribute('value');
											data += value;
										}
									} else {
										if(childOptions[x].firstChild.childNodes[0].tagName.toLowerCase() == "label"){
											if(childOptions[x].firstChild.childNodes[0].innerHTML!= ''){
												label = childOptions[x].firstChild.childNodes[0].innerHTML;
												value = childOptions[x].firstChild.childNodes[0].value;
												if(value == undefined || value == 'undefined')
													value = childOptions[x].firstChild.childNodes[0].getAttribute('value');	
												if(type=="label"){
													data += "||" + label;																				
												} else if(type=="value"){
													data += "||" + value ;																				
												} else {
													data += "||" + value + ";" + label;																				
												}												
											}
										} else if(childOptions[x].firstChild.childNodes[0].tagName.toLowerCase() == "input"){
											value = childOptions[x].firstChild.childNodes[0].value;
											if(value == undefined || value == 'undefined')
												value = childOptions[x].firstChild.childNodes[0].getAttribute('value');
											data += "||" + value;										
										}
									}
								}
								
							}
							xmlString +="<value type='link'>"+xmlencode(data)+"</value>";
						}
						//Case:input
						else if(dojo.query(childElement).filter("input").length>0){							
							// Case : Input Text				
							if(dojo.attr(childElement[0],"textType")=="text"){
								if(columnType != "text"){
									xmlString +="<value type='text'>"+ xmlencode(childElement[0].value)+"</value>";
								}else{
									xmlString +="<value>"+ xmlencode(childElement[0].value)+"</value>";
								}
							}
							//Case : Input - CheckBox
							if(dojo.attr(childElement[0],"textType")=="checkbox"){
								xmlString +="<value type='checkbox'>"+ xmlencode(childElement[0].checked)+"</value>";							
							}
							// Case : Input - TypeAhead
							if(dojo.attr(childElement[0],"textType")=="typeahead"){
								if(columnType != "typeahead"){
									xmlString +="<value type='text'>"+ xmlencode(childElement[0].value)+"</value>";
								}else{
									xmlString +="<value>"+ xmlencode(childElement[0].value)+"</value>";
								}
							}
							//Case Input-Date
							else if(dojo.attr(childElement[0],"textType")=="date"){
								if(columnType != "date"){
									xmlString +="<value type='date'>"+ xmlencode(childElement[0].value)+"</value>";		
								}else{
									xmlString +="<value>"+ xmlencode(childElement[0].value)+"</value>";
								}
							}
							//Case Input-Integer
							else if(dojo.attr(childElement[0],"textType")=="integer" || dojo.attr(childElement[0],"textType")=="int"){
								if(columnType != "integer" && columnType != "int"){
									xmlString +="<value type='integer'>"+ xmlencode(childElement[0].value)+"</value>";
								}else{
									xmlString +="<value>"+ xmlencode(childElement[0].value)+"</value>";
								}
							}
							
							//Case Input-Double
							else if(dojo.attr(childElement[0],"textType")=="double"){
								var value = convertDoubleToPrimitive(trim(xmlencode(childElement[0].value)));
								if(columnType != "double"){
									xmlString +="<value type='double'>"+value+"</value>";
								}else{
									xmlString +="<value>"+value+"</value>";
								}
							}
						}
						
						//case: image => return the image source
						else if(dojo.query(childElement).filter("img").length>0){
							if(columnType != "icon"){
								xmlString +="<value type='icon'>"+ xmlencode(dojo.attr(childElement[0],"src"))+"</value>";						
							}else{
								xmlString +="<value>"+ xmlencode(dojo.attr(childElement[0],"src"))+"</value>";
							}
						}
						
					}
					//Close the row tag and loop again
					xmlString +="</row>";	
				}
				//Close the xml String
				xmlString += "</grid>";
				/*
					This part of the function escapes the quotation(") character in the xml string.
				*/
				var index = xmlString.indexOf("\""); 		//getting the indexes of the first quotation(") in the xml
				var allQuotationsIndeces = new Array(0);	//array to hold the indeces
				
				//getting the indexes of all the quotation(")
				while(index != -1)	{			
					allQuotationsIndeces.push(index);
					index = xmlString.indexOf("\"", index+1);
				}
				
				//adding a frontslash before every quotation caracter starting from the last one so that the indeces remain the same
				for(var i = allQuotationsIndeces.length-1; i >= 0; i--)	{
					xmlString = xmlString.substring(0, allQuotationsIndeces[i])+"\\"+xmlString.substring(allQuotationsIndeces[i]);
				}
							
				return xmlString;
				
			};
					
	
			//Draws the header of the grid, which includes all the columns's labels/titles
			this.drawHeader = function(){
				var ActionColumnIndex = 0;
				//Start building the html
				var headerId = this.getTableName()+"_header";
				headerHtml = "<tr id=\""+headerId+"\">";
				//drag-and-drop
				if(this.mouseSortable){
					//build the drag-and-drop column
					headerHtml += "<th id='grid_headerID' style='word-wrap:break-word;vertical-align:middle>"+this.actionColumns[ActionColumnIndex].label + "</th>";
					ActionColumnIndex++;
				}
				//Selection Column
				if(this.selectionColumnEnabled){
					//Build the selection Column
					headerHtml += "<th style='word-wrap:break-word; padding: 3px;vertical-align:middle'>"+this.actionColumns[ActionColumnIndex].label + "<input class='tgInputBorder' type='checkbox'/></th>";			
					ActionColumnIndex++;
				}
				//Build the header HTML
				for(var i = 0; i < this.columns.length; i++){					
					if(this.columns[i].displayType=="none"){
						if(dojo.isIE < 8){
							if(this._isLink(this.columns[i].type)){
								headerHtml += "<th align='left' style='word-wrap:break-word;display:none;vertical-align:middle;text-align:center'>"+this.columns[i].label + "</th>";
							} else if (this.columns[i].type.toLowerCase() == 'checkbox' && (this.columns[i].checkboxheaderenable == 'true' || this.columns[i].checkboxheaderenable == true)){
								headerHtml += "<th align='left' style='word-wrap:break-word;display:none;vertical-align:middle;'><input type='checkbox' style='vertical-align:middle'>"+this.columns[i].label + "</th>";
							} else {
								headerHtml += "<th align='left' style='word-wrap:break-word;display:none;vertical-align:middle'>"+this.columns[i].label + "</th>";
							}
						} else {
							if(this._isLink(this.columns[i].type)){
								headerHtml += "<th align='left' style='display:none;vertical-align:middle;text-align:center'>"+this.columns[i].label + "</th>";
							} else if (this.columns[i].type.toLowerCase() == 'checkbox' && (this.columns[i].checkboxheaderenable == 'true' || this.columns[i].checkboxheaderenable == true)){
								headerHtml += "<th align='left' style='word-wrap:break-word;display:none;vertical-align:middle;'><input type='checkbox' style='vertical-align:middle'>"+this.columns[i].label + "</th>";
							} else {
								headerHtml += "<th align='left' style='display:none;vertical-align:middle'>"+this.columns[i].label + "</th>";
							}
						}
					} else {
						if(this._isLink(this.columns[i].type)){
							headerHtml += "<th align='left' style='word-wrap:break-word;vertical-align:middle;text-align:center'>"+this.columns[i].label + "</th>";
						} else if (this.columns[i].type.toLowerCase() == 'checkbox' && (this.columns[i].checkboxheaderenable == 'true' || this.columns[i].checkboxheaderenable == true)){
							headerHtml += "<th align='left' style='word-wrap:break-word;vertical-align:middle;'><input type='checkbox' style='vertical-align:middle'>"+this.columns[i].label+"</th>";
						} else {
							headerHtml += "<th align='left' style='word-wrap:break-word;vertical-align:middle'>"+this.columns[i].label + "</th>";
						}
					}
				}
				
				var startIndex = 0;
			
				if(this.selectionColumnEnabled){
					startIndex +=1;
				}
				if(this.mouseSortable){
					startIndex +=1;
				}				
				
				for(var i = startIndex; i < this.actionColumns.length;i++){
					headerHtml += "<th align='left' style='word-wrap:break-word;vertical-align:middle'>"+"</th>";					
				}
				headerHtml += "</tr>";	//Finish building the header HTML
				return headerHtml;	
			}
			
			
			//Function the generates the HTML code of the grid based on XML
			//It also assigns the grid an ID
			this.drawCore = function(id){				
				//String that will hold the HTML of the grid
				var coreHtml = "";
				
				//Loop over the length of the array containing the data from the XML
				for(var i = 0; i < this.gridData.length; i++){
					coreHtml += "<tr>";		//Create a row for each row in the array
					var ActionColumnIndex = 0;
					if(this.mouseSortable)	{	//Check whether the drag-and-drop is enabled and generate HTML code for it
						coreHtml += "<td class='"+this._getRowAlternationClass(i)+"' style='background-image:url("+this.actionColumns[ActionColumnIndex].value+"); background-repeat:no-repeat; background-position:center 7px; padding: 3px; cursor:move; vertical-align: top; overflow:hidden;' func='dragAndDrop' width=5px>";						
						coreHtml += "&nbsp</td>";
						ActionColumnIndex++;
					}
					
					//Check whether the selection column is enabled and generate HTML code for it
					if(this.selectionColumnEnabled){
						var tdWidth = this.actionColumns[ActionColumnIndex].size;
						coreHtml += "<td class='"+this._getRowAlternationClass(i)+"' ";
						if(tdWidth && tdWidth!='')
							coreHtml += "func='selectionColumn' style='overflow:hidden; padding: 3px; vertical-align: top;' width="+tdWidth+">";						
						else
							coreHtml += "func='selectionColumn' style='overflow:hidden; padding: 3px; vertical-align: top;'>";						
						coreHtml += "<input type='checkbox' func='selectionColumn' class='tgInputBorder' style='vertical-align:top'></input>"
						coreHtml += "</td>";
						ActionColumnIndex++;
					}
					//Go through each row and generate HTML <td> tags
					for(var j = 0; j < this.gridData[i].length; j++){									
						var type;
						var data;
						this.gridData[i][j] += "";	//Seperate the data held in the array cells
						
						//If the type is specified within the cell,
						//split type and data
						if(this.gridData[i][j].indexOf("///") != -1){
							type = this.gridData[i][j].split("///")[0];	//type Contains the type of cell
							data =  this.gridData[i][j].split("///")[1];	//data contains the value of each cell	
						}
						
						//If the type of the cell is not defined,
						//get the type from the cell's column definition
						//and the data from the data Array
						else{
							type = this.columns[j].type;
							data = this.gridData[i][j];
						}
						
						// draw cell (td)	
						coreHtml += this._createHtmlCell(this.columns[j], this.gridData[i][j], type, data, i);
					}
				
					//Generate HTML code for the manipualtion columns if they are present
					coreHtml += this._createHtmlActionColumns(i, ActionColumnIndex);

					coreHtml += "</tr>";	//Close <tr> and loop again
					ActionColumnIndex = 0;
				}
				return coreHtml;		//return the HTML code of the grid's core
			};
			
			
			
			// create the HTML to represent the cell in function of the type and return it
			this._createHtmlCell = function(column, gridDataCell, type, data, rowIndex) {
				var coreHtml = "";				
				var tdWidth = column.size;
				if(column.displayType=="none"){
					if(dojo.isIE < 8){
						if(this._isLink(type)){
							//coreHtml += "<td class='"+this._getRowAlternationClass(rowIndex)+"' style='overflow:hidden; padding: 0px 3px 3px 3px; vertical-align: top;display:none;text-align:left' width="+column.size+"px>";
							if(tdWidth && tdWidth!='')
								coreHtml += "<td class='"+this._getRowAlternationClass(rowIndex)+"' style='overflow:hidden; padding: 0px 3px 3px 3px; vertical-align: top;display:none;text-align:left' width="+tdWidth+"px>";
							else
								coreHtml += "<td class='"+this._getRowAlternationClass(rowIndex)+"' style='overflow:hidden; padding: 0px 3px 3px 3px; vertical-align: top;display:none;text-align:left'>";
						} else if(this._isList(type) || this._isMultipleList(type)){
							coreHtml += "<td class='"+this._getRowAlternationClass(rowIndex)+"' style='overflow:hidden; padding: 3px; vertical-align: top;display:none'>";
						} else {
							if(tdWidth && tdWidth != '')
								coreHtml += "<td class='"+this._getRowAlternationClass(rowIndex)+"' style='overflow:hidden; padding: 3px; vertical-align: top;display:none' width="+tdWidth+"px>";
							else
								coreHtml += "<td class='"+this._getRowAlternationClass(rowIndex)+"' style='overflow:hidden; padding: 3px; vertical-align: top;display:none'>";
						}
					} else {
						if(this._isLink(type)){
							//coreHtml += "<td class='"+this._getRowAlternationClass(rowIndex)+"' style='overflow:hidden; padding: 0px 3px 3px 3px; vertical-align: top;display:none;text-align:left' width="+column.size+"px>";
							if(tdWidth && tdWidth != '')
								coreHtml += "<td class='"+this._getRowAlternationClass(rowIndex)+"' style='overflow:hidden; padding: 0px 3px 3px 3px; vertical-align: top;display:none;text-align:left' width="+tdWidth+"px>";
							else
								coreHtml += "<td class='"+this._getRowAlternationClass(rowIndex)+"' style='overflow:hidden; padding: 0px 3px 3px 3px; vertical-align: top;display:none;text-align:left'>";
						} else if(this._isList(type) || this._isMultipleList(type)){
							coreHtml += "<td class='"+this._getRowAlternationClass(rowIndex)+"' style='overflow:hidden; padding: 3px; vertical-align: top;display:none'>";
						} else {
							if(tdWidth && tdWidth!='')
								coreHtml += "<td class='"+this._getRowAlternationClass(rowIndex)+"' style='overflow:hidden; padding: 3px; vertical-align: top;display:none' width="+tdWidth+"px>";
							else
								coreHtml += "<td class='"+this._getRowAlternationClass(rowIndex)+"' style='overflow:hidden; padding: 3px; vertical-align: top;display:none'>";
						}
					}
				}
				else {
					if(this._isLink(type)){								
						if(tdWidth && tdWidth!='')
							coreHtml += "<td class='"+this._getRowAlternationClass(rowIndex)+"' style='overflow:hidden;padding: 0px 3px 3px 3px; vertical-align: top;text-align:left' width="+tdWidth+"px>";								
						else
							coreHtml += "<td class='"+this._getRowAlternationClass(rowIndex)+"' style='overflow:hidden;padding: 0px 3px 3px 3px; vertical-align: top;text-align:left'>";								
					} else if(this._isList(type) || this._isMultipleList(type)){
						coreHtml += "<td class='"+this._getRowAlternationClass(rowIndex)+"' style='overflow:hidden; padding: 3px; vertical-align: top;'>";
					} else {
						if(tdWidth && tdWidth!='')
							coreHtml += "<td class='"+this._getRowAlternationClass(rowIndex)+"' style='overflow:hidden; padding: 3px; vertical-align: top;' width="+tdWidth+"px>";
						else
							coreHtml += "<td class='"+this._getRowAlternationClass(rowIndex)+"' style='overflow:hidden; padding: 3px; vertical-align: top;'>";
					}
				}
						
					
				//Check for the type of each cell to know what HTML tags to generate
				if(this._isBoolean(type)){
					if(data=="true"){
						coreHtml += "<select class='tgInputBorder' listType='boolean' style='vertical-align:top'><option selected='selected'>"+this.gridNls.boolYes+"</option><option>"+this.gridNls.boolNo+"</option></select>"
					}else{
						coreHtml += "<select class='tgInputBorder' listType='boolean' style='vertical-align:top'><option>"+this.gridNls.boolYes+"</option><option selected='selected'>"+this.gridNls.boolNo+"</option></select>"
					}
				}
						
				//Double: generate an input whose type is text
				else if(this._isDouble(type)){					
					var doubleValue = '';
					if(this.getEnableDoubleFormat()){
						doubleValue = dojo.number.format(data,{places:2});
					} else{ 
						doubleValue = data;
					}
					var className = column.className;
					if (className)
						className += " tginputBorder";
					else className = "tginputBorder";
							
					coreHtml += "<input style='vertical-align:top' class='"+className+"' textType='double' size ="+column.iconWidth+" type='text' value=\""+doubleValue+"\" onChange='validateDoubleInput(this,\""+this.gridNls.invalidDouble+"\")'></input>";
					this.setDoubleCellExist(true);
				}
						
				//Integer: generate an input whose type is text
				else if(this._isInteger(type)){
					coreHtml += "<input style='vertical-align:top' class='tgInputBorder' textType='integer' size ="+column.iconWidth+" type='text' value=\""+data +"\" ></input>";
					this.setIntCellExist(true);					
				}
						
				//Icon : generate an <img> tag
				else if(this._isIcon(type)){
					coreHtml += "<img width ="+column.iconWidth+"px height="+column.iconHeight+"px src="+ data +"></img>";
				}
				//CheckBox: generate an input whose type is CheckBox
				else if(this._isCheckbox(type)){
					if(data=="true"){							
						coreHtml += "<input textType='checkbox' type='checkbox' func='selectionColumn' class='tgInputBorder' style='vertical-align:top' checked='true'></input>";
					} else {
						coreHtml += "<input textType='checkbox' type='checkbox' func='selectionColumn' class='tgInputBorder' style='vertical-align:top'></input>";
					}
				}
				//Link
				else if(this._isLink(type)){	
					//Get the options					
					var xmlOptions = gridDataCell.split("///")[2];					
					//Get Default Value
					var xmlOptionsdefault = gridDataCell.split("///")[3];
					//Get LinkOptions
					var linkOptions = gridDataCell.split("///")[4];
					var entries = "";
					//Entries will be an array containing all the options
					if(data && data != ''){						
						entries = data.split("||");
					} else {						
						if(xmlOptions && xmlOptions!="null" && xmlOptions != column.value){							
							entries = xmlOptions.split("||");
						}else{							
							if( column!=null && xmlOptions!="null" && column.value!=""){								
								entries = column.value.split("||");
							}
							
						}
					}
					//Seperate the inner value from the display value in the list					
					var displayValues = new Array(entries.length);
					var innerValues = new Array(entries.length);
					for(var entry = 0; entry < entries.length; entry++){
						var entrySplit = entries[entry].split(";");
						innerValues[entry] = entrySplit[0];
						displayValues [entry] = entrySplit[1];
					}
							
					if(data == "")	{ //If no saved value is present, take the 1st option to display							
						data = entries[0];
					}
					//Empty the optionsHtml string to re-use for other lists						
					var contentHtml = "";
					contentHtml += "<table id=\""+this.tableName+'_'+column.id+'_'+rowIndex+"\" width='100%'>";
					contentHtml += "<tbody>";
					contentHtml += "<tr>";
					if(!this.displayLinkCont){
						contentHtml += "<td style='border:0px;padding:0px;vertical-align:top;display:none'>";
					} else{
						contentHtml += "<td style='border:0px;padding:0px;vertical-align:top'>";
					}
					
					contentHtml += "<table>";
					contentHtml += "<tbody>";
					for(var l = 0; l < entries.length; l++){
						contentHtml += "<tr id=\""+this.tableName+'_'+column.id+'_sub_'+l+"\"><td style='border:0px;padding:0px;vertical-align:top;width:100%'>";
						if(innerValues[l] != ''){
							if(column.displaypickertype=="input"){
								contentHtml += "<input value=\""+innerValues[l]+"\" style='' class='tgInputBorder' size=\""+column.iconWidth+"\">";											
							}else if(column.displaypickertype=="label"){
								contentHtml += "<label value=\""+innerValues[l]+"\" style=''>"+displayValues[l].replace(/"/g, "&quot;")+"</label>";
							} else {
								contentHtml += "<label value=\""+innerValues[l]+"\" style=''>"+displayValues[l].replace(/"/g, "&quot;")+"</label>";
							}
							contentHtml += "&nbsp<a class='lotusDelete'><img height=12 width=12 aria-label='delete button' alt='' src=\""+contextPath+"/tgweb20/stylesheet/oneui/images/blank.gif\" func='deletepicker'><span class='lotusAltText'>X</span></a>";							
							} else{
								contentHtml += "<img src=\""+contextPath+"/tgweb20/stylesheet/oneui/images/blank.gif\">";
							}
							contentHtml +="</td></tr>";
						}							
						contentHtml += "</tbody>";							
						contentHtml += "</table>";
						contentHtml += "</td>";
						contentHtml += "<td style='border:0px;padding:0px;vertical-align:top;text-align:right;'>";
						var script ='';
						if(linkOptions != null && linkOptions != '' && linkOptions.length != 4){
							var linkOptionsArray = linkOptions.split(";");
							script = "setDynamicTablePickerTableId(\""+this.tableName+'_'+column.id+'_'+rowIndex+"\");";
							if(linkOptionsArray[3] && linkOptionsArray[3]!=''){
								script = "setDynamicTablePickerTableId(\""+this.tableName+'_'+column.id+'_'+rowIndex+"\");";
								script += "if(document.getElementById(\""+linkOptionsArray[3]+"\")){document.getElementById(\""+linkOptionsArray[3]+"\").click();}else{eval(\""+linkOptionsArray[3]+"\")}";									
							}				
							if(linkOptionsArray[0] == 'link'){
								contentHtml += "&nbsp<a func='deletepickerlink' class='lotusAction' title=\""+linkOptionsArray[2]+"\" onclick='"+script+"'>"+linkOptionsArray[1].replace(/"/g, "&quot;")+"</a>";							
							}
							else if(linkOptionsArray[0] == 'image'){
									contentHtml += "&nbsp<img func='deletepickerlink' imgtype='picker' align='absmiddle' width=12 height=12 src=\""+contextPath+"/tgweb20/media/picker.gif\" title=\""+linkOptionsArray[2].replace(/"/g, "&quot;")+"\" onclick='"+script+"'></img>";					
							} 
								
						} else {							
							script = "setDynamicTablePickerTableId(\""+this.tableName+'_'+column.id+'_'+rowIndex+"\");";
							if(column.pickerid && column.pickerid!=''){
								script = "setDynamicTablePickerTableId(\""+this.tableName+'_'+column.id+'_'+rowIndex+"\");";
								script += "if(document.getElementById(\""+column.pickerid+"\")){document.getElementById(\""+column.pickerid+"\").click();}else{eval(\""+column.pickerid+"\")}";																		
							}
				
							if(column.subtype == 'link'){								
								contentHtml += "&nbsp<a func='deletepickerlink' class='lotusAction' title=\""+column.title+"\" onclick='"+script+"'>"+column.label.replace(/"/g, "&quot;")+"</a>";
							}
							else if(column.subtype == 'image'){
								contentHtml += "&nbsp<img func='deletepickerlink' imgtype='picker' align='absmiddle' width=12 height=12 src=\""+contextPath+"/tgweb20/media/picker.gif\" title=\""+column.title.replace(/"/g, "&quot;")+"\" onclick=''></img>";					
							} 
						}
						contentHtml += "</td>";			
						contentHtml += "</tr>";			
						contentHtml += "</tbody>";							
						contentHtml += "</table>";	
						//Close the list tag						
						coreHtml += contentHtml;
						this.setLinkPickerExist(true);
					}
					//List Multiple
					else if(this._isMultipleList(type)){
						//Get the options
						var xmlOptions = gridDataCell.split("///")[2];
						//Get Default Value
						var xmlOptionsdefault = gridDataCell.split("///")[3];
						var entries = "";
						//Entries will be an array containing all the options
						if(xmlOptions && xmlOptions != "null" && xmlOptions != column.value){
							entries = xmlOptions.split("||");
						}else{
							entries = column.value.split("||");
						}
						
						//Seperate the inner value from the display value in the list
						var displayValues = new Array(entries.length);
						var innerValues = new Array(entries.length);
							
						for(var entry = 0; entry < entries.length; entry++){
							var entrySplit = entries[entry].split(";");
							innerValues[entry] = entrySplit[0];
							displayValues [entry] = entrySplit[1];
						}
							
						if(data == ""){	//If no saved value is present, take the 1st option to display							
							data = entries[0];
						}
							
						//Splitting
						var innerData = data.split(";")[0];
						var displayData = data.split(";")[1];
						
						//Empty the optionsHtml string to re-use for other lists
						var optionsHtml = "";
							
						var selectedDataList = data.split("||");
						for(var k=0;k < entries.length; k++){
							var valueAdded = false;
							for(var x=0;x<selectedDataList.length;x++){
								var innerData = selectedDataList[x].split(";")[0];
								if(innerValues[k] == innerData){
									optionsHtml += "<option selected='selected' value=\""+innerValues[k]+"\">"+displayValues[k].replace(/"/g, "&quot;")+"</option>";
									valueAdded = true;
									continue;
								}
							}
							if(!valueAdded)
								optionsHtml += "<option value=\""+innerValues[k]+"\">"+displayValues[k].replace(/"/g, "&quot;")+"</option>";
						}
												//Close the list tag
						var listSize = '';
						var columnSize = column.size;
						if(columnSize && parseInt(columnSize))
							listSize = columnSize - ((columnSize*5)/100);
						coreHtml += "<select class='tgInputBorder' listType='multiplelist' style='vertical-align:top;' multiple>"+optionsHtml+"</select>";
					}						
					//List
					else if(this._isList(type)){
						//Get the options						
						var xmlOptions = gridDataCell.split("///")[2];
						//Get Default Value
						var xmlOptionsdefault = gridDataCell.split("///")[3];
						var entries = "";
						//Entries will be an array containing all the options
						if( xmlOptions && xmlOptions != "null" && xmlOptions != column.value){
							entries = xmlOptions.split("||");
						}else{
							entries = column.value.split("||");
						}
						
						//Seperate the inner value from the display value in the list
						var displayValues = new Array(entries.length);
						var innerValues = new Array(entries.length);
						
						for(var entry = 0; entry < entries.length; entry++){
							var entrySplit = entries[entry].split(";");
							innerValues[entry] = entrySplit[0];
							displayValues [entry] = entrySplit[1];							
						}
					
						if(data == ""){	//If no saved value is present, take the 1st option to display							
							data = entries[0];
						}		
												
						//Splitting
						var innerData = data.split(";")[0];
						var displayData = data.split(";")[1];
							
						//Empty the optionsHtml string to re-use for other lists
						var optionsHtml = "";
						
						//Generate HTML code for the list with the given options
						for(var k = 0; k < entries.length; k++){	
							//If one entry in the list is matched, set is as the selected value							
							if(innerValues[k] == innerData){
								optionsHtml += "<option selected='selected' value=\""+innerValues[k]+"\">"+displayValues[k].replace(/"/g, "&quot;")+"</option>";
							}else if(innerValues[k]==xmlOptionsdefault){
								optionsHtml += "<option selected='selected' value=\""+innerValues[k]+"\">"+displayValues[k].replace(/"/g, "&quot;")+"</option>";
							}else{
								optionsHtml += "<option value=\""+innerValues[k]+"\">"+displayValues[k].replace(/"/g, "&quot;")+"</option>";
							}							
						}
							
						//Close the list tag
						var listSize = '';
						var columnSize = column.size;
						if(columnSize && parseInt(columnSize))
							listSize = columnSize - ((columnSize*5)/100);
						coreHtml += "<select class='tgInputBorder' listType='list' style='vertical-align:top;'>"+optionsHtml+"</select>";
						this.setListDropDownExist(true);
					}
					//Type 2 of the list : getting the options from a function/formula
					else if(this._isListFormula(type)){	
						var functionString = gridDataCell.split("///")[2];
						//Take the body of the function from the string representing the function, and set it as the body of a new function
						data = functionString.substring(functionString.indexOf("{")+1, functionString.length-1);
						//Calling the new function that gets the list options
						//(Use the function object in javascript)
						var func = new Function(data);
						//Put the return values of the function in entries
						var entries = func();
						//Convert the return value of the function to a string, in order to split the options
						entries+="";
						entries = entries.split("||");
						//Split the options
						var value = gridDataCell.split("///")[1];
						
						//Split the inner values from the display values
						var innerValues = new Array(entries.length);
						var displayValues = new Array(entries.length);
						
						for(var entry = 0; entry < entries.length; entry++){
							var entrySplit = entries[entry].split(";");
							innerValues[entry] = entrySplit[0];
							displayValues[entry] = entrySplit[1];
						}
						
						var savedInnerValue = value.split(";")[0];
						var savedDisplayValue = value.split(";")[1];
						
						//Generating HTML code based on function results
						var optionsHtml = "";
						for(var k = 0; k < entries.length; k++){
							if(innerValues[k] == savedInnerValue && displayValues[k] == savedDisplayValue){
								optionsHtml += "<option selected='selected' value=\""+innerValues[k]+"\">"+displayValues[k].replace(/"/g, "&quot;")+"</option>";
							}else{
								optionsHtml += "<option value=\""+innerValues[k]+"\">"+displayValues[k].replace(/"/g, "&quot;")+"</option>";
							}
						}
						//Update the function attribute in the html
						//The function attribute will hold the called function's body
						if(functionString != column.value){
							coreHtml += "<select class='tgInputBorder' listType='listFormula' function=\""+functionString+"\" style='vertical-align:top'>"+optionsHtml+"</select>";
						}else{
							coreHtml += "<select class='tgInputBorder' listType='listFormula' style='vertical-align:top'>"+optionsHtml+"</select>";
						}
					}
					
					//Case Date : Generate an input whose type is text, and an icon next to it
					else if(this._isDate(type)){
						coreHtml += "<input class='tgInputBorder' type='text' textType='date' size=10 value =\""+data +"\" style='vertical-align:top'>&nbsp<img imgtype='date' align='absmiddle' width=16 height=16 src=\""+contextPath+"/tgweb20/media/Calendar.gif\"></img>";
						this.setDatePickerExist(true);
					}
					
					//Case label : generate a <label> tag with an empty space inside it
					else if(this._isLabel(type)){
						//Get Default Value
						var xmlOptionsdefault = gridDataCell.split("///")[2];
						if(data == "") data = "&nbsp";							
						if(xmlOptionsdefault && xmlOptionsdefault!="" && xmlOptionsdefault!= null && xmlOptionsdefault!="null" ) {
							coreHtml += "<label style='bold' key='"+xmlOptionsdefault+"'>"+data.replace(/"/g, "&quot;")+"</label>";
						} else{
							coreHtml += "<label style='bold'>"+data.replace(/"/g, "&quot;")+"</label>";
						}
					}
					
					else if(this._isTypeAhead(type)){
						var rowNumber = this.getInitialRowCount();	
						coreHtml += "<input class='tgInputBorder' textType='typeahead' size="+column.iconWidth+" type = 'text' value =\""+data +"\" id=\""+this.tableName+'_'+column.id+'_'+rowNumber+"\" style='vertical-align:top'></input>";							
						rowNumber++;
						this.setInitialRowCount(rowNumber);
					}
					
					//If none of the types were matched, then the type is either "text"
					//or unknown, so => generate an input whose type is text
					else{	
						coreHtml += "<input class='tgInputBorder' textType='text' size="+column.iconWidth+" type = 'text' value =\""+data.replace(/"/g, "&quot;")+"\" style='vertical-align:top'></input>";							
					}
					coreHtml+= "</td>"
					
					return coreHtml;
				}				
		
			
			// create the HTML code for the actionColumns if they exist
			this._createHtmlActionColumns = function(rowIndex, startActionIndex) {
				var coreHtml = "";
				for(var index = startActionIndex; index < this.actionColumns.length; index++){
					var imgHtml = "";
					var tdWidth = this.actionColumns[index].size;					
					if(this.actionColumns[index].type == "moveUp"){
						if(rowIndex==0){
							imgHtml = "<img class='tg_pe_moveup_icon' src="+this.actionColumns[index].value+" style='cursor:pointer;display:none' height ="+this.actionColumns[index].iconHeight+"px width="+this.actionColumns[index].iconWidth+"px func=moveUp ></img>";
						} else {
							imgHtml = "<img class='tg_pe_moveup_icon' src="+this.actionColumns[index].value+" style='cursor:pointer;' height ="+this.actionColumns[index].iconHeight+"px width="+this.actionColumns[index].iconWidth+"px func=moveUp ></img>";
						}
						this.setMoveRowUpExist(true);
					}else if(this.actionColumns[index].type == "moveDown"){
						if(rowIndex == this.gridData.length - 1){
							imgHtml = "<img class='tg_pe_movedown_icon' src="+this.actionColumns[index].value+" style='cursor:pointer;display:none' height ="+this.actionColumns[index].iconHeight+"px width="+this.actionColumns[index].iconWidth+"px func=moveDown ></img>";
						} else {
							imgHtml = "<img class='tg_pe_movedown_icon' src="+this.actionColumns[index].value+" style='cursor:pointer;' height ="+this.actionColumns[index].iconHeight+"px width="+this.actionColumns[index].iconWidth+"px func=moveDown ></img>";
						}
						this.setMoveRowDowExist(true);
					}else if(this.actionColumns[index].type == "delete"){
						imgHtml = "<a class='lotusDelete'><img height ="+this.actionColumns[index].iconHeight+"px width="+this.actionColumns[index].iconWidth+"px aria-label='delete button' alt='' src="+this.actionColumns[index].value+" func=delete><span class='lotusAltText'>X</span></a>";							
						this.setDeleteRowExist(true);
					}else if(this.actionColumns[index].type == "insertRow"){
						imgHtml = "<img src="+this.actionColumns[index].value+" style='cursor:pointer;' height ="+this.actionColumns[index].iconHeight+"px width="+this.actionColumns[index].iconWidth+"px func=insertRow ></img>";
						this.setInsertRowExist(true);
					}		
								
					//Build td and loop again	
					if(tdWidth && tdWidth!='')
						coreHtml += "<td class='"+this._getRowAlternationClass(rowIndex)+"' style='overflow:hidden; padding: 3px; vertical-align: top;' width="+this.actionColumns[index].size+"px>"+ imgHtml + "</td>";
					else
						coreHtml += "<td class='"+this._getRowAlternationClass(rowIndex)+"' style='overflow:hidden; padding: 3px; vertical-align: top;'>"+ imgHtml + "</td>";
				}
								
				return coreHtml;
			}
						
			this.displayLinkCont = true;

			this.setDisplayLinkContent = function(value){
				this.displayLinkCont = value;
			}	
			
			this.footerHtml = "";
			//Set a footer for the grid => can contain any HTML code
			/*
				htmlText : html code that will represents the footer
			*/
			this.setFooterHtml = function(htmlText){
				var numOfCol = this.columns.length+this.actionColumns.length;
				//colspan=numOfCols so the footer will be distributed evenly throughout the grid width
				var footerId = this.getTableName()+"_footer";
				this.footerHtml = "<tr id =\""+footerId+"\" style='display:none'><td class='lotusLast td tgDynamicTableAltRow' colspan="+numOfCol+" >"+ htmlText+"</td></tr>";
				this.footerEnabled = true;
			};
			
			this.showFooterHtml = function(){
				var footerId = this.getTableName()+"_footer";		
				document.getElementById(footerId).style.display = "";
			}
			
			this.hideFooterHtml = function(){
				var footerId = this.getTableName()+"_footer";
				document.getElementById(footerId).style.display = "none";
			}
			
			this.showHeaderHtml = function(){
				var footerId = this.getTableName()+"_header";		
				document.getElementById(footerId).style.display = "";
			}
			
			this.hideHeaderHtml = function(){
				var footerId = this.getTableName()+"_header";
				document.getElementById(footerId).style.display = "none";
			}
			
			
			this.isFooterHtmlVisible = function(){
				if (this.getFooterEnabled()) {
					var footerId = this.getTableName()+"_footer";
					return (document.getElementById(footerId).style.display != "none");
				} else {
					return false;
				}
			}
			
			//ID of the grid
			//It will be empty for now, but then it will be set to the placeHolderID, after the draw method
			this.id;
			
			this.draw = function(placeHolderID){
				dojo.require("dojo.i18n");
				dojo.requireLocalization("pe.core", "tg_grid");
				this.gridNls = dojo.i18n.getLocalization("pe.core", "tg_grid");
				
				this.id = placeHolderID;			//Sets the palceHolderID as an ID for the grid
				var totalWidth = 0;
				
				for(var i = 0; i < this.columns.length; i++){
					totalWidth += this.columns[i].size;	//Get the grid width
				}
				//Get action columns size
				for(var i = 0; i < this.actionColumns.length; i++){
					totalWidth += this.actionColumns[i].size;
				}
				//Open the table tag
				//var newHtml = "<table class='lotusTable tgDynamicTableBorder' style ='table-layout:fixed;width:"+totalWidth+"px' width="+totalWidth+" cellpadding='2' cellspacing='0' id=table_grid"+placeHolderID+">";
				var newHtml = "<table class='lotusTable tgDynamicTableBorder' style ='' cellpadding='2' cellspacing='0' id=table_grid"+placeHolderID+">";
				var actionColumnsIndex = 0;
				if(this.mouseSortable){
					var index = actionColumnsIndex;
					//newHtml += "<col id='colIndex_"+this.getTableName()+"_"+index+"' width="+this.actionColumns[actionColumnsIndex].size+"px>";
					actionColumnsIndex++;
				}
				if(this.selectionColumnEnabled){
					var index = actionColumnsIndex;
					//newHtml += "<col id='colIndex_"+this.getTableName()+"_"+actionColumnsIndex+"' width="+this.actionColumns[actionColumnsIndex].size+"px>";
					actionColumnsIndex++;
				}
				var idIndex = 0;
				for(var i = 0; i < this.columns.length; i++){
					idIndex = parseInt(actionColumnsIndex) + i;
					//newHtml += "<col id='colIndex_"+this.getTableName()+"_"+idIndex+"' width="+this.columns[i].size+"px>";
				}
				for(;actionColumnsIndex < this.actionColumns.length; actionColumnsIndex++){
					idIndex++;
					//newHtml += "<col id='colIndex_"+this.getTableName()+"_"+idIndex+"' width="+this.actionColumns[actionColumnsIndex].size+"px>";
				}
				//To draw the whole grid : 1-draw header, then draw core, then draw footer
				newHtml += this.drawHeader();
				newHtml += this.drawCore();
				newHtml += this.footerHtml;
				//Close the table tag
				newHtml += "</table>";
				//When the page loads, assign the html of the grid to the placeHolderI
				var ID = this.id;
				
				//dojo.addOnLoad(function(){
					dojo.html.set(dojo.byId(ID),newHtml);
				//});
				
				_intializeGlobalMouseClick(this);
				_initializeGridActions(this,1);
				if(this.getDatePickerExist()){
					_initializeDatePicker(this,1);
				}
				if(this.getLinkPickerExist()){
					_intializeDeletePickerRow(this);
				}
				//_validateInt(this);
				_initializeIntInputValidation(this,1);
				//validateDouble(this);
				_initializeDoubleInputValidation(this,2);
				_checkAll(this);
				_enableURL(this);
				if(this.getListDropDownExist()){
					_onChangeEvent(this,1);
				}
				// optimize: don't need to setAltRow here because the row are directly created with the class for AltRow
				//this.setAltRow();
				this.setMoveUpDownAlt();
			}

			/*
				- Method to set a row in the grid from an XML string passed to it
				- Fills the array 'gridData_row' with the information from the XML string
				and sets this information in the grid when it is called
				XML file for setDataRow() should have the following format : 
				"<row><value></value></row>"
				
				You can have as much row and value tags as you want,
				on the condition that the number of value tags in each rowis equal.						
				If there is no data to put in the value tag, provide an empty value tag
			*/
		this.setDataRow = function(xml){
			//Code for IE				
			try{
				var xmlDoc=new ActiveXObject("Microsoft.XMLDOM");
					xmlDoc.async="false";
					xmlDoc.loadXML(xml);
			}catch(e){
				//Code for Firefox, Opera, Safari,etc...
				try {
					var parser=new DOMParser();
					xmlDoc=parser.parseFromString(xml,"text/xml");
				} catch(e){
					alert(e.message);
				}
			}
				
			//Get all the rows from the XML string
			var allRowsTags = xmlDoc.getElementsByTagName("row");
			var numOfRows = allRowsTags.length;
			if(numOfRows > 0){	
				//Get the number of columns in the grid from the XML string(assuming correct XML format)
				var numOfCol = xmlDoc.getElementsByTagName("row")[0].getElementsByTagName("value").length;
			}else{	
				//If there are no rows, the number of columns is by default set to 0
				//This will be the case of an empty grid
				numOfCol = 0;
			}
			//data_array will hold the grid data from the XML string in an array
			var data_array_row= new Array(numOfRows);
				
			/*Putting the data coming from the XML string in the array*/
			/*Each entry in the array can have any of the following formats:					
				1 - value
				2 - type///value
				3 - type///value///options
				4 - type///value///function body				
			*/
			for(var i = 0; i < numOfRows; i++){
				data_array_row[i] = new Array(numOfCol);	//Specifying the row size in each iteration
				for(var j = 0; j < numOfCol; j++){
					//Get the type of cell from the type attribute given in the XML
					var cellType = allRowsTags[i].getElementsByTagName("value")[j].getAttribute("type");
					//Get the list of options if the type of the cell is a list
					var xmlOptions = allRowsTags[i].getElementsByTagName("value")[j].getAttribute("options");
					//Get the function definition from the function attribute gicen in the XML in case  the type was a 'listFormula'
					var func = allRowsTags[i].getElementsByTagName("value")[j].getAttribute("function");
					//If the value tag is non-empty, we get its value
					try{
						var cellValue = allRowsTags[i].getElementsByTagName("value")[j].childNodes[0].nodeValue;
					}catch(e){
						//If the value tag is empty, we get the default value in the column and give it to the cell
						cellValue = this.columns[j].value;
					}
						
					//If the cellType is empty, assign to data_array_row[i][j] the column type
					if(cellType == null){
						data_array_row[i][j] = cellValue;
						if(this._isListFormula(this.columns[j].type)){
							data_array_row[i][j] = "listFormula///"+cellValue+ "///" + this.columns[j].value;
						}
					}
					//If the cellType is non-empty,  assign to data_array_row[i][j] the cellType
					else{
						//Saving the values in the array using the different pre-mentioned formats, depending on each case
						data_array_row[i][j] = cellType;
							
						if(this._isListFormula(cellType)){
							data_array_row[i][j] += "///" + cellValue + "///" + func;
						}else if(this._isList(cellType)){
							data_array_row[i][j] += "///" + cellValue + "///" + xmlOptions;
						}else if(this._isMultipleLis(cellType)){
							data_array_row[i][j] += "///" + cellValue + "///" + xmlOptions;
						}else if(this._isLink(cellType)){
							data_array_row[i][j] += "///" + cellValue + "///" + xmlOptions;
						}else{
							data_array_row[i][j] += "///" + cellValue;
						}
					}
					
					//Resetting the cellValue, cellType, and func variables to re-use on next iteration
					cellValue = "";
					cellType = null;
					func = null;
				}
			}
			//Assign the values in data_array_row to gridData_row, so the grid now contains the data
			this.gridData_row = data_array_row;
		};
			
			
		this.initializeDND = function(){			
			var footerIsEnabled = this.footerEnabled;
			var gridObj = this;
			if(this.mouseSortable && this.edit){					
				var mouseX, mouseY, lastX, lastY = 0;
				dojo.connect(document,"onmousemove",function(e){
					mouseX = e.pageX; 
					mouseY = e.pageY;
				});
				
				//IE Doesn't stop selecting text when mousedown returns false we need to check
				// That onselectstart exists and return false if it does -- we won't check if the browser is IE
				// As thy may very well change this at some point
				var need_select_workaround = typeof dojo.attr(document,"onselectstart") != 'undefined';
				
				var ID = this.id;
				var footerIsEnabled = this.footerEnabled;
				var mouseEnterEvent;
				dojo.query("#"+ID+" > table > tbody > tr > td[func='dragAndDrop']").onmousedown(function(e){
					var mouseDown = true;																										 
																													   																																			  
					lastY = mouseY;	
					var tr = dojo.query(this.parentNode);
					dojo.style(tr[0],"backgroundColor","#C4DDF7");			
					var mouseDown = this;
					
					dojo.query("#"+ID + " > table > tbody > tr").onmouseenter(function(ev){			
					   if(mouseDown){	
					   	var rows = dojo.query("#"+ID + " > table > tbody > tr"); 
						var numOfRows = rows.length - 1 ;
						
						if(footerIsEnabled){
							numOfRows--;
						}							
			
						var rowIndex = dojo.indexOf(rows,this);
						if(rowIndex >0 && rowIndex <= numOfRows){
							if(mouseY > lastY){	
								dojo.place(this, tr[0],"before");
							}else {												
								dojo.place(tr[0], this,"before");																
							}								
							if(gridObj.getRowAlternationMode()){									
									gridObj.setAltRow();
							}
							gridObj.setMoveUpDownAlt();							
						}
						lastY = mouseY;	
					   } 
					});
					dojo.query("body").onmouseup(function(ev){						
						dojo.style(tr[0],"backgroundColor","White");
						mouseDown = false;
						dojo.stopEvent(ev);
					});
				});
				dojo.style(dojo.query("#"+ID+" > table > tbody > tr > td[func='dragAndDrop']"),"cursor","move");				
			}
		}

			
			//Returns the row index of the specified cell
			this.getRowIndex = function(cell){
				//dojo Code
				var parentIsTr = false;
				var tempObj = cell[0];
				var tr = '';
				while (!parentIsTr){
					var contentValue = tempObj.innerHTML.toLowerCase();
					if(tempObj.innerHTML && contentValue.indexOf("<td") != -1){
						tr = tempObj;
						parentIsTr = true;
					} else {
						tempObj = tempObj.parentNode;
					}
				}
				var rowIndex = dojo.indexOf(dojo.query("#"+this.id+" > table > tbody > tr"),tr) + 1;
				return rowIndex;
			}
			
			this.getRowIndexForInput = function(cell){
				var tr = cell.parentNode;
				return tr.rowIndex;
			}
			
			//Returns the column index of the specified cell
			this.getColIndexForInput = function(cell){
				//Counts how many non-data columns we have
				var uncountedInitialColumns = 0;
				if(this.mouseSortable){
					uncountedInitialColumns++;
				}
				if(this.selectionColumnEnabled){
					uncountedInitialColumns++;
				}
				var tr = cell.parentNode;
				var allCells = dojo.query("td", tr);
				index = dojo.indexOf(allCells, cell) - uncountedInitialColumns;
				return index;
			}
			
			//Returns the column index of the specified cell
			this.getColIndex = function(cell){
				//Counts how many non-data columns we have
				var uncountedInitialColumns = 0;
				if(this.mouseSortable){
					uncountedInitialColumns++;
				}
				if(this.selectionColumnEnabled){
					uncountedInitialColumns++;
				}
				
				var td = cell[0].parentNode;
				var tr = td.parentNode;
				var allCells = dojo.query("td", tr);
				//var allCells = dojo.query("#"+this.id+" > table > tbody > tr > td");
				index = dojo.indexOf(allCells,td);	
				
				if(index == -1){
					td = td.parentNode;
					var tr = td.parentNode;
					var allCells = dojo.query("td", tr);
					index = dojo.indexOf(allCells,td);	
				}				
				return index;
			}
			
			//Returns the column index of the specified cell
			this.getInternalColumnIndex = function(cell){
				//Counts how many non-data columns we have
				var uncountedInitialColumns = 0;
				if(this.mouseSortable){
					uncountedInitialColumns++;
				}
				if(this.selectionColumnEnabled){
					uncountedInitialColumns++;
				}
				
				var td = cell[0].parentNode;
				var tr = td.parentNode;
				var allCells = dojo.query("td", tr);
				
				var realCellIndex = dojo.indexOf(allCells,td);
				if(realCellIndex == -1){
					td = td.parentNode;
					var tr = td.parentNode;
					var allCells = dojo.query("td", tr);
					realCellIndex = dojo.indexOf(allCells,td);
				}				
				index = realCellIndex - uncountedInitialColumns;	
				return index;
			}
			
			/*
				Validates all feilds that are integers.
				showAlert is a boolean that specifies whether an alert will appear or not
			*/
			this.validateAllIntegers = function(showAlert){
				var numberOfRows = dojo.query("#"+ this.id + " > table > tbody > tr").length - 1 ; //number of rows without the header
				var numberOfColumns = this.columns.length;
				var all_are_integers = true;

				if(this.footerEnabled){
					numberOfRows--;
				}
				
				var uncountedInitialColumns = 0;
				if(this.mouseSortable){
					uncountedInitialColumns++;
				}
				if(this.selectionColumnEnabled){
					uncountedInitialColumns++;
				}
				numberOfColumns+=uncountedInitialColumns
				//We need to access the 'this' in a jQuery Call, so we save it in myGrid
				var myGrid = this;
				
				//dojo.addOnLoad(function(){
					for(var i=0; i < numberOfRows ; i++){
						for (var j=1 ; j < numberOfColumns ; j++){
							//If cell type is integer
							if(this.getCellType(i+2,j) == 'integer' ){
								//get value
								var val = this.getCellValue(i+2,j);
								//Check if the value is an integer
								if(!(isInteger(val))){
									all_are_integers = false;
								}
							}
						}
					}
				//});
				
				if(!all_are_integers && showAlert){
					alert(this.gridNls.invalidInt);	//invalidInt is a variable in the translation file, which is alerted depending on the chosen language
				}
				return all_are_integers;
			}
			
			/*
				Validates all feilds that are doubles.
				showAlert is a boolean that specifies whether an alert will appear or not
			*/
			this.validateAllDoubles = function(showAlert){
				//dojo Code
				var numberOfRows = dojo.query("#"+ this.id + " > table > tbody > tr").length - 1 ;
				var numberOfColumns = this.columns.length;
				var all_are_doubles = true;
				
				if(this.footerEnabled){
					numberOfRows--;
				}

				var uncountedInitialColumns = 0;
				if(this.mouseSortable){
					uncountedInitialColumns++;
				}
				if(this.selectionColumnEnabled){
					uncountedInitialColumns++;
				}
				numberOfColumns+=uncountedInitialColumns

				var myGrid = this;	//We need to access the 'this' in a jQuery Call, so we save it in myGrid
								
				for(var i=0; i < numberOfRows ; i++){
					for (var j=1 ; j < numberOfColumns ; j++){
						//If cell type is double
						if(myGrid.getCellType(i+2,j) == 'double' ){
							var val = myGrid.getCellValue(i+2,j);	//Get cell value								
							if(!(isDouble(val))){
								all_are_doubles = false;
							}
						}
					}
				}
				
				if(!all_are_doubles && showAlert){
					alert(this.gridNls.invalidDouble);		//Invalid double comes from the translation file
				}
				return all_are_doubles;
			}
			
			//Columns whose 'required' boolean is set to true have to have all their fields filled.
			//This method checks whether all columns whose 'required' feild is set to true have data in all their cells
			this.validateRequiredFields = function(showAlert){
				var retValue = true;
				var numOfCols = this.columns.length;
				//Loop over all the columns, and if the column's 'required' field is true, it checks for empty cells in it 
				for(var i=0; i < numOfCols ; i++){
					if(this.columns[i].required == true){
						var numOfRows = dojo.query("#"+this.id+" > table > tbody > tr").length;
						if(this.footerEnabled){
							numOfRows--;
						}							
						for(var j = 0 ; j < numOfRows - 1 ; j++){
							//If any of the column's cells has an empty value, return false
							if(this.getCellValue(j+2, i) == ""){			
								retValue = false;
							}
						}
					}
				}
				if(retValue == false && showAlert){
					//fieldIsRequired is a variable in the translation file
					alert(this.gridNls.fieldIsRequired);
				}
				return retValue;
			}
			
	//Calls validateAllIntegers & validateAllDouble & validateRequiredFeilds on all th grid
	//if any of them return false, it returns falses
	this.validateGrid = function(showAlert){
		return (this.validateRequiredFields(showAlert) && this.validateAllIntegers(showAlert) && this.validateAllDoubles(showAlert));
	}
			
			
		//function typeAheadInitialization(grid,typeAheadParams){
		this.typeAheadInitialization = function(grid,typeAheadParams){
			//dojo.addOnLoad(function(){
				var typeAheadObjArray = dojo.query("#"+grid.id+" > table > tbody > tr > td > input[texttype='typeahead']");
				for(var i=0;i<typeAheadParams.length;i++){
					var columnName = typeAheadParams[i][0];	
					for(var j=0;j<typeAheadObjArray.length;j++){
						if(typeAheadObjArray[j].id.indexOf(columnName)!=-1){
							var obj = dojo.byId(typeAheadObjArray[j].id);
							var typeAheadvalue = '';
							var url = typeAheadParams[i][1];
							var locale = typeAheadParams[i][2];
							var dataBaseName = typeAheadParams[i][3];
							var viewName = typeAheadParams[i][4];
							var subQuery = typeAheadParams[i][5];
							var responseParameter = typeAheadParams[i][6];
							var serverResponseCount =  typeAheadParams[i][7];
							var minimumDisplay =  typeAheadParams[i][8];
							var displayFooter = typeAheadParams[i][9];
							var onAfterClickFunction  = typeAheadParams[i][10];
							var transactionType  = typeAheadParams[i][11];
							var parentId  = typeAheadParams[0][12];
							var typeAheadEx = new typeAhead(grid.contextPath, url,locale,obj,dataBaseName,viewName,subQuery,responseParameter,serverResponseCount,transactionType);
							typeAheadEx.setDisplayFooter(displayFooter);
							typeAheadEx.setMinimumDisplayed(minimumDisplay);
							typeAheadEx.setOnAfterClickEvent(onAfterClickFunction);
							typeAheadEx.setParentId(parentId);
							typeAheadEx.onLoadEvent();
						}
					}
				}
			//});
		}
		
		//function typeAheadInitialization(grid,typeAheadParams){
		this.typeAheadRowInitialization = function(grid,typeAheadParams,cellPosition){
			/*var obj = dojo.query("#"+grid.id+" > table > tbody > tr > td > input[texttype='typeahead']");
			var len = obj.length;
			var typeAheadId = dojo.query("#"+grid.id+" > table > tbody > tr > td > input[texttype='typeahead']")[len-2].id;	*/		
			
			
			var obj = this.getCell(this.getNumofRows(), cellPosition);
			//dojo.addOnLoad(function(){				
			var obj = dojo.byId(dojo.query('> *', dojo.query(obj)[0])[0].id);		
			//var obj = dojo.byId(typeAheadId);		
			var typeAheadvalue = '';
			var url = typeAheadParams[0][1];
			var locale = typeAheadParams[0][2];
			var dataBaseName = typeAheadParams[0][3];	
			var viewName = typeAheadParams[0][4];
			var subQuery = typeAheadParams[0][5];
			var responseParameter = typeAheadParams[0][6];
			var serverResponseCount =  typeAheadParams[0][7];
			var minimumDisplay =  typeAheadParams[0][8];
			var displayFooter = typeAheadParams[0][9];
			var onAfterClickFunction  = typeAheadParams[0][10];
			var transactionType  = typeAheadParams[0][11];	
			var parentId  = typeAheadParams[0][12];
			var typeAheadEx = new typeAhead(grid.contextPath, url,locale,obj,dataBaseName,viewName,subQuery,responseParameter,serverResponseCount,transactionType);
			typeAheadEx.setDisplayFooter(displayFooter);
			typeAheadEx.setMinimumDisplayed(minimumDisplay);
			typeAheadEx.setOnAfterClickEvent(onAfterClickFunction);
			typeAheadEx.setParentId(parentId);			
			typeAheadEx.onLoadEvent();
			//});
		}
		
		
		this._isInteger = function(type){
			return (type == "integer" || type == "Integer" || type == "Int" || type == "int");
		}
		this._isDouble = function(type){
			return (type == "double" || type == "Double");
		}
		this._isCheckbox = function(type){
			return (type == "checkbox" || type == "checkBox" || type == "CheckBox" || type == "Checkbox");
		}
		this._isBoolean = function(type){
			return (type == "Boolean" || type == "boolean" || type == "Bool" || type == "bool");
		}
		this._isDate = function(type){
			return (type == "date" || type == "Date");
		}
		this._isLabel = function(type){
			return (type == "label" || type == "Label" || type == "LABEL");
		}
		this._isText = function(type){
			return (type == "text" || type == "Text");
		}
		this._isIcon = function(type){
			return (type == "icon" || type == "Icon");
		}
		this._isTypeAhead = function(type){
			return (type == "typeahead" || type == "Typeahead" || type == "TypeAhead" || type == "typeAhead");
		}
		this._isLink = function(type){
			return (type == "link" || type == "Link" || type == "LINK");
		}
		this._isList = function(type){
			return (type == "list" || type == "List");
		}
		this._isListFormula = function(type){
			return (type == "listFormula" || type == "ListFormula");
		}
		this._isMultipleList = function(type){
			return (type == "multiplelist");
		}		
		this._isSelect = function(type) {
			return (type == "SELECT" || type == "select" || type == "Select");
		}
		

}//END OF GRID OBJECT

		//Method to activate the URL of a column
		// private method. Should be moved inside grid object
		function _enableURL(grid)
		{	
				//Enable the URL for all the cells in a single column
				for(var i = 0; i < grid.columns.length; i++)
				{
					if(grid.columns[i].popupURL && grid.columns[i].popupURL != "")	//if the column url is specified
					{
						grid.enableColumnURL(i);	//calls the internal method on every cell in the column
					}
				}
		}
		
		// private method. Should be moved inside grid object
		function _onChangeEventInitialize(grid){
			grid.onChangeEvent = dojo.query("#"+grid.id+" > table > tbody > tr > td > select[listtype='list']").map(function(x){
				return dojo.connect(x,"onchange",function(e){
					var colIndex = grid.getInternalColumnIndex(dojo.query(this));//Get the column containing the list
					//if (dojo.isIE<8) colIndex++; // fix for bug 4492.
					if(grid.columns[colIndex].columnFunction)//Check if the column has a columnFunction
					{
						var func = grid.columns[colIndex].columnFunction;//Assign the column function to a variable func

						func += "";
						func = func.substring(func.indexOf("{")+1, func.length-1);	//Get the function body
						eval(func);
					}
				});
			});
		}
		
		// private method. Should be moved inside grid object
		function _onChangeEvent(grid,pos){
				switch(pos){
					case 1:
						_onChangeEventInitialize(grid);
						break;
					case 2:
						dojo.forEach(grid.getOnChangeEvent(),function(x){
							dojo.disconnect(x);
						});
						_onChangeEventInitialize(grid);
						break;
				}
		}	
		
		//Method to load the datepicker when a cell of type Date occurs
		// private method. Should be moved inside grid object
		function _initializeDatePicker(grid,pos){
				switch(pos){
				case 1:
					_showDatePicker(grid);
					break;
				case 2:
					dojo.forEach(grid.getDatePickerEvent(),function(x){
						dojo.disconnect(x);
					});
					dojo.forEach(grid.getImagePickerEvent(),function(x){
						dojo.disconnect(x);
					});
					_showDatePicker(grid);
					break;
				}
		}
		
		// private method. Should be moved inside grid object
		function _initializeIntInputValidation(grid,pos){
			switch(pos){
				case 1:
					_validateInt(grid);
					break;
				case 2:
					dojo.forEach(grid.getValidateIntEvent(),function(x){
						dojo.disconnect(x);
					});
					_validateInt(grid);
					break;
			}
		}
		
		// private method. Should be moved inside grid object
		function _initializeDoubleInputValidation(grid,pos){
			switch(pos){
				case 1:
					validateDouble(grid);
					break;
				case 2:
					dojo.forEach(grid.getValidateDoubleEvent(),function(x){		
						dojo.disconnect(x);
					});
					validateDouble(grid);
					break;
			}
		}
			
			// private method. Should be moved inside grid object
			function _initializeInputDatePicker(calendar,grid){
				grid.datePickerEvent = dojo.query("#"+grid.id+" > table > tbody > tr > td > input[texttype='date']").map(function(x){		
					return dojo.connect(x,"onclick",function(e){	
						grid.datepickerWidth = this.parentNode.clientWidth;
						grid.datepickerHeight = this.parentNode.clientHeight;
						calendar._pushChangeTo = this; 
						grid.popupCalendar = dijit.popup.open({
								popup: calendar,
								around: this
						}); 
						grid.datePickerEventStatus = true;
						_intializeGlobalMouseClick(grid);
						dojo.forEach(grid.getDatePickerEvent(),function(x){
							dojo.disconnect(x);
						});
					});
				});
			}
			
			// private method. Should be moved inside grid object
			function _initializeImageDatePicker(calendar,grid){
				grid.imagePickerEvent = dojo.query("#"+grid.id+" > table > tbody > tr > td > img[imgtype='date']").map(function(x){
					return dojo.connect(x,"onclick",function(e){	
						var input = dojo.query(" > input[texttype='date']",this.parentNode)[0];
						grid.datepickerWidth = this.parentNode.clientWidth;
						grid.datepickerHeight = this.parentNode.clientHeight;
						calendar._pushChangeTo = input; 
						// and open the popup below the targeted input
						dijit.popup.open({
							popup: calendar,
							around: input
						}); 
						grid.datePickerEventStatus = true;
						_intializeGlobalMouseClick(grid);
						dojo.forEach(grid.getImagePickerEvent(),function(x){
							dojo.disconnect(x);
						});
					});
				});
			}
			
			// private method. Should be moved inside grid object
			function _intializeGlobalMouseClick(grid){
					grid.mouseClickEvent =dojo.query(document).map(function(x){	
							return dojo.connect(x,"onclick",function(e){	
								if(dojo.query("#"+grid.getdojoCalendar().id)!=""){
									var parentElt = dojo.byId(grid.getdojoCalendar().id).parentNode;	
									if(parentElt.tagName=="DIV"){		
										var positionY = parentElt.style.top.split("px")[0];
										var positionX = parentElt.style.left.split("px")[0];
										var lengthY = parentElt.clientWidth;
										var lengthX = parentElt.clientHeight;

										//if(( positionX<e.pageX && e.pageX<(parseFloat(positionX)+parseFloat(lengthX))) && (parseFloat(positionY)-parseFloat(grid.getDatePickerHeight()))<e.pageY && e.pageY<(parseFloat(positionY)+parseFloat(lengthY))){												
										if (tg_isClickInObject(e, parentElt, 20)) {
											//alert("true");
										} else{
											//alert("false");
											dojo.forEach(grid.getDatePickerEvent(),function(x){
												dojo.disconnect(x);
											});
											dojo.forEach(grid.getImagePickerEvent(),function(x){
												dojo.disconnect(x);
											});
											_initializeInputDatePicker(grid.getdojoCalendar(),grid);
											_initializeImageDatePicker(grid.getdojoCalendar(),grid);
											grid.popupCalendar = false;
											dijit.popup.close(grid.getdojoCalendar());
											grid.datePickerEventStatus = false;
										}
									}
								}
							});

					});
			}

			//Function that displays the datepicker
			// Note: there is another function named showDatePicker in projexec/shared/pe_shared_actualspopup.xsp
			// private method. Should be moved inside grid object
			function _showDatePicker(grid){
					// create a new instance of Calendar if not already done
					if (! grid.dojoCalendar) {
						grid.dojoCalendar = new dojox.widget.Calendar({
							onValueSelected: function(val){
								// when the value changes, hide the popup 
								// and set a value to our input
								dojo.forEach(grid.getDatePickerEvent(),function(x){
									dojo.disconnect(x);
								});
								dojo.forEach(grid.getImagePickerEvent(),function(x){
									dojo.disconnect(x);
								});
								_initializeInputDatePicker(grid.getdojoCalendar(),grid);
								_initializeImageDatePicker(grid.getdojoCalendar(),grid);
								grid.popupCalendar = false;
								dijit.popup.close(grid.getdojoCalendar());
								grid.datePickerEventStatus = false;
								var dateStr = dojo.date.locale.format(val, { selector: "date", formatLength: "short"});
								if (dojo.locale.indexOf("no") == 0 && dateStr.indexOf("-")!= -1) {
									// the date formated by dojo 1.3.2 is incorrect it returns "2012-08-10" instead of "10.08.12"
									this._pushChangeTo.value = val.getDate()+"."+(val.getMonth()+1)+"."+val.getFullYear();	
								} else {
									this._pushChangeTo.value = dateStr;
								}
							},
							destroy: function(){
								// avoid leaving a ref in object for IE
								delete this._pushChangeTo;
								this.inherited(arguments);
							}, onMouseUp: function(){
								//alert("onMouseUp");
							}, onChange: function(){
								//alert("onChange");
							}
						});
					} else {
						dojo.forEach(grid.getDatePickerEvent(),function(x){
							dojo.disconnect(x);			
						});
						dojo.forEach(grid.getImagePickerEvent(),function(x){
							dojo.disconnect(x);			
						});
					}
					
					dojo.extend(dojo.NodeList, {
						// the guts of the "plugin"
						addPicker: function(args){
							_initializeInputDatePicker(grid.getdojoCalendar(),grid);
							_initializeImageDatePicker(grid.getdojoCalendar(),grid);
							return this; // dojo.NodeList
						}
					});
					// one line of code:
					dojo.query(".datePicker").addPicker();
		}
		
			/*
				This has a mechanism that checks all the rows in the selection column 
				when the header select-box is checked, and deselects all the rows when 
				the header check-box is unselected
			*/
			// private method. Should be moved inside grid object
			function _checkAllSelectionColumn(grid,object)
			{
						var ID = grid.id;		//Access the this.id later in a the jQuery call
						var mouseSortableEnabled = grid.getMouseSortable(); //Access whether the drag-and-drop is enabled later in the jQuery call
						var footerIsEnabled = grid.getFooterEnabled();		//Access whether the footer is enabled later in the jQuery call
						//var selectionColumnIsEnabled = grid.getSelectionColumnEnabled();
						var selectionColumnIsEnabled = true;

						//dojo.addOnLoad(function(){		
							var rows = dojo.query("#"+ID+" > table > tbody > tr"); //Get all the rows including the header
							var numOfRows = rows.length ;											//Get the number of rows
							//If the grid is non-empty
							
							if(numOfRows != 0 )
							{
								//Decrement the number of rows if the footer is enabled
								if(footerIsEnabled)
								{
									numOfRows--;
								}
								
								//Check at what index the selection column falls, index 0 or index 1
								if(selectionColumnIsEnabled)
								{
									selectionColumnIndex = 0;
									if(mouseSortableEnabled)
									{
										selectionColumnIndex++;
									}
									
									var allCheckBox = dojo.query("#"+ID+" > table > tbody > tr > th > input[type='checkbox']");
									for(var j=0;j<allCheckBox.length;j++){
										if(allCheckBox[j] == object){
											if(dojo.attr(dojo.query("#"+ID+" > table > tbody > tr > th > input[type='checkbox']")[j],"checked")==true)
											{
												//Loop on the rest of the selection column check-boxes and check them all
												for(var i=2;i<=numOfRows;i++)
												{
													//Set the checked attribute for the checkboxes to true
													dojo.attr(dojo.query("#"+ID+" > table > tbody > tr:nth-child("+i+") > td > input[type='checkbox']")[j],"checked",true);
												}
												dojo.forEach(grid.getCheckAllEvent(),function(x){
													dojo.disconnect(x);
												});
												_checkAll(grid);
											}
											else 
											{
												//Loop on the rest of the selection column check-boxes and uncheck them all
												for(var i=2;i<=numOfRows;i++)
												{
													//Set the checked attribute for the checkboxes to false
													dojo.attr(dojo.query("#"+ID+" > table > tbody > tr:nth-child("+i+") > td > input[type='checkbox']")[j],"checked",false);												
												}
												dojo.forEach(grid.getCheckAllEvent(),function(x){
													dojo.disconnect(x);
												});
												_checkAll(grid);
											}
										}
									}
								} 
							}
						//});
		}
		
		
		//Initializes the checkAllSelectionColumn if the header checkbox is changed
		// private method. Should be moved inside grid object
		function _checkAll(grid)
		{
				//dojo Code
				var isMouseSortable = grid.getMouseSortable();
				var selectionColumnIndex = 0;
				if(isMouseSortable)
				{
					selectionColumnIndex++;
				}
		
					var rows = dojo.query("#"+grid.id+" > table > tbody > tr");
					var numOfRows = rows.length;
					if(grid.getFooterEnabled())
					{
						numOfRows--;
					} 
					grid.checkAllEvent = dojo.query("#"+grid.id+" > table > tbody > tr > th > input[type='checkbox']").map(function(x){	
						return dojo.connect(x,"onclick",function(e){
							_checkAllSelectionColumn(grid,x);
						});
					});
		}
		
		// private method. Should be moved inside grid object
		function _intializemoveRowDown(grid)
		{
			var index;
			if(grid.getMoveRowDowExist()){
				grid.moveRowDownEvent = dojo.query("#"+grid.id+" > table > tbody > tr > td > img[func='moveDown']").map(function(x){		
						return dojo.connect(x,"onclick",function(e){		
							index = dojo.indexOf(dojo.query("#"+grid.id+" > table > tbody > tr > td > img[func='moveDown']"),this);								
							grid.moveRowDown(index);
							setRowIndexOnAction(index);	
						});
					});
			}
		}
		
		// private method. Should be moved inside grid object
		function _intializemoveRowUp(grid)
		{
			var index;
			if(grid.getMoveRowUpExist()){
				grid.moveRowUpEvent = dojo.query("#"+grid.id+" > table > tbody > tr > td > img[func='moveUp']").map(function(x){		
						return dojo.connect(x,"onclick",function(e){		
							index = dojo.indexOf(dojo.query("#"+grid.id+" > table > tbody > tr > td > img[func='moveUp']"),this);		
							grid.moveRowUp(index);	
							setRowIndexOnAction(index);	
						});
					});
			}
		}
	
		
		// private method. Should be moved inside grid object
		function _intializeDeleteRow(grid)
		{
			var index;
			if(grid.getDeleteRowExist()){
				grid.deleteRowEvent = dojo.query("#"+grid.id+" > table > tbody > tr > td > a > img[func='delete']").map(function(x){		
						return dojo.connect(x,"onclick",function(e){	
							var deletesObj = dojo.query("#"+grid.id+" > table > tbody > tr > td > a > img[func='delete']");
							index = dojo.indexOf(deletesObj,this);
							
							// with dojo 1.3.2 and documentMode IE7, the order for the elements returned is reversed -> must correct the row index -> this only happens in QD since all other 
							// environments use a newer version of dojo
							if (dojo.version.major == 1 && dojo.version.minor == 3 && dojo.isIE && document.documentMode <= 7) {
								index = deletesObj.length - index - 1;
							}
							
							grid.deleteRow(index);
							setRowIndexOnAction(index);
							grid.setAltRow();
							grid.setMoveUpDownAlt();
							if(grid.getDeleteFunction())
								eval(grid.getDeleteFunction());
						});
					});
			}
		}
		
		// private method. Should be moved inside grid object
		function _intializeDeletePickerRow(grid)
		{
			if(grid.getLinkPickerExist()){
				grid.deleteRowPickerEvent = dojo.query("#"+grid.id+" > table > tbody > tr > td > table > tbody > tr > td > table > tbody > tr > td > a > img[func='deletepicker']").map(function(x){								
						return dojo.connect(x,"onclick",function(e){
							if(grid.edit){
								var tdAvailable = true;
								var trObject = '';
								while(tdAvailable){
									if(x.innerHTML.toLowerCase().indexOf('<td') != -1){
										tdAvailable = false;
									} else {
										x = x.parentNode;
										trObject = x;
									}
								}
								if (trObject.parentNode){
									trObject.parentNode.removeChild(trObject);
								}
							}
						});
					});
			}
		}
		
		// private method. Should be moved inside grid object
		function _initializeInsertRow(grid)
		{
			var index;
			if(grid.getInsertRowExist()){
				grid.insertRowEvent = dojo.query("#"+grid.id+" > table > tbody > tr > td > img[func='insertRow']").map(function(x){		
					return dojo.connect(x,"onclick",function(e){			
						index = dojo.indexOf(dojo.query("#"+grid.id+" > table > tbody > tr > td > img[func='insertRow']"),this);
						index++;
						grid.insertRow(index);	
					});
				});
			}
		}
		
		//Initializing the moveUp,moveDown,delete, and insert functions, in order to use them with Action columns
		// private method. Should be moved inside grid object
		function _initializeGridActions(grid,pos){
			var index;
			//dojo.addOnLoad(function(){
				//Move row down function
				switch(pos){
					case 1:
						_intializemoveRowDown(grid);
						_intializemoveRowUp(grid);
						_intializeDeleteRow(grid);
						_initializeInsertRow(grid);
						_intializeDeletePickerRow(grid);
						break;
					case 2:
						dojo.forEach(grid.getMoveRowDownEvent(),function(x){		
							dojo.disconnect(x);
						});
						dojo.forEach(grid.getMoveRowUpEvent(),function(x){
							dojo.disconnect(x);
						});
						dojo.forEach(grid.getDeleteRowEvent(),function(x){
							dojo.disconnect(x);
						});
						dojo.forEach(grid.getDeleteRowPickerEvent(),function(x){
							dojo.disconnect(x);
						});
						dojo.forEach(grid.getInsertRowEvent(),function(x){
							dojo.disconnect(x);
						});
						
						_intializemoveRowUp(grid);
						_intializeDeleteRow(grid);
						_initializeInsertRow(grid);
						_intializemoveRowDown(grid);
						_intializeDeletePickerRow(grid);
						break;
					case 3:
						dojo.forEach(grid.getMoveRowDownEvent(),function(x){		
							dojo.disconnect(x);
						});

						dojo.forEach(grid.getMoveRowUpEvent(),function(x){
							dojo.disconnect(x);
						});

						dojo.forEach(grid.getDeleteRowEvent(),function(x){
							dojo.disconnect(x);			
						});

						dojo.forEach(grid.getDeleteRowPickerEvent(),function(x){
							dojo.disconnect(x);			
						});
						
						dojo.forEach(grid.getInsertRowEvent(),function(x){
							dojo.disconnect(x);			
						});
						
						_intializeDeleteRow(grid);
						_initializeInsertRow(grid);
						_intializemoveRowDown(grid);
						_intializemoveRowUp(grid);
						_intializeDeletePickerRow(grid);
						break;
					case 4:
						dojo.forEach(grid.getMoveRowDownEvent(),function(x){
							dojo.disconnect(x);
						});
						
						dojo.forEach(grid.getMoveRowUpEvent(),function(x){
							dojo.disconnect(x);			
						});
						
						dojo.forEach(grid.getDeleteRowEvent(),function(x){
							dojo.disconnect(x);			
						});
						
						dojo.forEach(grid.getDeleteRowPickerEvent(),function(x){
							dojo.disconnect(x);			
						});
						
						dojo.forEach(grid.getInsertRowEvent(),function(x){
							dojo.disconnect(x);			
						});
						_initializeInsertRow(grid);
						_intializemoveRowDown(grid);
						_intializemoveRowUp(grid);
						_intializeDeleteRow(grid);
						_intializeDeletePickerRow(grid);
						break;
					case 5:
						dojo.forEach(grid.getMoveRowDownEvent(),function(x){		
							dojo.disconnect(x);
						});
						
						dojo.forEach(grid.getMoveRowUpEvent(),function(x){
							dojo.disconnect(x);			
						});
						
						dojo.forEach(grid.getDeleteRowEvent(),function(x){
							dojo.disconnect(x);			
						});
						
						dojo.forEach(grid.getDeleteRowPickerEvent(),function(x){
							dojo.disconnect(x);			
						});
						
						dojo.forEach(grid.getInsertRowEvent(),function(x){
							dojo.disconnect(x);			
						});

						_intializemoveRowDown(grid);
						_intializemoveRowUp(grid);
						_intializeDeleteRow(grid);
						_initializeInsertRow(grid);
						_intializeDeletePickerRow(grid);
						break;
					default:
						alert("Error in Initialize Grid Actions");
				}
			//});
		}
		
		//Mehtod that calls isInteger(c) on blur
		// private method. Should be moved inside grid object
		function _validateInt(grid){
			if(grid.getIntCellExist()){
				/*grid.validateIntEvent = dojo.query("#"+grid.id+" > table > tbody > tr > td > input[texttype='integer']").onblur(function(){		
					if (dojo.attr(this, "texttype") == "integer") {
						if( ! isInteger(this.value)){
							alert(grid.gridNls.invalidInt);
						}
					}
				});*/
				
				dojo.forEach(grid.getValidateIntEvent(),function(x){
							dojo.disconnect(x);
				});
				
				grid.validateIntEvent = dojo.query("#"+grid.id+" > table > tbody > tr > td > input[texttype='integer']").map(function(x){	
					return dojo.connect(x,"onblur",function(e){
						if (dojo.attr(this, "texttype") == "integer") {
							if( ! isInteger(this.value)){
								alert(grid.gridNls.invalidInt);
							}
						}
						/*dojo.forEach(grid.getValidateIntEvent(),function(x){
							dojo.disconnect(x);
						});*/
					});
				});	
			}
		}
		
		//Mehtod that calls isDouble(c) on blur
		function validateDouble(grid){	
			if(grid.getIntCellExist()){
				/*grid.validateDoubleEvent = dojo.query("#"+grid.id+" > table > tbody > tr > td > input[texttype='double']").onblur(function(){
					if (dojo.attr(this, "texttype") == "double") {
						if(! isDouble(this.value)){
							alert(grid.gridNls.invalidDouble);
						}
					}
				 });*/
				dojo.forEach(grid.getValidateDoubleEvent(),function(x){
					dojo.disconnect(x);
				});
				grid.validateDoubleEvent = dojo.query("#"+grid.id+" > table > tbody > tr > td > input[texttype='double']").map(function(x){	
					return dojo.connect(x,"onblur",function(e){
						if (dojo.attr(this, "texttype") == "double") {
							if( ! isDouble(this.value)){
								alert(grid.gridNls.invalidDouble);
							}
						}
						/*dojo.forEach(grid.getValidateDoubleEvent(),function(x){
							dojo.disconnect(x);			
						});*/
					});
				});
			 }
		}
				
		
		//Validate Integer
		function isInteger(s){
			for (var i = 0; i < s.length; i++){
				var c = s.charAt(i);
				if (!isDigit(c)){
					return false;
				}
			}
			return true;
		}
		
		//Validate Double
		function isDouble(d){
			var num_of_decimal_pts=0;
			for (var i = 0; i < d.length; i++){
					var c = d.charAt(i);
				if (c=="."){
					num_of_decimal_pts++;
				}
				if (!isDoubleDigit(c)){
					return false;
				}
			}
			
			if(num_of_decimal_pts > 1)
				return false;
			else return true;
		}
		
		//Function that tells whether the given character is a digit
		function isDigit (c){
			return ((c >= "0") && (c <= "9"))
		}
		//Function that tells whether a digit can be used in a double or not
		function isDoubleDigit (c){
			return (((c >= "0") && (c <= "9"))||(c=="."))
		}
		
		// XXX warning: global
		var dynamicTablePickerCellId='';
		function setDynamicTablePickerTableId(_pickerCellId){	
			dynamicTablePickerCellId = _pickerCellId;		
		}		
		
		// Warning: used externally
		function getDynamicTablePickerTableId (){
			return dynamicTablePickerCellId;
		}
		// Warning: used externally
		function getDynamicTablePickerRow(id,grid){				
			return grid.getRowIndexForInput(document.getElementById(id).parentNode);
		}
		// Warning: used externally
		function getDynamicTablePickerColumn(id,grid){			
			var index = grid.getColIndexForInput(document.getElementById(id).parentNode);
			/*if(dojo.isIE < 8)
				return index - 1;*/
			return index;
		}
		
		// XXX warning: global
		var rowIndexOnAction ='';
		// Warning: used externally
		function getRowIndexOnAction(){
			return rowIndexOnAction;
		}
		
		function setRowIndexOnAction(_rowIndexOnAction){
			rowIndexOnAction = _rowIndexOnAction;
		}
		
		// Warning: used externally
		function hideDeleteButton(cell){
			var parentIsTr = false;
			var tempObj = cell[0];
			var tr = '';
 			while (!parentIsTr){
 				var contentValue = tempObj.innerHTML.toLowerCase();
	 			if(tempObj.innerHTML && contentValue.indexOf('<td') != -1){
 					tr = tempObj;
					var deleteObj = dojo.query('.lotusDelete',tempObj)[0];
					deleteObj.style.display='none';
					parentIsTr = true;
				} else {
					tempObj = tempObj.parentNode;
				}
			}
		}
		
		// Warning: used externally
		function hideMoveUpIcons(tableid){
			var iconsObj = dojo.query('.tg_pe_moveup_icon',tableid);
			if(iconsObj){
				for(var i=0;i<iconsObj.length;i++){
					iconsObj[i].style.display = 'none';
				}
			}
		}
		// Warning: used externally
		function displayMoveUpIcons(tableid){
			var iconsObj = dojo.query('.tg_pe_moveup_icon',tableid);
			if(iconsObj){
				for(var i=0;i<iconsObj.length;i++){
					iconsObj[i].style.display = 'block';
				}
			}
		}
		// Warning: used externally
		function hideMoveDownIcons(tableid){
			var iconsObj = dojo.query('.tg_pe_movedown_icon',tableid);
			if(iconsObj){
				for(var i=0;i<iconsObj.length;i++){
					iconsObj[i].style.display = 'none';
				}
			}
		}
		// Warning: used externally
		function displayMoveDownIcons(tableid){
			var iconsObj = dojo.query('.tg_pe_movedown_icon',tableid);
			if(iconsObj){
				for(var i=0;i<iconsObj.length;i++){
					iconsObj[i].style.display = 'block';
				}
			}
		}
		// Warning: used externally
		function xmlencode(string) {
			if (!string.replace) {
				string=new String(string);
			}
   	 		return string.replace(/\&/g,'&'+'amp;').replace(/</g,'&'+'lt;')
        		.replace(/>/g,'&'+'gt;').replace(/\'/g,'&'+'apos;').replace(/\"/g,'&'+'quot;');
		}


// return x y object of the event in the page
function tg_getMousePos(event){
	if (event) {
		if (navigator.userAgent.indexOf('Chrome')!=-1) {
			// chrome
		  return {x:(event.clientX + window.pageXOffset), y:(event.clientY + window.pageYOffset)};
		} else {
			// ff
		  return {x:event.pageX, y:event.pageY};
		}	  
	} else {
			// ie
		if( document.body && ( document.body.scrollLeft || document.body.scrollTop ) ) {
   		//DOM compliant
   		return {x:(window.event.clientX + document.body.scrollLeft), y:(window.event.clientY + document.body.scrollTop)};
  	} else {
  		//IE6 standards compliant mode
  		return {x:(window.event.clientX + document.documentElement.scrollLeft), y:(window.event.clientY + document.documentElement.scrollTop)};
		}
	}
}
			
// return x y position of the object position in the page			
function tg_getObjectXY(obj){
  if (obj.offsetParent){  // ie
    var curleft= 0;
   	var curtop = 0;
    while (obj.offsetParent){
	   	curleft+= obj.offsetLeft;
    	curtop += obj.offsetTop;
    	obj = obj.offsetParent;
    }
    return {x:curleft, y:curtop};
  }
  return {x:obj.x, y:obj.y}; // ff
}
			
// check if mouse click is in the object
function tg_isClickInObject(event, obj, offset) {
	if (typeof offset == "undefined") {
		offset = 10;
	}
	var mousePos = tg_getMousePos(event);		
	var objPos = tg_getObjectXY(obj);
	//console.log("mousePos ", mousePos);
	//console.log("objPos ", objPos);
	
	var objWidth = obj.clientWidth;
	if (typeof objWidth == "undefined") objWidth = obj.offsetWidth;
	var objHeight = obj.clientHeigh;
	if (typeof objHeight == "undefined") objHeight = obj.offsetHeight;	
	//console.log("objWidth ", objWidth);
	//console.log("objHeight ", objHeight);
		
	if ((mousePos.y <  objPos.y-offset) || ( mousePos.y > (objPos.y+objHeight+offset)) 
		|| (mousePos.x < (objPos.x-offset)) || (mousePos.x > (objPos.x+objWidth+offset))) {
		//console.log("outside");
		return false;
	} else {
		//console.log("inside");
		return true;
	}
}

function validateDoubleInput(obj,msg){
	var doubleValue = obj.value;	
	if(dojo.number.parse(doubleValue) || dojo.number.parse(doubleValue) == 0){	
		return true;
	} else if(isNaN(doubleValue)){
		alert(msg);
	}
}

function convertDoubleToPrimitive(value){
	if(dojo.number.parse(value) || dojo.number.parse(value)==0 ){		
		return dojo.number.parse(value);
	} else if(!isNaN(value)){		
		return value;
	}
}
