//Copyright (C) 2008 Ivanov I.M. irigm@mail.ru +77051809750
//For find non english chars: [^\x00-\x7F]+

function callWindow(uid,id,i)
{	SRec_mas[uid].callWindow(id,i);
}

function setFilterVal(uid,id,c,p)
{	SRec_mas[uid].setFilterVal(id,c,p);
}

var SRec_mas = new Array(); //List of all objects "EdtRec" (then something better to think of)

class SRec
{
	constructor()
	{
		this.win=null;
		this.rwin=null;

		this.f_State='0'; //"0" - editing, "1" - selecting a single entry, "2" - selecting a multiple record
		this.f_PropName=""; //If the mode f_State is 1 then f_PropName saves the name of the field for which the data is intended
		this.f_TypeName=""; //the name of the displayed object (type-> n attribute)
		//this.record_id=-1; //from here the form of editing takes the values id after its loading
		this.f_Settings=""; //XML that is superimposed on the current node Metadata
		this.f_pI=0; this.f_pU=0; this.f_pD=0; this.f_pS=0; //rights
		this.nodeMetadata=null; //accepted metadata
		this.nodeMetadataObjList=null;
		this.f_nodeData=null; //received data, hidden fields
		this.masCT=new Array();//parameter table for cells
		this.masCL=new Array();//node table column
		this.masVis=new Array(); //Whether to display a column
		this.masChBox=new Array(); //Checkboxes
		this.xmldoc=null; //accepted XML document (for CDATA creation)
		this.pagepos=0; //current data page

		this.pBarCnt=0; //Progress bar
		this.pBarDiv=null; //Progress bar

		this.name="";

		this.uid=getUID();
		this.request = new TRequest(this);
		SRec_mas[this.uid]=this;
	}

	applyReq(req,fn,node,xmldoc)
	{
		//alert(getXMLNodeSerialisation(node));
		this.hideProgressBar();

		this.xmldoc=node.ownerDocument; //xmldoc;
		if (fn==-1) //Information menu
		{
			alert(findFirstNode(node,'#cdata-section').nodeValue);
		}else
		if (fn==0)
		{
			//alert(getXMLNodeSerialisation(node));
			this.setMetadata(node);
			this.updateSize();
		}else
		if (fn==11) //Update record after editing, 1 entry has come.
		{
			this.updateRows(node);
		}else
		if (fn==3) //Information which record or records were deleted.
		{
			this.ApplyDelRec(node);
		}else
		if (fn==4) //Data after the selection of records, replacement of existing ones.
		{
			this.insertRows(node,true);
		}else
		if (fn==6) //Fill in the drop-down lists.
		{
			this.setDataSelect(node);
		}else
		if (fn==8) //There was a link to the report.
		{
			if(this.rwin!=null)
			{
				this.rwin.hideProgressBar();
				this.rwin.setContent('<table border="0px" style="width: 100%; height: 100%; background-color: #f1f1f1;"><tr><td align="center"><a href="'+findFirstNode(node,'#cdata-section').nodeValue+'">'+_('Download_report')+': "'+this.win.getCaption().innerHTML+'".</a></td></tr></table>');
			}
		}else
			alert("Unknown function! fn=\""+fn+"\"" );
	}

	//Edit the GUI filter from the xml string.
	setGUISettings(xmlStr)
	{
		if ((xmlStr!=null)&&(xmlStr!=""))
		{
			xmlDOC=CreateXMLDOC(xmlStr);
			//let nPFilter=findFirstNode(xmlDOC,"filter")
			let nPFilter=findNodeOnPath(xmlDOC.documentElement,"type/objects-list/filter");
			nPColumn=nPFilter.firstChild;
			while (nPColumn != null)
			{
				if(nPColumn.nodeName=="column")
				{
					let prop=document.getElementById('filter_'+this.uid+'_'+nPColumn.getAttribute("n"));
					if(prop!==null) prop.value=getCdata(nPColumn).nodeValue;

					/*let np=nPColumn.getAttribute("n")
					let vp=nPColumn.getAttribute("visible")
					let cdata=getCdata(nPColumn).nodeValue

					columnNode=findNodeOnAttribute(nodeFilter, 'column', 'n', np)
					if(columnNode!=null)
					{
						if (vp!=null) columnNode.setAttribute("visible",vp)
						getCdata(columnNode).nodeValue=cdata
					}*/
				}
				nPColumn=nPColumn.nextSibling;
			}
			let btn=document.getElementById("btnfilter_"+this.uid);
			if(btn!==null) btn.focus();
		}
	}

	//Apply the settings to the current node "type-> n" must match.
	setXMLSettings(xml)
	{
		//Apply the parameters to the current XML filter if there are filter settings in the parent window!
		if(xml===null || typeof(xml) == "undefined") return;

		if(typeof(xml) == "string"){
			if(xml!="")
			{
				applyNodeToNode(findFirstNodeOnAttribute(CreateXMLDOC(xml), "type", "n", this.f_TypeName), findFirstNodeOnAttribute(this.nodeMetadata, "type", "n", this.f_TypeName), "n");
			}
		}else
		if(typeof(xml) == "object"){
			if(xml.getAttribute("n")==this.f_TypeName)
			{
				applyNodeToNode(xml, findFirstNodeOnAttribute(this.nodeMetadata, "type", "n", this.f_TypeName), "n");
			}
		}
	}

	create(htmlElement)
	{
		let str='\
			<div id="eDiv'+this.uid+'" style="width: 100%; height: 100%; position: relative;">\
			<table class="SFilter" border="0" cellspacing="0" cellpadding="0" style="width: 100%; height: 100%;"><tr><td>\
				<table id="idfilter'+this.uid+'" cellspacing="2" cellpadding="0" style="border: 1px solid rgb(99, 99, 99); table-layout: auto;" width="100%" bgcolor="'+g_rowColor2+'">\
					<caption></caption><thead></thead><tbody></tbody>\
				</table>\
			</td></tr><tr><td>\
				<table style="width:100%;"><tr><td><img src="../resources/metadata/dbms/images/rplus.png" alt="add" id="SRec_Add_'+this.uid+'" title="'+_('Add_record')+'" border="0" style="cursor: pointer;"/></td>\
					<td><img src="../resources/metadata/dbms/images/rdel.png" alt="del" id="SRec_Del_'+this.uid+'" title="'+_('Delete_record')+'" border="0" style="cursor: pointer;"/></td>\
					<td><img src="../resources/metadata/dbms/images/excel.png" alt="excel" id="SRec_Exc_'+this.uid+'" title="'+_('Export_to_Excel')+'" border="0" style="cursor: pointer;"/></td>\
					<td style="width: 99%;">&nbsp;</td>\
					<td><img src="../resources/metadata/dbms/images/refresh.png" alt="refresh" id="SRec_Rfr_'+this.uid+'" title="'+_('Update')+'" border="0" style="cursor: pointer;"/></td></tr>\
				</table>\
			</td></tr><tr><td id="tblContainer_'+this.uid+'" style="vertical-align:top; overflow:hidden; width:100%; height:100%; text-align:center;">\
					<div id="tblSContainer_'+this.uid+'" style="position: absolute; overflow:scroll; width: 400px; height: 400px;">\
						<table id="thetable'+this.uid+'" class="SShow">\
							<caption></caption>\
							<thead><tr><th></th></tr></thead>\
							<tbody><tr><td></td></tr></tbody>\
						</table>\
					</div>\
			</td></tr><tr><td>\
				<center><table id="pages'+this.uid+'"><tbody><tr><td>&nbsp;</td></tr></tbody></table></center>\
			</td></tr></table>\
			</div>\
		';

		if(htmlElement==null || typeof(htmlElement) == "undefined")
		{
			this.win=new TWin();
			this.win.BuildGUI(pageX-10,pageY-10);
			this.win.setHeight(400);
			//this.win.setLeftTop()

			this.win.setContent(str);
			this.win.obj=this;

			this.win.addResizeListener(function(obj){return function(){obj.updateSize();}}(this));

		}else{
			htmlElement.innerHTML=str;
		}

		document.getElementById('SRec_Add_'+this.uid).onclick=function(thiz){return function(){thiz.insertRecord();};}(this);
		document.getElementById('SRec_Del_'+this.uid).onclick=function(thiz){return function(){thiz.deleteRecord();};}(this);
		document.getElementById('SRec_Exc_'+this.uid).onclick=function(thiz){return function(){thiz.showreport('xls');};}(this);
		document.getElementById('SRec_Rfr_'+this.uid).onclick=function(thiz){return function(){thiz.appendFilter(); thiz.sendFilter(-1,0);};}(this);
	}

	//Update dimensions of the elements (the main table in absolute coordinates).
	updateSize()
	{
		let dv1=document.getElementById("tblSContainer_"+this.uid);
		let dv2=document.getElementById("tblContainer_"+this.uid);
		if(dv1!=null && dv2!=null)
		{
			dv1.style.width = dv2.offsetWidth+"px";
			dv1.style.height = dv2.offsetHeight+"px";
		}
	}

	//Show progress bar
	showProgressBar()
	{
		this.pBarCnt++;
		if(this.pBarDiv==null)
		{
			this.pBarDiv=document.createElement('div');
			this.pBarDiv.style.cssText='position: absolute; left: 0px; top: 0px; z-index: 1; background-color: rgba(0,0,0,0.5); width:100%; height: 100%;';
			this.pBarDiv.innerHTML='<table width="100%" height="100%" border="0" cellpadding="0" cellspacing="0"><tr><td align="center" style="vertical-align: middle;"><img src="../resources/metadata/dbms/images/loading.gif" alt=""></td></tr></table>';

			let eDiv=document.getElementById('eDiv'+this.uid);
			eDiv.appendChild(this.pBarDiv);
		}
	}

	//Hide progress bar
	hideProgressBar()
	{
		this.pBarCnt--;
		if(this.pBarCnt<=0)
		{
			if(this.pBarDiv!==null) deleteHTML(this.pBarDiv);
			this.pBarCnt=0;
			this.pBarDiv=null;
		}
	}

	//Function to fill the drop-down lists (here it is necessary to ensure that everywhere there is a "var" in front of the variables).
	setDataSelect(node)
	{
		//alert("setDataSelect = " + getXMLNodeSerialisation(node));

		let nodeType,prop_id,prop,option,nodeProp,id,value,cdataNode;
		nodeType=findFirstNode(node, 'type');
		prop_id=nodeType.getAttribute("pn");//Field name
		prop=document.getElementById('filter_'+this.uid+'_'+prop_id);

		//Determine what type of node was a drop-down list or a field with a button.
		let selector=null;
		let nodeFilter=findNodeOnPath(this.nodeMetadata,"type/objects-list/filter");
		let nodeCur=findNodeOnAttribute(nodeFilter, 'column', 'n', prop_id);
		if(nodeCur!=null) selector=nodeCur.getAttribute("selector");

		//alert("nodeCur = " + getXMLNodeSerialisation(nodeCur));

		/*nodeCur=nodeFilter.firstChild
		while(nodeCur!=null)
		{
			if((nodeCur.nodeName=="column")&&(nodeCur.getAttribute("n")==prop_id))
			{
				selector=nodeCur.getAttribute("selector");
			}
			nodeCur=nodeCur.nextSibling;
		}*/

		if(selector==="combo") //if the drop-down list
		{
			prop.innerHTML = "";

			//Select the value for this list
			let val=null;
			let nodeFilter=findNodeOnPath(this.nodeMetadata,"type/objects-list/filter");
			let nodeCol=nodeFilter.firstChild;
			while(nodeCol!=null)
			{
				if((nodeCol.nodeName==="column")&&(nodeCol.getAttribute("n")==prop_id))
				{
					val=getCdataValue(nodeCol);
					break;
				}
				nodeCol=nodeCol.nextSibling;
			}

			//The first line in the selection is NULL value = -1.
			option = document.createElement('option');
			option.setAttribute("value","");
			option.appendChild( document.createTextNode(""));
			option.selected = true;
			prop.appendChild( option );
			if(prop!=null)
			{
				nodeProp=nodeType.firstChild;
				while (nodeProp!=null)
				{
					if (nodeProp.nodeName=="record")
					{
						id=nodeProp.getAttribute("id");
						value="";
						cdataNode = nodeProp.firstChild
						while (cdataNode!=null)
						{
							if (cdataNode.nodeName=="#cdata-section")
							{
								value+=cdataNode.nodeValue+" ";
								//break;
							}
							cdataNode = cdataNode.nextSibling;
						}
						option = document.createElement('option');
						option.setAttribute("value",id);
						if (id==val) option.selected=true;
						option.appendChild(document.createTextNode(value));
						prop.appendChild( option );
					}
					nodeProp=nodeProp.nextSibling;
				}
				prop.style.cssText="width: 100%;"; //fuck IE
			}
		}else //if the field with the button
		{
			//count the number of values
			let count=0;
			nodeProp=nodeType.firstChild;
			while (nodeProp!=null)
			{	if (nodeProp.nodeName=="record")
					count++;
				nodeProp=nodeProp.nextSibling;
			}
			if(count==0)
			{
				alert(_("No_results_were_found_for_your_search"));
			}else
			if(count==1) //fill without window
			{
				nodeProp=findFirstNode(nodeType, 'record');
				id=nodeProp.getAttribute("id");
				value=findFirstNode(nodeProp, '#cdata-section').nodeValue;
				prop.value=id;
				let propvis=document.getElementById('filter_'+this.uid+'_'+prop_id+'_visible');
				propvis.value=value;
				propvis.select();
			}else
			if(count>1) //The item selection window is displayed.
			{
				let htmlString='<table width="100%" bgcolor="'+g_rowColor2+'">';
				nodeProp=nodeType.firstChild
				i=0;
				while (nodeProp!=null)
				{
					if (nodeProp.nodeName=="record")
					{
					    let bgColor='#e0e0e0';
						if (i%2==0) bgColor='white';
						id=nodeProp.getAttribute("id");
						value=getCdataValue(nodeProp);
						value=value.replace(/"/g, "&quot;"); value=value.replace(/'/g, "\\'");
						htmlString+='<tr><td bgColor="'+bgColor+'" onClick="setFilterVal('+this.uid+',\''+id+'\',\''+value+'\',\''+prop_id+'\')" style="cursor: pointer;">'+findFirstNode(nodeProp, '#cdata-section').nodeValue+'&nbsp;</td></tr>'+"\n";
						i++;
					}
					nodeProp=nodeProp.nextSibling;
				}
				htmlString+='</table>';

				let win=new TWin();
				win.BuildGUI(pageX-10,pageY-10);
				win.setHeight(400);
				win.setContent(htmlString);
				win.setCaption(document.createTextNode(_('Selection')));
				win.setParent(this.win);
				//win.obj=this
			}
		}
	};

	//Set the value for the object filter with a text field search
	setFilterVal(id,caption,prop_id)
	{
		let prop=document.getElementById('filter_'+this.uid+'_'+prop_id);
		let propvis=document.getElementById('filter_'+this.uid+'_'+prop_id+'_visible');
		if ((prop!=null)&&(propvis!=null))
		{
			prop.value=id;
			propvis.value=caption;
			propvis.select();
			this.appendFilter(); //We move the values from the HTML fields to XML.
			this.sendFilter(-1,0);
		}
	}

	//we pass the id to the object filter prop_id - the name of the filter
	setFilterObject(TypeName, prop_id, id)
	{
		let node=findFirstNodeOnAttribute(this.nodeMetadata,'column','n',prop_id);
		if(node!=null)
		{
			let name=node.getAttribute("FieldCaption");
			getCdata(node).nodeValue=id;
			//we request data from the server to fill in the comments on the record id
			let prop=document.getElementById('filter_'+this.uid+'_'+prop_id);
			if(prop!=null) prop.value=id;
			//request comment on the id of the record from the server
			if(this.request.callServer(ScriptName,'<?xml version="1.0" encoding="utf-8"?><metadata fn="6"><type n="'+TypeName+'" c="'+name+'" pn="'+prop_id+'" fn="'+name+'"><objects-list><filter><column n="id"><![CDATA['+id+']]></column></filter></objects-list></type></metadata>',true))
			{
				this.showProgressBar();
			}
		}else
		{
			alert('Filter "'+prop_id+'" not find!');
		}
	}

	//The function to collect data from HTML fields in XML
	appendFilter()
	{
		let nodeType=findFirstNode(this.nodeMetadata, "type");
		let nodeFilter=findNodeOnPath(nodeType,"objects-list/filter");
		if (nodeFilter!=null)
		{
			let columnNode=nodeFilter.firstChild;
			while (columnNode != null)
			{
				if (columnNode.nodeName=="column")
				{
					let value = '';
					let input = document.getElementById('filter_'+this.uid+'_'+columnNode.getAttribute("n"));
					if(input!=null) value=input.value;

					//'2016-02-27 00:00:00'
					if(columnNode.getAttribute("vt")=="dateTime" || columnNode.getAttribute("vt")=="date") //If field is "dateTime" then transmit in UnixTime format in second
					{
						if(value!=""){
							let date = new Date(value.replace(/-/g, "/"));
							value=date.getTime()/1000;// - date.getTimezoneOffset()*60;
							if(isNaN(value)) value='';
						}
					}
					getCdata(columnNode).nodeValue=value; //TODO do check for data type
				}
				columnNode = columnNode.nextSibling;
			}
		}
		//alert(getXMLNodeSerialisation(this.nodeMetadata));
	}

	/** Function to send filter data to the server
	 * id - id of record -1 then all
	 * page - result page number
	*/
	sendFilter(id,page)
	{
		let nodeType=findFirstNode(this.nodeMetadata, "type");
		let nodeObjectsList=findFirstNode(nodeType, "objects-list");
		let nodeFilter=findNodeOnPath(nodeType,"objects-list/filter");
		let typename=nodeType.getAttribute("n");
		let xs='';
		xs+='<?xml version="1.0" encoding="utf-8"?>\n';
		if(id!=-1) xs+='<metadata fn="11">\n';
		else xs+='<metadata fn="4">\n';
		xs+='	<type n="'+typename+'" pp="'+page+'"><objects-list order="'+nodeObjectsList.getAttribute('order')+'"><filter>';
		//Opera does not serialize CDATA, so we form the filter manually
		let nextNode=nodeFilter.firstChild;
		while(nextNode!=null)
		{
			if(nextNode.nodeName=="column")
			{
				if(nextNode.getAttribute("n")=="id" && id!=-1)
				{
					xs+='<column n="'+nextNode.getAttribute("n")+'" vt="'+nextNode.getAttribute("vt")+'" size="'+nextNode.getAttribute("size")+'">';
					xs+='<![CDATA['+id+']]>';
					xs+='</column>\n';
				}else
				{
					xs+='<column n="'+nextNode.getAttribute("n")+'" vt="'+nextNode.getAttribute("vt")+'" size="'+nextNode.getAttribute("size")+'">';
					xs+='<![CDATA['+getCdataValue(nextNode)+']]>';
					xs+='</column>\n';
				}
			}
			nextNode=nextNode.nextSibling;
		}
		xs+='</filter></objects-list></type>\n';
		xs+='</metadata>';

		//alert(xs);

		if(this.request.callServer(ScriptName,xs))
		{
			this.showProgressBar();
		}
	}

	//Get metadata records and break them into global variables.
	setMetadata(node)
	{
		this.nodeMetadata=node;
		this.setXMLSettings(this.f_Settings); //Appending settings to nodeMetadata

		//Create GUI filter
		let td,tr,td1,td2;
		let nodeFilter=null;
		let tablefilter=document.getElementById('idfilter'+this.uid);
		if (tablefilter.tBodies==null) alert('tablefilter=null');
		let nodeType=findFirstNode(node, "type");
		this.f_pI=nodeType.getAttribute("ins");//access rights
		this.f_pU=nodeType.getAttribute("upd");
		this.f_pD=nodeType.getAttribute("del");
		this.f_pS=nodeType.getAttribute("sel");
		this.f_TypeName = nodeType.getAttribute("n");
		this.name=this.f_TypeName;
		let rep=nodeType.getAttribute("rep");
		if(rep!='1') deleteHTML("id_pdf"); //TODO
		if(this.f_pI!='1') deleteHTML('SRec_Add_'+this.uid);
		if(this.f_pD!='1') deleteHTML('SRec_Del_'+this.uid);
		this.nodeMetadataObjList=findNode(nodeType, "objects-list");
		if(this.win!=null) this.win.setWidth(this.nodeMetadataObjList.getAttribute("width"));
		nodeFilter=findNodeOnPath(nodeType,"objects-list/filter");


		//let id=-1;
		//After loading the metadata, we request the data by sending an XML filter.
		let count=0;
		let row=1; let nRow=null;
		let h=nodeFilter.getAttribute("height");
		if((nodeFilter!=null)&&(h!=0)) //Create HTML elements by XML filter.
		{
			let columnNode=nodeFilter.firstChild;
			while (columnNode != null)
			{
				if ((columnNode.nodeName==="column")&&(columnNode.getAttribute("visible")!="0"))
				{
					count++;
					let value=getCdataValue(columnNode);

					if(row>1) row--;
					if(columnNode.getAttribute("row")!=null) row=parseInt(columnNode.getAttribute("row"))+1;
					if(columnNode.getAttribute("row")!=null && row>1)
					{
						tr = document.createElement('tr');
						td1 = document.createElement('td');
						tr.appendChild(td1);
						td1.colSpan='2';

						let table=document.createElement('table');
						table.border=0;
						table.setAttribute("width","100%");
						table.cellspacing=0;
						table.cellpadding=0;
						td1.appendChild(table);
						nRow=table.insertRow(0);
					}

					if(row>1)
					{
						td1 = nRow.insertCell(-1);
						td1.setAttribute("width","1%");
						td2 = nRow.insertCell(-1);
						//td2.setAttribute("width","10%")
					}
					if(row==1)
					{
						tr = document.createElement('tr');
						td1 = document.createElement('td');
						tr.appendChild(td1);
						td2 = document.createElement('td');
						td2.style.cssText="width: 100%;";
						tr.appendChild(td2);
					}
					//td2.style.cssText='white-space:nowrap'

					td1.appendChild(document.createTextNode(columnNode.getAttribute("d")));
					td1.style.cssText='white-space:nowrap;';
					if (columnNode.getAttribute("vt")==="dateTime")
					{
						let table=document.createElement('table');
						table.border=0;
						table.style.cssText="width:100%;/*table-layout:fixed;*/border-spacing:0;border-collapse:collapse;";
						let newRow=table.insertRow(0);
						let newCell1 = newRow.insertCell(0);
						newCell1.style.cssText="padding:0px;width:100%;";
						let newCell2 = newRow.insertCell(1);
						newCell2.style.cssText="padding:0px;width:25px;";

						let input = document.createElement('input');
						input.style.cssText="width: 100%;";
						input.setAttribute("type","text");
						input.onkeydown=function(event){
							events = event || window.event;
							if(events.keyCode==13) events.keyCode=9;
						};
						input.setAttribute("name",columnNode.getAttribute("n"));
						if(columnNode.getAttribute("size")!=null)
							input.setAttribute("maxlength",columnNode.getAttribute("size"),0);

						input.setAttribute("value",isNaN(value) || value=='' ? '' : (new Date(value*1000)).toString());
						input.setAttribute("id",'filter_'+this.uid+'_'+columnNode.getAttribute("n"));
						newCell1.appendChild( input );


						let img = document.createElement('img');
						img.src='../resources/metadata/dbms/images/datepicker.jpg';
						img.style.cssText="cursor: pointer;";
						newCell2.appendChild(img);

						td2.appendChild( table );

						new Calendar({
								  inputField: input,
								  dateFormat: "%Y-%m-%d %H:%M:%S",
								  trigger: img,
								  align: "Bl",
								  bottomBar: false,
								  showTime: true,
								  //singleClick: true,
								  onSelect: function(){ this.hide(); }
						  });

					}else
					if (columnNode.getAttribute("vt")==="date")
					{
						let table=document.createElement('table');
						table.border=0;
						table.style.cssText="width:100%;/*table-layout:fixed;*/border-spacing:0;border-collapse:collapse;";
						newRow=table.insertRow(0);
						let newCell1 = newRow.insertCell(0);
						newCell1.style.cssText="padding:0px;width:100%;";
						let newCell2 = newRow.insertCell(1);
						newCell2.style.cssText="padding:0px;width:25px;";

						input = document.createElement('input');
						input.style.cssText="width: 100%;";
						input.setAttribute("type","text");
						input.onkeydown=function(event){
							events = event || window.event;
							if(events.keyCode==13) events.keyCode=9;
						};
						input.setAttribute("name",columnNode.getAttribute("n"));
						if(columnNode.getAttribute("size")!=null)
							input.setAttribute("maxlength",columnNode.getAttribute("size"),0);

						input.setAttribute("value",isNaN(value) || value=='' ? '' : (new Date(value*1000)).toString());
						input.setAttribute("id",'filter_'+this.uid+'_'+columnNode.getAttribute("n"));
						newCell1.appendChild( input );


						let img = document.createElement('img');
						img.src='../resources/metadata/dbms/images/datepicker.jpg';
						img.style.cssText="cursor: pointer;";
						newCell2.appendChild(img);

						td2.appendChild( table );

						new Calendar.setup({
							inputField     :    input,
							ifFormat       :    "%Y-%m-%d",
							button         :    img,
							align          :    "Tl",
							singleClick    :    false,
							onSelect: function(){ this.hide(); }
						});

					}else
					if (columnNode.getAttribute("vt")==="b")
					{
						let select = document.createElement('select');
						select.onkeydown=function(){
							if(event.keyCode==13) event.keyCode=9;
						};
						select.style.cssText="width: 100%;";
						let opt=findFirstNode(columnNode,"options");
						if(opt==null)
						{
							let option=document.createElement("option");
							option.setAttribute("value","");
							option.appendChild(document.createTextNode(""));
							if(value=="") option.selected=true;
							select.appendChild( option );
							option=document.createElement("option");
							option.setAttribute("value","1");
							option.appendChild(document.createTextNode(_('Yes')));
							if(value=="1") option.selected=true;
							select.appendChild( option );
							option=document.createElement("option");
							option.setAttribute("value","0");
							option.appendChild(document.createTextNode(_('Not')));
							if(value=="0") option.selected=true;
							select.appendChild( option );
						}else
						{
							opt=opt.firstChild;
							while(opt!=null)
							{
								if(opt.nodeName=="option")
								{
									let option = document.createElement("option");
									option.setAttribute("value",opt.getAttribute("val"));
									if(opt.getAttribute("val")==value) option.selected=true;
									option.appendChild(document.createTextNode(opt.getAttribute("d")));
									select.appendChild( option );
								}
								opt=opt.nextSibling;
							}
						}
						select.setAttribute("id",'filter_'+this.uid+'_'+columnNode.getAttribute("n"));
						td2.appendChild( select );
					}else
					if (columnNode.getAttribute("vt")==="string")
					{
						let input = document.createElement('input');
						input.style.cssText="width: 100%;";
						input.setAttribute("type","text");
						input.onkeydown=function(event){if(event.which==13) event.which=9;};
						input.setAttribute("name",columnNode.getAttribute("n"));
						if(columnNode.getAttribute("size")!=null)
							input.setAttribute("maxlength",columnNode.getAttribute("size"),0);
						input.setAttribute("value",value);
						input.setAttribute("id",'filter_'+this.uid+'_'+columnNode.getAttribute("n"));
						td2.appendChild( input );
					}else
					if (columnNode.getAttribute("vt")==="i4")
					{
						let table=document.createElement('table');
						table.border=0;
						table.style.cssText="width:100%;/*table-layout:fixed;*/border-spacing:0;border-collapse:collapse;";
						let newRow=table.insertRow(0); //We add a row in the created table.
						let newCell1 = newRow.insertCell(0);
						newCell1.style.cssText="padding:0px;padding-right:1px;width:100%;";
						let newCell2 = newRow.insertCell(1);
						newCell2.style.cssText="padding:0px;padding-right:1px;height:100%;";
						let newCell3 = newRow.insertCell(2);
						newCell3.style.cssText="padding:0px;width:25px;height:100%;";

						let input = document.createElement('input');
						input.style.cssText="width: 100%;";
						input.setAttribute("type","text");
						input.onkeydown=function(){ if(event.keyCode==13) event.keyCode=9; };
						input.setAttribute("name",columnNode.getAttribute("n"));
						if(columnNode.getAttribute("size")!=null)
							input.setAttribute("maxlength",columnNode.getAttribute("size"),0);
						input.setAttribute("value",value);
						input.setAttribute("id",'filter_'+this.uid+'_'+columnNode.getAttribute("n"));
						newCell1.appendChild( input );

						let button = document.createElement('input');
						button.className='button-secondary';
						button.setAttribute("type","button");
						button.setAttribute("value","+");
						button.style.cssText="height:100%;width:22px;margin:0px;padding:0px;";
						newCell2.appendChild( button );
						button.onclick=function(inp){return function(){ inp.value=getIntVal(inp.value)+1; }}(input);

						button = document.createElement('input');
						button.className='button-secondary';
						button.setAttribute("type","button");
						button.setAttribute("value","-");
						button.style.cssText="height:100%;width:22px;margin:0px;padding:0px;";
						button.onclick=function(inp){return function(){ inp.value=getIntVal(inp.value)-1; }}(input);
						newCell3.appendChild( button );

						td2.appendChild( table );
					}else
					if (columnNode.getAttribute("vt")==="f8")
					{
						let input = document.createElement('input');
						input.style.cssText="width: 100%;";
						input.setAttribute("type","text");
						input.onkeydown=function(){ if(event.keyCode==13) event.keyCode=9; };
						input.setAttribute("name",columnNode.getAttribute("n"));
						if(columnNode.getAttribute("size")!=null)
							input.setAttribute("maxlength",columnNode.getAttribute("size"),0);
						input.setAttribute("value",value);
						input.setAttribute("id",'filter_'+this.uid+'_'+columnNode.getAttribute("n"));
						td2.appendChild( input );
					}else
					if (columnNode.getAttribute("vt")==="object")
					{
						let selector=columnNode.getAttribute("selector");
						let object=columnNode.getAttribute("object");
						let fc=columnNode.getAttribute("FieldCaption");

						let table=document.createElement('table');
						//table.setAttribute("bgColor","#0000FF")
						table.border=0;
						table.style.cssText="width:100%;/*table-layout:fixed;*/border-spacing:0;border-collapse:collapse;";
						let newRow=table.insertRow(0); //We add a row in the created table.
						let newCell1 = newRow.insertCell(0);
						newCell1.style.cssText="padding:0px; border: 0px solid #999999; /*width:100%;*/";
						let newCell2 = newRow.insertCell(1);
						newCell2.style.cssText="padding:0px;  padding-left:1px; border: 0px solid #999999; width:30px; height:100%;";

						if(selector=="combo")
						{
							let select = document.createElement('select');
							select.style.cssText="width: 100%;";
							select.onkeydown=function(){ if(event.keyCode==13) event.keyCode=9; };
							//select.setAttribute("name",columnNode.getAttribute("n"))
							select.setAttribute("value",value);
							select.setAttribute("id",'filter_'+this.uid+'_'+columnNode.getAttribute("n"));
							select.onchange = function(thiz,node){ return function(){ thiz.onComboObjectChangeHandler(node);}; }(this,columnNode);

							newCell1.appendChild(select);

							let button = document.createElement('input');
							button.className='button-secondary';
							button.setAttribute("type","button");
							button.setAttribute("value","...");
							button.style.cssText="display:block; box-sizing: border-box; margin: 0px; padding: 0px;width:100%; height:100%; font-size: 9pt;";
							button.onclick=function(thiz,val1,val2){return function(){thiz.SelectObjects(val1,val2);};}(this,object,columnNode.getAttribute("n"));
							newCell2.appendChild(button);

							//I collect values from XML and inserting a request to the server (to fill out the dropdown).
							let nTypeF = findFirstNode(columnNode, "type");
							if(nTypeF != null)
							{
								//Add parameters to request
								nTypeF.setAttribute("c",fc);
								nTypeF.setAttribute("pn",columnNode.getAttribute("n"));
								nTypeF.setAttribute("fn",columnNode.getAttribute("n"));

								let strXMLF = getXMLNodeSerialisation(nTypeF);
								let nColF=nodeFilter.firstChild;
								while(nColF != null)
								{
									if(nColF.nodeName==="column")
									{
										let valF=getCdataValue(nColF);
										strXMLF=strXMLF.replace('${'+nColF.getAttribute('n')+'}', valF);
									}
									nColF = nColF.nextSibling;
								}
								strXMLF='<?xml version="1.0" encoding="utf-8"?><metadata fn="6">'+strXMLF+'</metadata>';

								if(this.request.callServer(ScriptName,strXMLF,true))
								{
									this.showProgressBar();
								}
							}else
							{
								if(this.request.callServer(ScriptName,'<?xml version="1.0" encoding="utf-8"?><metadata fn="6"><type n="'+object+'" c="'+fc+'" pn="'+columnNode.getAttribute("n")+'" fn="'+columnNode.getAttribute("n")+'"></type></metadata>',true))
								{
									this.showProgressBar();
								}
							}
						}else
						{
							//Two elements are placed in the table
							let input = document.createElement('input');
							//After pressing Enter we pass the entered line to the server
							input.onkeydown=function(obj,val1,val2,val3,val4){
								return function(e){
									if(e==null) e=window.event;
									if(e.keyCode==13){
										obj.callFilterVal(val1,val2,-1,val3.value,val4);
										return false;
									}
								};
							}(this,object,fc,input,columnNode.getAttribute("n"));

							input.style.cssText="width: 100%; height:22px; line-height:22px;";
							input.setAttribute("type","text");
							input.setAttribute("id",'filter_'+this.uid+'_'+columnNode.getAttribute("n")+"_visible");
							input.setAttribute("value","");
							newCell1.appendChild(input);
							//A hidden field where data is stored (you can make it stored in XML).
							let hidden = document.createElement('input');
							hidden.setAttribute("type", "hidden");
							hidden.setAttribute("id",'filter_'+this.uid+'_'+columnNode.getAttribute("n"));
							//hidden.setAttribute("value",value)
							hidden.value=value;
							newCell1.appendChild(hidden);

							let button = document.createElement('input');
							button.className='button-secondary';
							button.setAttribute("type","button");
							button.setAttribute("value","...");
							button.style.cssText="width:30px; height:100%;margin: 0px; padding: 0px;";
							button.onclick=function(thiz,val1,val2)
							{	return function(){thiz.SelectObjects(val1,val2);};
							}(this,object,columnNode.getAttribute("n"));
							newCell2.appendChild(button);

							//If the field is filled then we request the field header by its id
							if ((value!="")&&(value!=-1))
							{
								let xmlString='<?xml version="1.0" encoding="utf-8"?><metadata fn="6"><type n="'+columnNode.getAttribute("object")+'" c="'+columnNode.getAttribute("FieldCaption")+'" pn="'+columnNode.getAttribute("n")+'" fn="'+columnNode.getAttribute("n")+'"><objects-list><filter><column n="id"><![CDATA['+value+']]></column></filter></objects-list></type></metadata>';
								if(this.request.callServer(ScriptName,xmlString,true))
								{
									this.showProgressBar();
								}
							}
						}
						td2.appendChild( table );

					}else alert("Unknown type = "+columnNode.getAttribute("vt"));
					tablefilter.tBodies[0].appendChild(tr);
				}
				columnNode = columnNode.nextSibling;
			}
			//button to apply
			tr = document.createElement('tr');
			td = document.createElement('td');
			td.appendChild( document.createTextNode(" "));
			tr.appendChild(td);
			td = document.createElement('td');
			td.setAttribute("align","right");

			let button = document.createElement('input');
			button.className='button-secondary';
			button.setAttribute("type","button");
			button.setAttribute("value",_("Filtering"));
			button.setAttribute("id","btnfilter_"+this.uid);
			button.onclick=function(obj){
				return function()
				{	obj.appendFilter();
					obj.sendFilter(-1,0);
				};
			}(this);
			td.appendChild( button );
			tr.appendChild(td);
			tablefilter.tBodies[0].appendChild(tr);
		}
		if((count==0)||(h=0)) deleteHTML("idfilter"+this.uid);

		//Columns in which there are links to the array
		let pos=0;
		let columnNode=this.nodeMetadataObjList.firstChild;

		while (columnNode != null)
		{
			if(columnNode.nodeName=="column")
			{
				this.masCL[pos]=columnNode;
				this.masCT[pos]=findFirstNode(columnNode, "type");
				if(columnNode.getAttribute("visible")!="0") this.masVis[pos]=true; else this.masVis[pos]=false;
				pos++;
			}
			columnNode = columnNode.nextSibling;
		}

		if (this.win!=null && this.win.getTop()!=40)
			this.win.setCenter();

		//Building the columns of the data table
		this.buildHead();

		//this.sendFilter(id,0);
		this.sendFilter(-1,0);
	}

	/** The event occurs when you change the list of the referenced to "vt = Object" and if there is a dependency, then the field is updated.
	*/
	onComboObjectChangeHandler(node)
	{
		//I go through the fields and if there is a configurable query, I ask the data again.
		let nodeType=findFirstNode(this.nodeMetadata, "type");
		let nodeFilter=findNodeOnPath(nodeType,"objects-list/filter");
		if(nodeFilter!=null) //Create HTML elements by XML filter.
		{
			let columnNode=nodeFilter.firstChild;
			while (columnNode != null)
			{
				if (columnNode.nodeName==="column")
				{
					let nTypeF = findFirstNode(columnNode, "type");
					if(nTypeF != null)
					{
						//Add parameters to request
						nTypeF.setAttribute("c",columnNode.getAttribute("FieldCaption"));
						nTypeF.setAttribute("pn",columnNode.getAttribute("n"));
						nTypeF.setAttribute("fn",columnNode.getAttribute("n"));

						let strXMLF = getXMLNodeSerialisation(nTypeF);
						if(strXMLF.indexOf('${'+node.getAttribute('n')+'}')!=-1) //If it does not participate then it does not react to the change.
						{
							let nColF=nodeFilter.firstChild;
							while(nColF != null)
							{
								if(nColF.nodeName==="column")
								{
									let elm=document.getElementById('filter_'+this.uid+'_'+nColF.getAttribute("n"));
									if(elm!=null)
									{
										let valF=elm.value;
										strXMLF=strXMLF.replace('${'+nColF.getAttribute('n')+'}', valF);
									}
								}
								nColF = nColF.nextSibling;
							}

							strXMLF='<?xml version="1.0" encoding="utf-8"?><metadata fn="6">'+strXMLF+'</metadata>';
							if(this.request.callServer(ScriptName,strXMLF,true))
							{
								this.showProgressBar();
							}
						}
					}
				}
				columnNode = columnNode.nextSibling;
			}
		}
	}

	//We ask the server for a list of values almost like a drop-down list.
	//typeName - The name of the object (TODO if the current is the variable f TypeName)
	//name - the name of the column for selecting the values (must match the name of any filter in typeName)
	//id - id of record if it is necessary to return only the description, if -1 then it is not considered
	//value - filter value text field
	//htmlid - field name in filter n
	callFilterVal(typeName,name,id,value,htmlid)
	{
		if(value!="")
		{
			if(this.request.callServer(ScriptName,'<?xml version="1.0" encoding="utf-8"?><metadata fn="6"><type n="'+typeName+'" c="'+name+'" pn="'+htmlid+'" id="'+id+'"><objects-list><filter><column n="'+name+'"><![CDATA['+value+']]></column></filter></objects-list></type></metadata>',true))
			{
				this.showProgressBar();
			}
		}else
		{
			document.getElementById("filter_"+htmlid).value=-1;
			appendFilter();
			this.sendFilter(-1,0);
		}
	}

	//Building a table header for the data
	buildHead()
	{
		if(this.win!=null) this.win.setCaption(this.nodeMetadataObjList.getAttribute("d"));

		let thetable = document.getElementById('thetable'+this.uid);
		delChild(thetable.tHead);
		let tr=document.createElement('tr');
		tr.style.cssText='background-color: var(--header-color);';
		let th=document.createElement('th');
		th.appendChild( document.createTextNode('№'));
		th.style.cssText='width: 1%;';
		tr.appendChild(th);
		th=document.createElement('th');
		th.appendChild( document.createTextNode('Del'));
		th.title = _('Invert_selection');
		th.style.cssText='width: 1%; cursor: pointer; text-decoration: underline;';
		th.onmouseover=function(){ this.style.backgroundColor=g_rowColor2; };
		th.onmouseout=function(){ this.style.backgroundColor='var(--header-color)'; };
		th.onclick=function(thiz){return function(){ for(let i=0;i<thiz.masChBox.length;i++){ if(!thiz.masChBox[i].disabled) thiz.masChBox[i].checked = ! thiz.masChBox[i].checked; }};}(this);
		tr.appendChild(th);

		let pos=0;
		let columnNode=this.nodeMetadataObjList.firstChild;

		while (columnNode != null)
		{
			if(columnNode.nodeName=="column")
			{
				this.masCT[pos]=findFirstNode(columnNode, "type");
				if(this.masVis[pos])
				{
					th=document.createElement('th');
					th.appendChild( document.createTextNode(columnNode.getAttribute("d")));
					th.style.cssText='width: '+columnNode.getAttribute("width")+'px;';

					if(this.nodeMetadataObjList.getAttribute('order')==columnNode.getAttribute('n')) { th.style.backgroundColor='#afafaf'; }

					if(columnNode.getAttribute("order")!=null && columnNode.getAttribute("order")!='')
					{
						th.style.textDecoration='underline';
						th.style.cursor='pointer';
						th.onclick=function(thiz,cName){ return function(){ findNodeOnPath(thiz.nodeMetadata,"type/objects-list").setAttribute('order',cName); thiz.appendFilter(); thiz.sendFilter(-1,0);}; }(this,columnNode.getAttribute("n"));
						th.onmouseover=function(){ this.style.backgroundColor="var(--btn-color2)"; };
						th.onmouseout=function(thiz,cName){ return function(){ if(findNodeOnPath(thiz.nodeMetadata,"type/objects-list").getAttribute('order') == cName) this.style.backgroundColor='#afafaf'; else this.style.backgroundColor='#dadada'; }; }(this,columnNode.getAttribute("n"));
					}
					tr.appendChild(th);
				}
				pos++;
			}
			columnNode = columnNode.nextSibling;
		}
		thetable.tHead.appendChild(tr);
	}

	//Function to insert data into a table.
	//node - A node with data.
	//clear - Whether to clear all entries.
	insertRows(node,clear)
	{
		let theTable = document.getElementById('thetable'+this.uid); //Data table

		let nodeType=findFirstNode(node, "type");
		let pagecount=nodeType.getAttribute("pc"); //total pages
		if((nodeType.getAttribute("pp")!=null)&&(nodeType.getAttribute("pp")!=-1)) this.pagepos=nodeType.getAttribute("pp");

		if(clear || this.f_nodeData==null)
		{	this.f_nodeData=node;

			//Delete all rows from the data table
			for(let i = 1; i < theTable.rows.length;)
			{
				theTable.deleteRow(i);
			}
			this.masChBox=new Array(); //List of checkboxes

			//Delete rows from the page table
			let tablepages=document.getElementById('pages'+this.uid);
			for(let i = 0; i < tablepages.rows.length;)
			{
				tablepages.deleteRow(i);
			}

			//We build a page selection page in a row of 40 digits.
			tablepages.removeChild(tablepages.tBodies[0]);
			tablepages.appendChild(document.createElement('tbody'));
			if(pagecount>1)
			{
				let newRow=tablepages.insertRow(-1);
				for(let i=0;i<pagecount;i++)
				{
					let bgColor='#DDDDDD';
					if (i%2==0) bgColor='#EEEEEE';
					if (this.pagepos==i) bgColor='DodgerBlue';
					let newCell = newRow.insertCell(-1);
					newCell.setAttribute("bgColor",bgColor);
					newCell.style.cssText="cursor: pointer;";
					newCell.appendChild(document.createTextNode(i+1));
					//Upon clicking, a filter with old values is used only with a different page number.
					newCell.onclick=function(obj,page){
						return function(){
							obj.appendFilter();
							obj.sendFilter(-1,page);
						};
					}(this,i);
					newCell.onmouseover=function(){
						this.setAttribute("bgColor","#AAAAFF");
					};
					newCell.onmouseout=function(val1,val2){
						return function(){
							val1.setAttribute("bgColor",val2);
						};
					}(newCell,bgColor);
					if((i+1)%40==0) newRow=tablepages.insertRow(-1);
				}
			}
		}else
		{
			let tmpNR=findFirstNode(this.f_nodeData, "type");
			let nodeRecord = nodeType.firstChild;
			while (nodeRecord != null)
			{
				if(nodeRecord.nodeName=="record")
				{
					tmpNR.appendChild(nodeRecord.cloneNode(true) );
				}
				nodeRecord = nodeRecord.nextSibling;
			}
		}

		//Add new entries
		let nColor=findNumNodeOnAttribute(findNodeOnPath(this.nodeMetadata,"type/objects-list"),"column","n","color");
		let TypeName = nodeType.getAttribute("n");
		let i=0; //The position should be received from the server.

		let nodeRecord = nodeType.firstChild;
		while (nodeRecord != null)
		{
			if(nodeRecord.nodeName=="record")
			{
				let bgColor='';
				let i=theTable.rows.length; //number of rows in the table
				if (i%2==0) bgColor=g_rowColor1; else bgColor=g_rowColor2;

				if(nColor>=0) //Color from Result
				{	bgColorT=findNodeOnNum(nodeRecord,"#cdata-section",nColor).nodeValue;
					if(bgColorT!="") bgColor=bgColorT;
				}
				let id=nodeRecord.getAttribute("id");
				//add rows to an existing record table
				let tr = document.createElement('tr');
				tr.onmouseover=function(){ this.style.backgroundColor="var(--btn-color2)"; };
				tr.onmouseout=function(val1,val2){return function(){val1.style.backgroundColor=val2;}}(tr,bgColor);
				tr.setAttribute("id",id+'_'+this.uid);
				tr.setAttribute("bgColor",bgColor);
				//sequential record number
				let td = document.createElement('td');
				td.appendChild( document.createTextNode( i+100*this.pagepos ) );
				tr.appendChild(td);

				//CheckBuck to delete records
				td = document.createElement('td');
				td.style.cssText="text-align: center;";
				if(!(this.f_pD!="1" || nodeRecord.getAttribute("a").indexOf("d")==-1))
				{
					let checkbox = document.createElement('input');
					this.masChBox.push(checkbox);
					//checkbox.disabled=true;
					checkbox.setAttribute("type","checkbox");
					checkbox.setAttribute("value",id);
					checkbox.style.cssText="font: normal normal normal 11px normal Arial;";
					td.appendChild( checkbox );
				}
				tr.appendChild(td);

				//for each column we make a column
				let colN=0; //column number
				let cdataNode = nodeRecord.firstChild;
				while (cdataNode!=null)
				{
					if(cdataNode.nodeName=="#cdata-section")
					{
						if(this.masVis[colN])
						{
							td = document.createElement('td');
							if((this.f_pU=="1")||(this.f_State=="1")){
								td.style.cssText="cursor: pointer;";
							}
							let textNode=document.createTextNode(cdataNode.nodeValue);
							td.setAttribute("id",id+this.masCL[colN].getAttribute("n")); //so that you can identify each record when you update
							td.appendChild(textNode);
							//if in the metadata for this column there is a reference object then add a link
							if (this.masCT[colN]!=null)
							{
								//Opening a new window in the filter is passed to the current values of the row
								td.style.cssText="cursor: pointer; background-color: var(--btn-color); font-weight: bold;";
								td.onmouseover=function(){
									this.style.backgroundColor="var(--btn-color2)";
								};
								td.onmouseout=function(){
									this.style.backgroundColor="var(--btn-color)";
								};
								//when you click on a cell, the sent filter is prefilled with variables in accordance with the id of the pressed line
								//in the function we pass the cell id and the column number
								td.onclick=function(obj,val1,val2){
									return function(){
										obj.callWindow(val1,val2);
									}
								}(this,id,colN);
							}else
							{
								if((this.f_pU=="1" && nodeRecord.getAttribute("a").indexOf("u")!=-1)||(this.f_State=="1"))
								{
									td.onclick=function(thiz,val1,val2){
										return function(){thiz.updateRecord(val1);};
									}(this,id);
								}else
								{
									td.style.cssText="cursor: default;";
								}
							}
							tr.appendChild(td);
						}
						colN++;
					}
					cdataNode = cdataNode.nextSibling;
				}
				theTable.tBodies[0].appendChild(tr);
			}
			nodeRecord = nodeRecord.nextSibling;
		}
	}

	//by the column number, return the reference to the column node (numbering from 0)
	getColumnOnNum(num)
	{
		let i=0;
		let fNodeProp = findFirstNode(this.nodeMetadata,"objects-list").firstChild;
		while(fNodeProp != null)
		{
			if(fNodeProp.nodeName=="column")
			{
				if(num==i) return fNodeProp;
				i++;
			}
			fNodeProp=fNodeProp.nextSibling;
		}
		return null;
	}

	//Name the column number
	getColNumOnName(name)
	{
		let i=0;
		let nn = findNode(this.nodeMetadata,"objects-list").firstChild;
		while (nn != null)
		{
			if(nn.nodeName=='column')
			{
				if(nextNode.getAttribude('n')==name) return i;
				i++;
			}
			nextNode=nextNode.nextSibling;
		}
	}

	//Call the ShowRecord.html window with the parameters for the filter (not just the object name)
	//id - id records from the database
	//col - Column Number
	callWindow(id,col)
	{
		//we represent xml as a string and replace values of type $ {id} with values from the current record
		let typeName=this.masCT[col].getAttribute("n");
		let xmlString=getXMLNodeSerialisation(this.masCT[col]);
		while(true)
		{
			let sub1=BeforeFirst(xmlString,"${");
			if(sub1==null) break;
			let sub2=AfterFirst(xmlString,"}");
			if(sub2==null) break;
			let val=BeforeFirst(AfterFirst(xmlString,"${"),"}");
			xmlString=sub1+this.getData(id,val)+sub2;
		}
		//We assign a string of the global variable so that we can take the infu from the child
		//Settings.add(0,xmlString)
		//wishWin = window.open("showrecord.html?name="+typeName,typeName,"width=800,height=600,menubar=no,location=no,resizable=yes,scrollbars=yes");
		let rec=new SRec();
		rec.create();
		rec.f_Settings=xmlString;
		//rec.f_State=state;
		//rec.f_PropName=propname;
		rec.f_TypeName=typeName;
		rec.win.setLeftTop(pageX-250,pageY-10);
		rec.win.setParent(this.win);
		if(rec.request.callServer(ScriptName,'<?xml version="1.0" encoding="utf-8"?><metadata fn="0"><type n="'+rec.f_TypeName+'"></type></metadata>'))
		{
			rec.showProgressBar();
		}
	}

	//find the node cdata in the data by the record id and column name
	getDataC(id,col)
	{
		let i=0;
		let b=false;
		//determine the sequence number of the column
		let node=findNodeOnPath(this.nodeMetadata,"type/objects-list");
		let nodeCol = node.firstChild;
		while (nodeCol != null)
		{
			if(nodeCol.nodeName=="column")
			{
				if(nodeCol.getAttribute("n")==col){
					b=true;
					break;
				}
				i++;
			}
			nodeCol = nodeCol.nextSibling;
		}
		if(!b)return null;

		//we search for value in result set
		node=findFirstNode(this.f_nodeData, 'type');
		let nodeRec=findNodeOnAttribute(node, 'record', 'id', id);
		return findNodeOnNum(nodeRec,"#cdata-section",i);
	}

	//find the value in the result set by the id of the record and the name of the column
	getData(id,col)
	{
		if(findNode(this.nodeMetadata,'type').getAttribute("ObjectID")==col) return id;
		let cdt=this.getDataC(id,col);
		if(cdt!=null) return cdt.nodeValue; else return '';
	}

	//look for a string by id and update the values (TODO consecutively without hidden fields)
	updateRows(node)
	{
		//We sort through the received records and update the values
		let nodeRecord = findNode(node,"type").firstChild
		while (nodeRecord != null)
		{
			if(nodeRecord.nodeName=="record")
			{
				let ii=0;
				let jj=0;
				let id=nodeRecord.getAttribute("id");
				let tr=document.getElementById(id+'_'+this.uid);

				if (tr==null)
				{
					this.insertRows(node,false); //If not then insert
				}else
				{
					let cdataNode = nodeRecord.firstChild;
					while (cdataNode!=null)
					{
						if (cdataNode.nodeName=="#cdata-section")
						{
							let cd=this.getDataC(id,this.masCL[ii].getAttribute("n"));
							if(cd!=null) cd.nodeValue=cdataNode.nodeValue;

							if(this.masCL[ii].getAttribute("visible")!="0")
							{
								while(tr.childNodes[jj+2].childNodes[0])
									tr.childNodes[jj+2].removeChild(tr.childNodes[jj+2].childNodes[0]);
								tr.childNodes[jj+2].appendChild(document.createTextNode(cdataNode.nodeValue));

								jj++;
							}
							ii++;
						}
						cdataNode = cdataNode.nextSibling;
					}
				}
			}
			nodeRecord = nodeRecord.nextSibling;
		}
	}

	//request data to fill the Object Filter
	//The result can fill the filter field with complete information or a window with a further choice of the value
	SelectObjects(typeName,propname)
	{
		let rec=new SRec();
		rec.opener=this;
		rec.create();
		rec.f_State=1;
		rec.f_PropName=propname;
		rec.f_TypeName=typeName;
		rec.win.setLeftTop(pageX-250,pageY-10);
		rec.win.setParent(this.win);
		if(rec.request.callServer(ScriptName,'<?xml version="1.0" encoding="utf-8"?><metadata fn="0"><type n="'+rec.f_TypeName+'"></type></metadata>'))
		{
			rec.showProgressBar();
		}

		//the filter is sent if not 1 value has come and much it is necessary to display a window with a choice of one of them
		//if the "..." button was pressed to display the showrecord.html window with the object selection mode
		//wishWin = window.open("showrecord.html?name="+typeName+"&state=1&propname="+propname,typeName+Math.floor(Math.random()*1000000),"width=800,height=600,menubar=no,location=no,resizable=yes,scrollbars=yes");
	}

	openPage(page)
	{
		open(page);
	}

	dataalert()
	{
		let error_msg="";
		if (error_msg!="") alert("ShowRecords: \n"+error_msg);
	}

	showreport(ext)
	{
		if(this.rwin!=null) this.rwin.Close();

		this.rwin=new TWin();
		this.rwin.BuildGUI(pageX-10,pageY-10);
		this.rwin.setParent(this.win);
		this.rwin.setSize(280,130);
		this.rwin.setCaption(_('Report'));
		this.rwin.setContent('<table border="0px" style="width: 100%; height: 100%; background-color: #f1f1f1;"><tr><td align="center"><b>'+_('Preparing_of_report')+'</b></td></tr><tr><td align="center"><img src="./metadata/dbms/form/loading.gif" alt=""/></td></tr></table>');

		this.appendFilter();
		//Call data from server
		let nodeType=findFirstNode(this.nodeMetadata, "type");
		let typename=nodeType.getAttribute("n");
		let nodeFilter=findNodeOnPath(nodeType,"objects-list/filter");
		let xs='';
		xs+='<?xml version="1.0" encoding="utf-8"?>\n';
		xs+='<metadata fn="8">\n';
		xs+='	<type n="'+typename+'" ext="'+ext+'" id="-1" pp="0">\n';
		xs+='		<objects-list><filter>';
		let nextNode=nodeFilter.firstChild;
		while(nextNode!=null)
		{
			if(nextNode.nodeName=="column")
			{
				xs+='<column n="'+nextNode.getAttribute("n")+'" vt="'+nextNode.getAttribute("vt")+'" size="'+nextNode.getAttribute("size")+'">';
				xs+='<![CDATA['+getCdataValue(nextNode)+']]>';
				xs+='</column>\n';
			}
			nextNode=nextNode.nextSibling;
		}
		xs+='		</filter></objects-list>\n';
		xs+='	</type>\n';
		xs+='</metadata>';
		if(this.request.callServer(ScriptName,xs))
		{
			this.rwin.showProgressBar();
		}
	}

	chp(page)
	{
		//The current filter values are sent to the script to form a page change
		document.forms.filter.xml_page.value=page;
		document.forms.filter.submit();
	}

	insertRecord()
	{
		let erec = new EdtRec("");
		erec.opener=this;
		erec.eRecNo(this.nodeMetadata,-1);
		erec.win.setParent(this.win);
	}

	updateRecord(id)
	{
		if(this.f_State=="0") //editing
		{
			let erec = new EdtRec("");
			erec.win.setParent(this.win);
			erec.opener=this;
			erec.eRecNo(this.nodeMetadata,id);

			//e.win.setLeftTop(pageX-10,pageY-10);
		}else
		if(this.f_State=="1") //select one record
		{
			//Send the id of the selected record to the parent of the selected record and close the window
			//alert("id="+id+" f_PropName="+this.f_PropName+" f_TypeName="+this.f_TypeName);
			this.opener.setFilterObject(this.f_TypeName,this.f_PropName,id);
			this.win.Close();
		}else
		if(this.f_State=="2") //Multiple choice (on the records of ticking TODO is not implemented)
		{
		}
	}

	//We run through the marked records and request their removal
	deleteRecord(recordid)
	{
		if (confirm(_("Are_you_sure_you_want_to_delete_the_entries")+'?'))
		{
			for(let i=0;i<this.masChBox.length;i++)
			{
				if(this.masChBox[i].checked)
				{
					if(this.request.callServer(ScriptName,'<?xml version="1.0" encoding="utf-8"?><metadata fn="3"><type n="'+this.f_TypeName+'" id="'+this.masChBox[i].value+'"></type></metadata>',true))
					{
						this.showProgressBar();
					}
				}
			}
		}
		return false;
	}

	//Update HTML data after update record
	ApplyDelRec(node)
	{
		let nodeType=findFirstNode(node, "type");
		let typeName=nodeType.getAttribute("n");
		id=nodeType.getAttribute("id");
		deleteHTML(id+'_'+this.uid);
		//Rebuild sequential numbering of rows (first column)
		let theTable = document.getElementById('thetable'+this.uid); //data table
		for(let i=1;i<theTable.rows.length;i++)
		{while (theTable.rows[i].cells[0].childNodes[0]) //delete all childs
			{theTable.rows[i].cells[0].removeChild(theTable.rows[i].cells[0].childNodes[0]);
			}
			theTable.rows[i].cells[0].appendChild(document.createTextNode(i));
		}
	}

	callData(typeName,settings)
	{
		this.f_TypeName=typeName;
		this.f_Settings=settings;

		if(this.request.callServer(ScriptName,'<metadata fn="0"><type n="'+this.f_TypeName+'"></type></metadata>'))
		{
			this.showProgressBar();
		}
	}

}

//Convert XML to array
function nodeToTable(node)
{
	let result=new Array();

	let nType=findFirstNode(node, "type");
	//Read name fields
	let nList=findFirstNode(node, "objects-list");
	let cols=new Array();
	let pos=0;
	let nCols=nList.firstChild;
	while(nCols != null)
	{
		if(nCols.nodeName=="column")
		{
			cols[pos]=nCols.getAttribute("n");
			pos++;
		}
		nCols = nCols.nextSibling;
	}

	pos=0; //Line number
	let nRecord = nType.firstChild;
	while(nRecord != null)
	{
		if(nRecord.nodeName=="record")
		{
			result[pos]['id']=nRecord.getAttribute("id");
			let i=0; //column number

			cdataNode = nRecord.firstChild;
			while (cdataNode!=null)
			{
				if(cdataNode.nodeName=="#cdata-section")
				{
					result[pos][cols[i]]=cdataNode.nodeValue;
//alert(pos+') '+cols[i]+' = '+cdataNode.nodeValue);
					i++;
				}
				cdataNode = cdataNode.nextSibling;
			}
			theTable.tBodies[0].appendChild(tr);
		}
		nodeRecord = nodeRecord.nextSibling;
	}

	return result;
}
