/**
 * Supports FKey, FKeySet, Block, BlockSet & Parent
 *
 * @extends LoginPanelAgent
 */

function LKTableAgent(id) {

	//Necessary scripts and CSS added, before, in the HTML header via "addCSS" and "addScript" functions (see utils.js)
	//are no more used but those files are added through the ParentWidget Java file
	//(see its "getRequiredCSSFilesForModification()" and "getRequiredJSFilesForModification()" functions).
	
	this.init(id);
	this.width = -1;
	//this.width = "auto"; //"auto" is better:

	this.update = AgentPCB.update;
	this.onLogin = AgentPCB.onLogin


	// set by openPanel
	this.tablePSId = null;
	this.maxTuples = null;
	this.xeReqSpec = null;
	this.distinct = null; // used by Dictionary to eliminate duplicated typical values
	this.idFieldWithSuggestUI = null;  //If we come from a suggestion UI panel (which already has a search filter).
	this.specialPluginFieldId = null; //If we come from a specific Plugin (like Musée Picasso's one), the "select" function will has another functionality.
	
	// /!\ : defines the maximum number of children to be displayed, per pages, in the treeview inner navigation
	//when an element has a lot of children to display.
	this.nbMaxChildrenPerPage = 10;
	this.actualInnerPage = new Array(); //arrays of actual inner pages for several inner children navigation.

	this.openPanel = function(fieldLabel, xeValue, filter, isHierarchical, idFieldWithSuggestUI, specialPluginFieldId) {
		this.idFieldWithSuggestUI = idFieldWithSuggestUI;
		var xeCommand = (this.recId) ? this.xeGetFieldValue() : this.xeGetModGUIData(id);
		
		if (filter != undefined && filter.length > 0) 
			xeCommand.setAttribute('filter', filter);
		
		var eWidgetResult = this.eWidgetResult(xeCommand);
		var eGUI = eWidgetResult.getElementsByTagName('ModGUIData')[0].childNodes[0];

		if(eGUI.tagName == 'LoginModGUIData') {
			this.width = 320;
			this.initLoginPanel(eGUI);
			this.openLoginPanel();
		} else { // LKTableModGUIData
			this.width = 420;
			
			var guiLabels = this.getMap(eGUI.getElementsByTagName('GUILabels')[0]);
			this.guiLabels = this.getMap(eGUI.getElementsByTagName('GUILabels')[0]);
			var colorIconDir = eGUI.getAttribute('colorIconDir');
			var newRecordHref = eGUI.getAttribute('newRecordHref');
			this.tablePSId = eGUI.getAttribute('tablePSId');

			var eReqSpec = eGUI.getElementsByTagName('ReqSpec')[0];
			this.xeReqSpec = XMLTools.convertToXE(eReqSpec);
			this.maxTuples = parseInt(this.xeReqSpec.getAttribute('length'), 10);

			//Gets TypicalSet and TypicalTuples:	
			var eTypicalSet = eGUI.getElementsByTagName('TypicalSet')[0];
			var pageCount = parseInt(((eTypicalSet.getAttribute('count') - 1) / this.maxTuples) + 1, 10);
			var eTypicalTuples = XMLTools.getChildElements(eTypicalSet);
			this.typicalSet = new TypicalSetObject(filter != undefined ? filter : '', 1, pageCount, eTypicalTuples);
			
			/*
			//Gets the root of the hierarchical tree:
			var xeCommand = this.xeGetChildren(this.tablePSId, '');
	    	
	    	var eWidgetResult = this.eWidgetResult(xeCommand);
	    	var eChildrenList = eWidgetResult.getElementsByTagName('ChildrenList')[0];
	    	var eRecordChildren = eChildrenList.getElementsByTagName('RecordChild');
	    	*/
			
			//Perhaps a bit hard to understand, but efficient:
			
	    	var isListView = isHierarchical != undefined && isHierarchical ? ((filter != undefined && filter.length > 0) ? true : (Cookies.get(this.getCookieId()) == 'list') ) : true;
	    	
	    	// /!\ Init this.specialPluginFieldId if it's defined:
			this.specialPluginFieldId = specialPluginFieldId != undefined && specialPluginFieldId.length > 0 ? specialPluginFieldId : null;
			
			this.panel = new LKTablePanel(this.id, fieldLabel, guiLabels, colorIconDir, isListView, this.typicalSet, newRecordHref, isHierarchical, idFieldWithSuggestUI, specialPluginFieldId, pageCount);
			
			
			//If we come from a suggestion UI panel (which already has a search filter):
			if (idFieldWithSuggestUI != undefined && filter != undefined && filter.length > 0) {
				this.applyPattern(filter);
			}
			
			
			
			this.displayPanel();
			this.setPanelWidth();
			// C'est pas la peine d'appeller cette fonction.
//			this.setDivTop();
			this.panel.setFocus();
			this.panel.initRowHighlighter();
			
			//Trick to replace the encoded filter when opening the first time, the panel 
			//(for example, in the advanced search page), by a blank value, which give the same result 
			//(all the possible records in the first result from the encoded filter)
			if (idFieldWithSuggestUI == undefined && filter != undefined && filter.length > 0 && pageCount > 1) {
				this.panel.setPattern('');
			}
			
			//Bug while opening the lkTable panel from the "More" link (with a search filter) from the suggestion pannel (see "suggest.js"):
			if (idFieldWithSuggestUI != undefined && filter != undefined && filter.length > 0) {
				// set DIV style
				var div = this.getDiv(); 
				//No more need of the suggest class (we use the same DIV to generate the panel HTML code but it's not a "suggest" panel.
				$j(div).removeClass("suggest");
				//Reset the width:
				$j(div).css("width", this.width + "px");
				//No font-size needed to be specified (as for the suggestion panel):
				$j(div).css("font-size", '');
				
				//And we move the panel, to the right, in the x position of the input text field which has a SuggestAgent and interface.
				//It will "mask" the default button launching the LkTable interface to avoid unwanted clicks on it (which is not really a problem, in fact).
				$j(div).css("left", getAbsPos($(idFieldWithSuggestUI), 'Left') + "px");
			}
			
			
			if (!isListView) {
				//Root Treeview initialization:
				$j(document).ready(function(){
					initTreeView("#" + id + "-root");
					//Hide/remove what is necessary:
					var firstRootLi = $j("li[id ^= '" + id + "'][id $= '_r0']");
					$j(firstRootLi).css("background", "none");
					var firstRootHitArea = $j(firstRootLi).children("div:first-child");
					//$j(firstRootHitArea).removeClass("hitarea collapsable-hitarea lastCollapsable-hitarea");
					$j(firstRootHitArea).remove();
				});
			}
		}
	}
	
	this.toggleViewType = function() { // cmd : 'list' | 'tree'
		this.panel.isListView = !this.panel.isListView;
		this.displayPanel();
		this.setPanelWidth();
		this.panel.setFocus('vtBut');
		this.panel.initRowHighlighter();
		// update cookie
		var cookieValue = (this.panel.isListView) ? 'list' : 'tree';
		Cookies.set(this.getCookieId(), cookieValue)
	}

	/**
	 * this.tablePSId must be set first!!!
	 */
	this.getCookieId = function() {
		return 'table_' + this.tablePSId + '.typicalViewType';
	}

	/**
	 * this.displayPanel() must be called first
	 */
	this.setPanelWidth = function() {
		//No more table view (which can be really large):
		//this.width = (this.panel.isListView) ? 420 : parseInt(d.body.offsetWidth * 0.8, 10);
		this.getDiv().style.width = this.width;
	}

	
	/**
	 * @return {TypicalSetObject}
	 */
	this.getTypicalSet = function(pattern, pageIndex) {

		if(!pattern)
			pattern = '';
		if(!pageIndex)
			pageIndex = 1;

		// update xeReqSpec
		this.xeReqSpec.setAttribute('start', ((pageIndex - 1) * this.maxTuples) + 1);
		if(pattern) {
			var xeQuickFilter = this.xeReqSpec.getChild('QuickFilter');
			if(!xeQuickFilter)
				xeQuickFilter = new XMLElement('QuickFilter', this.xeReqSpec);
			xeQuickFilter.setAttribute('expr', pattern);
		}

		// create data query XE
		var xeDataQuery = new XMLElement('DataQuery');
		xeDataQuery.setAttribute('count', 'true');
		xeDataQuery.setAttribute('format', 'formattedValues');
		xeDataQuery.setAttribute('onlyTypicalSet', 'true');
		
		var xeRequest = new XMLElement('Request', xeDataQuery);
		xeRequest.setAttribute('psid', this.tablePSId);
		xeRequest.setAttribute('target', 'table');
		xeRequest.appendChild(this.xeReqSpec);

		// send request
		var eDataResult = ProgramShop.getResultElement(xeDataQuery, this.space, this.DEBUG);

		//Gets TypicalSet vars:	
		var eTypicalSet = eDataResult.getElementsByTagName('TypicalSet')[0];
		var pageCount = parseInt(((eTypicalSet.getAttribute('count') - 1) / this.maxTuples) + 1, 10);
		var pageIndex = (pageCount == 0) ? 0 : pageIndex;
		var eTypicalTuples = XMLTools.getChildElements(eTypicalSet);
		
		return new TypicalSetObject(pattern, pageIndex, pageCount, eTypicalTuples);
	}	
	
	this.applyPattern = function(pattern) {
		this.panel.setTypicalSet(this.getTypicalSet(pattern != undefined ? pattern : this.panel.getPattern()));
		
		//Force list view (to switch if the view is in "tree" mode):
		this.panel.isListView = true;
		
		this.displayPanel();
		this.panel.setFocus();
	}

	this.gotoPrevPage = function() {
		this.gotoPage(this.panel.pageIndex - 1, 'back')
	}

	this.gotoNextPage = function() {
		this.gotoPage(this.panel.pageIndex + 1, 'next')
	}

	this.gotoPage = function(page, oFocus) {
		if(!page)
			page = $('goto_' + this.id).value;
		page = parseInt(page, 10);
		if(isNaN(page) || page < 1)
			page = 1;
		else if(page > this.panel.pageCount)
			page = this.panel.pageCount;
		
		this.panel.setTypicalSet(this.getTypicalSet(this.panel.getPattern(), page));
		
		this.displayPanel();
		if(!oFocus)
			oFocus = 'goto';
		this.panel.setFocus(oFocus)
	}

	this.setRow = function(tr) {
		this.panel.setRow(tr)
	}

	this.highlightRow = function() {
		if(this.panel)
			this.panel.listener_highlight();
	}

	
	this.getTreeRootHtmlContent = function() {
		var agent = "Manager.getAgentWithId(\'" + this.id + "\')";
		
    	var xeCommand = this.xeGetChildren(this.tablePSId, '', this.nbMaxChildrenPerPage, 0);
    	
    	var eWidgetResult = this.eWidgetResult(xeCommand);
    	var eChildrenList = eWidgetResult ? eWidgetResult.getElementsByTagName('ChildrenList')[0] : null;
    	var newContent = '';
    	
		newContent += eChildrenList ? this.getRecordChildrenHtml(agent, eChildrenList, true, id + '-root') : '';
 
    	return newContent;
    }
	
	
	this.getParentChildren = function(recordId, offset, actualInnerPage) {
		var doRefreshChildrenForNavigation = false;
		if (offset != undefined && actualInnerPage != undefined)
			doRefreshChildrenForNavigation = true;
		
		//Actual inner page update.
		if (doRefreshChildrenForNavigation && actualInnerPage && isNumeric(actualInnerPage) && this.actualInnerPage[new String(recordId)] != actualInnerPage)
			this.actualInnerPage[new String(recordId)] = actualInnerPage;
		
		var agent = "Manager.getAgentWithId(\'" + this.id + "\')";
		var queryOffset = offset && isNumeric(offset) ? offset : 0;
    	var xeCommand = this.xeGetChildren(this.tablePSId, recordId, this.nbMaxChildrenPerPage, queryOffset);
    	
    	var eWidgetResult = this.eWidgetResult(xeCommand);
    	var eChildrenList = eWidgetResult ? eWidgetResult.getElementsByTagName('ChildrenList')[0] : null;
    	
    	var actualContent = $j('#' + id + '-t' + this.tablePSId + '_r' + recordId).html();
    	
    	var newTreeviewUlTagId = id + '-treeview' + this.tablePSId + '_r' + recordId;
    	
    	var newContent = '';
    	
    	newContent += eChildrenList ? this.getRecordChildrenHtml(agent, eChildrenList, false, newTreeviewUlTagId) : '';
 
    	if (newContent.length > 0) {	    	
	    	//Update DOM by completing the element with its children or by replacing its children were we navigate in:
    		if (doRefreshChildrenForNavigation) {
    			$j('#'+newTreeviewUlTagId).fadeOut(300,
    					function () { 
    						$j(this).html(newContent);
    						$j(this).fadeIn(300);
    						cleanHtmlAndReInitTreeView(id, this.tablePSId, recordId, "#" + id + "-root");
    				    });  
    		} else {
    			$j('#' + id + '-t' + this.tablePSId + '_r' + recordId).html(actualContent + newContent);
    			cleanHtmlAndReInitTreeView(id, this.tablePSId, recordId, "#" + id + "-root");
    		}
    	}
    	
    	return eChildrenList;
    }
	    
	this.checkPageValueOK = function(recordId, objId, maxPages) {
		var value = new Number($j("#" + objId).attr("value"));
		var isEmpty = value.length == 0;
		var isOK = containsOnlyFigure($j("#" + objId).attr("value")) 
					&& !isEmpty
					&& value != this.actualInnerPage[new String(recordId)]
					&& value >= 1
					&& value <= maxPages;
		
		
		//Img ok:
		$j("#" + objId + "_OK").css("display", (isOK ? "inline" : "none") );
		//Img nok:
		$j("#" + objId + "_NOK").css("display", (!isOK ? "inline" : "none") );
		
		if (isOK) {
			$j("#" + objId + "_Bt").removeAttr("disabled");
			return true;
		} else {
			$j("#" + objId + "_Bt").attr("disabled", "disabled");
			return false;
		}		
	}

	
	this.gotoPageInChildrenInnerNavigation = function(eRecordId, pageValue) {
		this.actualInnerPage[new String(eRecordId)] = new Number(pageValue);
		var prevOffset = this.nbMaxChildrenPerPage * this.actualInnerPage[new String(eRecordId)] - this.nbMaxChildrenPerPage;
		this.getParentChildren(eRecordId, prevOffset, this.actualInnerPage[new String(eRecordId)]);	
	}
	
	this.getRecordChildrenHtml = function(agent, eChildrenList, isRoot, treeviewUlTagId) {
		var html = '';
		var pagesNb;
		var eRecordChildren = eChildrenList && eChildrenList.getElementsByTagName('RecordChild') ? eChildrenList.getElementsByTagName('RecordChild') : '';
		var eRecordId = eChildrenList && eChildrenList.getAttribute("recordId") ? eChildrenList.getAttribute("recordId") : 0;
    	var childrenListRealChildrenTotalCount = eChildrenList ? eChildrenList.getAttribute("realChildrenTotalCount") : 0;
    	var marginTop; //hack for IE7 and below.
    	
    	
    	
		if (eRecordChildren.length > 0) {
			
			html += '<ul id="' + treeviewUlTagId + '" ' + (isRoot ? ' class="treeview"' : '') + '>';
			
			if (childrenListRealChildrenTotalCount > this.nbMaxChildrenPerPage) {
				
				if (isRoot) {
					html += '<li id="' + id + '-t'+this.tablePSId+'_r0" style="background:none;"><ul id="' + id + '-treeview' + this.tablePSId + '_r0">';
				}
				
				if (this.actualInnerPage[new String(eRecordId)] == undefined)
					this.actualInnerPage[new String(eRecordId)] = 1;
				
				pagesNb = Math.ceil(childrenListRealChildrenTotalCount / this.nbMaxChildrenPerPage);
				
				html += '<li>';
				html += 	'<div class="treeviewInnerChildrenNav even">';
				
				if ($j.browser.msie && $j.browser.version < 8)
					marginTop = 'margin-top: -17px;';
				else
					marginTop = '';
				
	    		if (this.actualInnerPage[new String(eRecordId)] > 0) {
	    				var actualInnerPage = new Number(this.actualInnerPage[new String(eRecordId)] - 1);
						var prevOffset = this.nbMaxChildrenPerPage * actualInnerPage - this.nbMaxChildrenPerPage;
						
		    			html += 	'<div style="display: inline; float: left;">';
						html += 		'<input type="image" src="/rsrc/img/bullet_arrow_up.png" title="' + this.guiLabels.back + '" ';
						if (this.actualInnerPage[new String(eRecordId)] > 1)
							html += 		' onclick="' + agent + '.getParentChildren(' + eRecordId + ', ' + prevOffset + ', ' + actualInnerPage + ')"';
						else
							html += 		' disabled="disabled" style="visibility:hidden;"';
						html += ' />';
						
						html += 	'</div>';
	    			
	    		}
	    		
	    		html += 		'<span>&nbsp;' + this.guiLabels.gotoPage + '&nbsp;</span>';
	    		
	    		html += 		'<input type="text" style="width: 15px;" id="' + id + '-gotoInnerPage_' + eRecordId + '"';
	    		//Was good for FF (all in a "on key up" event) but not for IE:
				//html += ' onkeyup="var isOK = ' + agent +'.checkPageValueOK(this.id, ' + pagesNb + '); if (event.keyCode==13 && isOK) {' + agent + '.gotoPageInChildrenInnerNavigation(' + eRecordId + ', this.value); return false;}" />';
	    		//So, the checking is done when the key is up (the added char is displayed just between onKeyPress and onKeyUp events)
	    		//then a "global variable" is set to true or false and the onKeyPress event works only if it's true and if the Enter key is pressed:
	    		html += 		' onkeyup="this.isOK = ' + agent +'.checkPageValueOK(' + eRecordId + ', this.id, ' + pagesNb + ');" ';
	    		html += 		' onkeypress="if (event.keyCode==13 && this.isOK != undefined && this.isOK == true) { ' + agent + '.gotoPageInChildrenInnerNavigation(' + eRecordId + ', this.value); return false;}" />';
				
				html += 		'&nbsp;<input type="button" disabled="disabled" id="' + id + '-gotoInnerPage_' + eRecordId + '_Bt" value="ok" ';
				html += 		' onclick="' + agent + '.gotoPageInChildrenInnerNavigation(' + eRecordId + ', $j(\'#' + id + '-gotoInnerPage_' + eRecordId + '\').val())" />';
				
				html += 		'&nbsp;<img src="/rsrc/img/form_value_nok.png" alt="" style="width: 11px; height: 11px; display: none;" id="' + id + '-gotoInnerPage_' + eRecordId + '_NOK"/>';
	    		html += 		'<img src="/rsrc/img/form_value_ok.png" alt="" style="width: 11px; height: 11px; display: none;" id="' + id + '-gotoInnerPage_' + eRecordId + '_OK"/>';
				html += 		'&nbsp;';
				html += 		'<div style="text-align: right; float: right; ' + marginTop + '"><span>p.' + this.actualInnerPage[new String(eRecordId)] + '/' + pagesNb + '</span>';
				html += 			'<br /><span>' + childrenListRealChildrenTotalCount + ' ' + this.guiLabels.element + 's ' + this.guiLabels.inTotal + '</span>';
				html += 		'</div>';
				html += 	'</div>';//end of children nav
				html += '</li>';
			}
			
	    	for (var i = 0; i < eRecordChildren.length; i++) {
	    		var eRecordChild = eChildrenList.getElementsByTagName('RecordChild')[i];
	    		
	    		if (eRecordChild == undefined)
	    			return '';
	    		
	    		var childRecordHasChildren = eRecordChild.getAttribute('hasChildren');
	    		var childRecordId = eRecordChild.getAttribute('id');
	    		
	    		//If record has children, "even" class.
	    		var eClass = (childRecordHasChildren && Boolean(childRecordHasChildren) == true) ? "even" : "odd";
	    		//Value of RecordChild/PSValue/Txt :
	    		var tLabel;
	    		
	    		/*
        		for (var j=1; j <= this.typicalSet.typicalTuples.length; j++) {
        			if (j == childRecordId) {
        				tLabel = this.typicalSet.typicalTuples[j-1].str;
        				break;
        			}
        		}
        		*/
	    		
	    		//Value of RecordChild/PSValue/Txt :
	    		var eRecordChildPSValue = eRecordChild.getElementsByTagName("PSValue")[0];
	        	var eRecordChildTxtValue = eRecordChildPSValue.getElementsByTagName("Txt");
	        		
	        	tLabel = (eRecordChildTxtValue[0] && eRecordChildTxtValue[0].childNodes[0]) ? eRecordChildTxtValue[0].childNodes[0].data : '';
	    		
	        	        		
	    		var eTitle = (this.guiLabels.select + " " + tLabel).substr(0, 80);
				
	    		if (isRoot && childrenListRealChildrenTotalCount <= this.nbMaxChildrenPerPage) {
	    			var lastNodeClass = i == eRecordChildren.length - 1 ? ' class="last" ' : '';
	    			html += '<li id="' + id + '-t'+this.tablePSId+'_r'+childRecordId+'"'+lastNodeClass+'>';
	    		} else
	    			html += '<li id="' + id + '-t'+this.tablePSId+'_r'+childRecordId+'">';
	    		
	    		
	    		if (childRecordHasChildren && Boolean(childRecordHasChildren) == true) {
	    			html += '<div';
	    			html += ' id="expand_' + id + '-t'+this.tablePSId+'_r'+childRecordId+'"'; 
	    			html += ' onClick="' + agent + '.getParentChildren(' + childRecordId + ')"';
	    			//html += ' title="' + eTitle + '" tabIndex="1' + i + '"';
	    			html += ' title="' + eTitle + '" ';
	    			html += ' class="fakedHitarea"';
	    			html += '></div>';
	    		}
	    		 
	    		
	    		//If we come from a suggestion UI panel:
	    		var agentForSelectValue = "Manager.getAgentWithId(\'";
	    		agentForSelectValue += this.idFieldWithSuggestUI != undefined && this.idFieldWithSuggestUI.indexOf("sug_") != 1 ? this.idFieldWithSuggestUI : this.id;
	    		agentForSelectValue += "\')";
	    		
	    		var agentForClosePanel = "Manager.getAgentWithId(\'";
	    		agentForClosePanel += this.id;
	    		agentForClosePanel += "\')";
	    	
	    		
	    		tLabel = correctUnwantedTags(tLabel); //see utils.js
	    		
	    		html += 	'<a href="javascript:' + agentForSelectValue + '.select(' + childRecordId + (this.specialPluginFieldId != null ? ', \'' + this.specialPluginFieldId + '\'' : '') + '); ' + agentForClosePanel + '.closePanel()" title="' + eTitle + '" >';
	    		html += 		'<span class="' + eClass + '">';
	    		html += 			tLabel;
	    		html += 		'</span>';
	    		html += 	'</a>';
	    		html += '</li>';
	    	}
    
    		if (childrenListRealChildrenTotalCount > this.nbMaxChildrenPerPage ) {
    			var actualInnerPage = new Number(this.actualInnerPage[new String(eRecordId)] + 1);
				var nextOffset = this.nbMaxChildrenPerPage * actualInnerPage - this.nbMaxChildrenPerPage;
				
				html += '<li';
				if (isRoot)
					html += ' class="last"';
				html += '>';
				
				html += 	'<div class="treeviewInnerChildrenNav even">';				
				html += 		'<div style="display: inline; float: left;">';
				html += 			'<input type="image" src="/rsrc/img/bullet_arrow_down.png" title="' + this.guiLabels.next + '" ';
				if (this.actualInnerPage[new String(eRecordId)] < pagesNb)
					html += 			' onclick="' + agent + '.getParentChildren(' + eRecordId + ', ' + nextOffset + ', ' + actualInnerPage + ')"';
				else
					html += 			' disabled="disabled" style="visibility:hidden;"';
				html += 			' />';
				html +=		 	'</div>';
				
				
				html += 		'<span>&nbsp;' + this.guiLabels.gotoPage + '&nbsp;</span>';
	    		
	    		html += 		'<input type="text" style="width: 15px;" id="' + id + '-gotoInnerPage_bottom_' + eRecordId + '"';
	    		//Was good for FF (all in a "on key up" event) but not for IE:
				//html += ' onkeyup="var isOK = ' + agent +'.checkPageValueOK(this.id, ' + pagesNb + '); if (event.keyCode==13 && isOK) {' + agent + '.gotoPageInChildrenInnerNavigation(' + eRecordId + ', this.value); return false;}" />';
	    		//So, the checking is done when the key is up (the added char is displayed just between onKeyPress and onKeyUp events)
	    		//then a "global variable" is set to true or false and the onKeyPress event works only if it's true and if the Enter key is pressed:
	    		html += 		' onkeyup="this.isOK = ' + agent +'.checkPageValueOK(' + eRecordId + ', this.id, ' + pagesNb + ');" ';
	    		html += 		' onkeypress="if (event.keyCode==13 && this.isOK != undefined && this.isOK == true) { ' + agent + '.gotoPageInChildrenInnerNavigation(' + eRecordId + ', this.value); return false;}" />';
				
				html += 		'&nbsp;<input type="button" disabled="disabled" id="' + id + '-gotoInnerPage_bottom_' + eRecordId + '_Bt" value="ok" ';
				html += 		' onclick="' + agent + '.gotoPageInChildrenInnerNavigation(' + eRecordId + ', $j(\'#' + id + '-gotoInnerPage_bottom_' + eRecordId + '\').val())" />';
				
				html += 		'&nbsp;<img src="/rsrc/img/form_value_nok.png" alt="" style="width: 11px; height: 11px; display: none;" id="' + id + '-gotoInnerPage_bottom_' + eRecordId + '_NOK"/>';
	    		html += 		'<img src="/rsrc/img/form_value_ok.png" alt="" style="width: 11px; height: 11px; display: none;" id="' + id + '-gotoInnerPage_bottom_' + eRecordId + '_OK"/>';
				html += 		'&nbsp;';
				html += 		'<div style="text-align: right; float: right; ' + marginTop + '"><span>p.' + this.actualInnerPage[new String(eRecordId)] + '/' + pagesNb + '</span>';
				html += 			'<br /><span>' + childrenListRealChildrenTotalCount + ' ' + this.guiLabels.element + 's ' + this.guiLabels.inTotal + '</span>';
				html += 		'</div>';
				
				html += 	'</div>'; //end of children nav
				html += '</li>';
				
				if (isRoot) {
	    			html += '</ul></li>';
	    		}
			}   
	    	
    		
    		html += '</ul>';
    		

    	}
		
		
		
		return html;
	}
	
	
	this.select = function(recId, specialPluginFieldId) {
		
		if (specialPluginFieldId != undefined && specialPluginFieldId != null && specialPluginFieldId.length > 0) {
			var monObjet = specialPluginFieldId.indexOf("#") == -1 ? $j("#"+specialPluginFieldId) : $j(specialPluginFieldId);
			monObjet.val(recId);
		}
		
		var xmlValue = '<NullValue/>';
		if(recId && recId != '') {
			switch(this.fieldType) {
			case 'FKey':
				xmlValue = '<FKey recId="' + recId + '"/>';
				break;
			case 'Parent':
				xmlValue = '<Parent recId="' + recId + '"/>';
				break;				
			case 'Block':
				xmlValue = '<Block recId="' + recId + '"/>';
				break;				
			case 'FKeySet':
				if(this.recId || this.mmrId) {
					Manager.getAgent('link_' + this.fieldRef).addFKey(recId);
					this.closePanel();
					return;
				} else
					xmlValue = '<FKey recId="' + recId + '"/>';
				break;
			case 'BlockSet':
				if(this.recId || this.mmrId) {
					Manager.getAgent('link_' + this.fieldRef).addBlock(recId);
					this.closePanel();
					return;
				} else
					xmlValue = '<Block recId="' + recId + '"/>';
				break;
			}
		}
		this.submitValue(xmlValue, false);
		
	}

	this.deleteItem = function() {
		this.submitValue('<NullValue/>');
	}

	this.toString = function() {
		return 'LKTableAgent: {id: ' + this.id + '}';
	}
}

LKTableAgent.prototype = new LoginPanelAgent();



function cleanHtmlAndReInitTreeView(id, tablePSId, recordId, whichOne) {
	//Cleaning "expand children" SPAN tag which has just been clicked, launching this function :
 	$j('#expand_' + id + '-t' + tablePSId + '_r' + recordId).remove();
	
 	//Cleaning treeview action DIV tags before ...
 	$j("div[class*='hitarea']").remove();
	
	// ... re-initializing the root:
	initTreeView(whichOne);	//see utils.js
	
	if (recordId == 0) {
		//Hide/remove what is necessary:
		var firstRootLi = $j("li[id ^= '" + id + "'][id $= '_r0']");
		$j(firstRootLi).css("background", "none");
		var firstRootHitArea = $j(firstRootLi).children("div:first-child");
		//$j(firstRootHitArea).removeClass("hitarea collapsable-hitarea lastCollapsable-hitarea");
		$j(firstRootHitArea).remove();	
	}
}


/**
 * @constructor
 * @param {Array}
 *            eTypicalTuples TypicalTupleObject array
 */
function TypicalSetObject(pattern, pageIndex, pageCount, eTypicalTuples) {
	this.pattern = pattern;
	this.pageIndex = pageIndex;
	this.pageCount = pageCount;
	
	this.typicalTuples = [];
	for( var i = 0; i < eTypicalTuples.length; i++) {
		this.typicalTuples[i] = new TypicalTupleObject(eTypicalTuples[i])
	}
}


/**
 * @constructor
 * @param {Element} eTypicalTuple TypicalTuple element
 */
function TypicalTupleObject(eTypicalTuple) {
	this.id = eTypicalTuple.getAttribute('id');
	
	//this.str = (eTypicalTuple.firstChild) ? eTypicalTuple.firstChild.data : '';
	this.str = (eTypicalTuple.childNodes[0]) ? eTypicalTuple.childNodes[0].data : '';
	
	//Just above: works for all web browser :
	//"firstChild" is known by FireFox, IE7, Safari, ... but no more by IE8, so we use a more commun method.
		
	this.str = correctUnwantedTags(this.str); //see utils.js
	
	this.toString = function() {
		return this.str;
	}
}

/**
 * @param {Array<Element<FormatValue>>} Ordered array of table field labels.
 * @param {Array<Integer>} sigIndices Indices of significant values, in given order.
 * @param {String} sigSep String to separate significant values.
 */
function LKTablePanel(agentId, fieldLabel, guiLabels, colorIconDir, isListView, typicalSet, newRecordHref, isHierarchical, idFieldWithSuggestUI, specialPluginFieldId, firstPageCount) {
	
	this.agentId = agentId;
	this.guiLabels = guiLabels;
	this.fieldLabel = fieldLabel;
	this.colorIconDir = colorIconDir;
	
	this.isListView = isListView;
	this.newRecordHref = newRecordHref;
	this.isHierarchical = isHierarchical;
	this.idFieldWithSuggestUI = idFieldWithSuggestUI;
	this.specialPluginFieldId = specialPluginFieldId != undefined && specialPluginFieldId.length > 0 ? specialPluginFieldId : null;
	
	this.firstPageCount = firstPageCount;
	
	this.pageIndex;
	this.pageCount;
	this.pattern = '';
	this.typicalTuples;
	
	this.setTypicalSet = function(typicalSet) {
		this.pageIndex = typicalSet.pageIndex;
		this.pageCount = typicalSet.pageCount;
		this.pattern = (typicalSet.pattern) ? typicalSet.pattern : '';
		this.typicalTuples = typicalSet.typicalTuples;
	}
	this.setTypicalSet(typicalSet);


	this.getPattern = function() {
		return $('dicFilter_' + this.agentId).value;
	}
	
	this.setPattern = function(newPatternValue) {
		 $('dicFilter_' + this.agentId).value = newPatternValue;
	}

	/**
	 * @param {String} oRef "back" | "next" | "goto" | "vtBut" | undefined
	 */
	this.setFocus = function(oRef) {
		var id = this.agentId;
		var obj = (oRef) ? $(oRef + '_' + id) : null;
		if(!obj) {
			if(oRef == 'back')
				obj = $('next_' + id);
			else if(oRef == 'next')
				obj = $('back_' + id);
		}
		if(!obj)
			obj = $('dicFilter_' + id);
		if(!obj)
			obj = $('close_' + id);
		if(obj)
			obj.focus()
	}

	this.highlightedRow = null;
	this.rowToHighlight = null;

	this.initRowHighlighter = function() {
		this.listener_highlight()
	}

	this.listener_highlight = function() {
		
		if(this.isListView)
			return;
		
		if(this.highlightedRow != this.rowToHighlight) {
			if(this.highlightedRow != null)
				this.highlightedRow.className = this.highlightedRow.className.split('_')[0];
			if(this.rowToHighlight != null)
				this.rowToHighlight.className += '_mouseOver';
			this.highlightedRow = this.rowToHighlight
		}
		setTimeout("Manager.getAgentWithId(\'" + this.agentId + "\').highlightRow()", 50);
	}

	this.setRow = function(tr) { // tr is a TR element, called by onMouseOver event
		this.rowToHighlight = tr;
	}

	this.toHTML = function() {
		var agent = "Manager.getAgentWithId(\'" + this.agentId + "\')";

		var vtButName = (this.isListView) ? 'bt_treeView.gif' : 'bt_listView.gif';
		var vtButAlt = (this.isListView) ? this.guiLabels.showValuesInTreeview : this.guiLabels.showValuesInListview;
		
		var html = '<table class="wide ptable">' + '<tr>' + '<td class="ptitbar" onMouseDown="DragAndDrop.start(this,event); return false">' + '<table class="wide" summary="' + this.guiLabels.titleBar + '">' + '<tr>' + '<td>' + this.fieldLabel + '</td>' + '<td align="right" nowrap valign="top">';

		// new record link
		if(this.newRecordHref) {
			var fieldRef = this.agentId.replace(/^[^_]+_/, '');
			html += '<span ' + (this.isListView ? 'tabIndex="1" ' : '') + ' id="popup_' + fieldRef + '" onclick="Manager.openPopup(this,\'' + this.newRecordHref + '\'); return false;" class="new"><img src="' + this.colorIconDir + 'bt_newDoc.gif" class="bt11 m04" />' + this.guiLabels.newRecord + '</span>';
		} else if (this.idFieldWithSuggestUI && this.idFieldWithSuggestUI.indexOf("Parent_") == -1) {
			var fieldRef = this.idFieldWithSuggestUI.replace(/^[^_]+_/, '');
			html += '<span  ' + (this.isListView ? 'tabIndex="1" ' : '') + ' onclick=\'$j("#popup_' + fieldRef + '").click(); return false;\' class="new"><img src="' + this.colorIconDir + 'bt_newDoc.gif" class="bt11 m04" />' + this.guiLabels.newRecord + '</span>';
		}

		if (this.isHierarchical)
			html += '<input type="image" onclick="' + agent + '.toggleViewType(); return false" ' + 'src="' + this.colorIconDir + vtButName + '" class="bt11 m04" ' + 'alt="' + vtButAlt + '" title="' + vtButAlt + '" ' + (this.isListView ? 'tabIndex="2" ' : '') + '  id="vtBut_' + this.agentId + '">';


		html += '<input type="image" onclick="' + agent + '.closePanel(); return false" ' + 'src="' + this.colorIconDir + 'bt_close_11.gif" class="bt11" ' + 'alt="' + this.guiLabels.close + '" title="' + this.guiLabels.close + '"  ' + (this.isListView ? 'tabIndex="3" ' : '') + '  id="close_' + this.agentId + '" /></td>' + '</tr>' + '</table>' + '</td>' + '</tr>';

		//Search input text + Page navigation if more than one:
		if(Number(this.pageCount) > 1 || this.pattern.length == 0 || (Number(this.firstPageCount) > 1 && this.pattern.length > 0)) {
			html += '<tr>' + '<td>' + '<div class="dicNav">' + '<table class="wide">' + '<tr>' + '<td nowrap>' + this.guiLabels.containing + '&nbsp;<input type="text" id="dicFilter_' + this.agentId + '" ' + 'onkeypress="if (event.keyCode==13) {' + agent + '.applyPattern(); return false}" size="12" ' + 'value="' + this.pattern + '"' + '  ' + (this.isListView ? 'tabIndex="4" ' : '') + '  />&nbsp;' + '<input type="image" src="/rsrc/img/bt_right.gif" class="btNav"  ' + (this.isListView ? 'tabIndex="5" ' : '') + '  ' + 'onClick="' + agent + '.applyPattern(); return false" alt="' + this.guiLabels.filter + '" title="' + this.guiLabels.filter + '" />' + '</td>';
			
			//Not necessary for a Tree View:
			if (this.isListView) {
				if(this.pageCount > 1) {
					html += '<td nowrap align="center">';
					
					if(this.pageIndex > 1)
						html += '<input type="image" src="/rsrc/img/bt_left.gif" ' + 'class="btNav" onClick="' + agent + '.gotoPrevPage(); return false" ' + 'alt="' + this.guiLabels.back + '" id="back_' + this.agentId + '" tabIndex="6" />&nbsp;';
					
					html += this.guiLabels.page + '&nbsp;' + this.pageIndex + '&nbsp;' + this.guiLabels.of + '&nbsp;' + this.pageCount;
					
					if(this.pageIndex < this.pageCount)
						html += '&nbsp;<input type="image" ' + 'src="/rsrc/img/bt_right.gif" class="btNav" ' + 'onClick="' + agent + '.gotoNextPage(); return false" ' + 'alt="' + this.guiLabels.next + '" id="next_' + this.agentId + '" tabIndex="7" />';
					
					html += '</td>';
				}
				if(this.pageCount > 2)
					html += '<td nowrap align="right">' + this.guiLabels.gotoPage + '&nbsp;<input type="text" id="goto_' + this.agentId + '"  ' + (this.isListView ? 'tabIndex="8" ' : '') + '  ' + 'onKeyPress="if (event.keyCode==13) {' + agent + '.gotoPage(); return false}" ' + 'size="3" />&nbsp;' + '<input type="image" src="/rsrc/img/bt_right.gif" class="btNav"  ' + (this.isListView ? 'tabIndex="9" ' : '') + '  ' + 'onClick="' + agent + '.gotoPage(); return false" alt="' + this.guiLabels.gotoPage + '" />' + '</td>';
			}
			html += '</tr>' + '</table>' + '</div>' + '</td>' + '</tr>';
		}
		html += '<tr>';
		
		//If we come from a suggestion UI panel:
		var agentForSelectValue = "Manager.getAgentWithId(\'";
		agentForSelectValue += this.idFieldWithSuggestUI != undefined && this.idFieldWithSuggestUI.indexOf("sug_") != 1 ? this.idFieldWithSuggestUI : this.agentId;
		agentForSelectValue += "\')";
		
		
		var agentForClosePanel = "Manager.getAgentWithId(\'";
		agentForClosePanel += this.agentId;
		agentForClosePanel += "\')";
		
		if(this.pageCount > 0) {
			html += '<td class="dictionary">';
			
			if (!this.isListView) {
				html += Manager.getAgentWithId(this.agentId).getTreeRootHtmlContent();
			} else {
				
	    		
	    		
				for( var i = 0; i < this.typicalTuples.length; i++) {
					var eClass = (i % 2 != 0) ? "odd" : "even";
					
					var tLabel = this.typicalTuples[i].str;
					
					var eTitle = (this.guiLabels.select + " " + tLabel).substr(0, 80);
					html += '<a href="javascript:' + agentForSelectValue + '.select(' + this.typicalTuples[i].id + (this.specialPluginFieldId != null ? ', \'' + this.specialPluginFieldId + '\'' : '') +'); ' + agentForClosePanel + '.closePanel()" class="' + eClass + '" title="' + eTitle + '"  ' + (this.isListView ? 'tabIndex="1' + i +'" ' : '') + ' >' + tLabel + '</a>';
				}				
			}
			
			html += '</td>'
		} else
			html += '<td class="noEntries">' + this.guiLabels.noResults + '</td>';
		
		html += '</tr>' + '<tr>' + '<td align="center" class="pbuts">'
		html += '<div class="perror"';
		
		if(!this.errorMsg) {
			html += ' style="display: none">';
		} else {
			html += ' style="display: block">';
		}
		html += this.errorMsg;
		html +='</div>';
		html += '<table summary="' + this.guiLabels.actionButtons + '">';
		
		html += '<tr><td><button onClick="' + agentForSelectValue /* agent */ + '.deleteItem(); return false"  ' + (this.isListView ? 'tabIndex="998" ' : '') + ' >' + this.guiLabels.Delete + '</button></td>' + '</tr>' + '</table>';
		
		html += '</td>' + '</tr>' + '</table>';

		return html;
	}
}