//Copyright (C) Ivanov I.M. file created in 2008
//For find non english chars: [^\x00-\x7F]+

//Stubs
function setPropVal(uid,id,c,p){
	ERec_mas[uid].setPropVal(id,c,p);
}

var ERec_mas = new Array(); //List of all ERec objects (TODO then you better come up with something).

class EdtRec
{
	constructor(caption)
	{
		this.uid=getUID();
		this.record_id=null;
		
		this.win=new TWin();
		this.win.BuildGUI(pageX-10,pageY-10);
		this.win.setSize("500px","150px");
		this.win.setContent('<div id="eDiv'+this.uid+'" style="width: 100%; /*height: 100%;*/ position: relative;"></div>');
		
		let eDiv=document.getElementById('eDiv'+this.uid);
		eDiv.innerHTML = '<table style="width:100%;height:100%"><tr><td style="vertical-align:middle;background-color:#F1F1F1"><center><IMG src="../resources/metadata/dbms/images/loading.gif"></center></td></tr></table>'

		this.caption=caption;
		if(this.caption!='')
			this.win.setCaption(this.caption);
		this.win.obj=this;
		this.win.hide(false);
		
		this.name="name"+this.uid;
		this.opener=null; //Link to ShowRecord if it is opened from it.
		this.nodeMetadata=null;
		
		this.pBarCnt=0; //Progress Bar
		this.pBarDiv=null; //Progress Bar

		this.request = new TRequest(this);

		//this.fields = new Array();

		ERec_mas[this.uid]=this;
		this.f_TypeName=""; //Имя редактируемого объекта (type->n attribute)
		
		this.onInserted=null; //After insert row
		this.onUpdated=null; //After update row
	}

	//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  style="width:100%;height:100%" 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);
			if(eDiv==null) return;
			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;
		}
	};

	//Функция для создания или редактирования новой записи (аналог callData)
	//Если id = -1 то это создание новой записи
	eRecNa(typeName,id,settings)  
	{
		this.f_TypeName=typeName;
		this.f_Settings=settings;
		this.record_id=id;
		if(this.request.callServer(ScriptName,'<?xml version="1.0" encoding="utf-8"?><metadata fn="0"><type n="'+typeName+'"></type></metadata>'))
		{
			this.showProgressBar();
		}
	};

	//Задать CDATA значение для узла "type->properties->prop" по "n" 
	setPropCdata(name,value)
	{
		let node=findNodeOnPath(this.nodeMetadata,"type/properties/prop[@n='"+name+"']");
		if(node!=null) getCdata(node).nodeValue=value;
	}

	//Задать новое значение GUI полю (не XML, XML выше)
	setValue(propName,value){
		let field=document.getElementById("prop_"+this.uid+"_"+propName);
		if(field!=null)
		{
			field.value=value;
		}else{
			log.error('Field "'+propName+'" not found!');
		}
	}

	//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 a user GUI from XML ()
	// Node - Node "type"
	eRecNo(Node,record_id)
	{
		this.record_id=record_id;

		this.nodeMetadata=Node.cloneNode(true); //Для чего клонирую? 
		let nodeType=findFirstNode(this.nodeMetadata, 'type');
		//Appending settings to nodeMetadata
		this.setXMLSettings(this.f_Settings);

		//Записываю record_id в соответствующее XML поле
		this.setPropCdata(nodeType.getAttribute("ObjectID"),record_id);
		
		let str='';
		str+='		<table class="SEdit" id="eTable'+this.uid+'" border="0px" cellspacing="1" cellpadding="1" style="width: 100%; height: 100%;">';
		str+='			<caption><b id="caption'+this.uid+'"></b></caption>';
		str+='			<thead>';
		str+='				<tr bgcolor="#dadada">';
		str+='					<th style="width:20%">'+trt('Name')+'</th>';
		str+='					<th style="width:80%">'+trt('Value')+'</th>';
		str+='				</tr>';
		str+='			</thead>';
		str+='			<tbody></tbody>';
		str+='		</table>';
		document.getElementById('eDiv'+this.uid).innerHTML=str;
		//this.win.setContent(str);

		//document.getElementById('menu').parentNode.appendChild( this.win.div )
		let eTable=document.getElementById('eTable'+this.uid);

		let type_name=nodeType.getAttribute("n");
		if(this.caption === undefined || this.caption=='')
			this.win.setCaption(nodeType.getAttribute("d"));
		let nodeProperties=findNodeOnPath(this.nodeMetadata, 'type/properties');
		this.win.setWidth(nodeProperties.getAttribute("width"));

		let nodeFilters=findNodeOnPath(Node,'type/objects-list/filter');
		let nodeProp=null;

		//For convenience, when adding a new record, we rewrite the values from the parent filter in the edit field.
		if(nodeFilters!=null)
		{
			let nodeFilter=nodeFilters.firstChild;
			while (nodeFilter!=null)
			{
				if(nodeFilter.nodeName=="column")
				{
					nodeProp=nodeProperties.firstChild;
					while(nodeProp!=null)
					{
						if(nodeProp.nodeName=="prop")
						{
							if (nodeFilter.getAttribute("n")==nodeProp.getAttribute("n"))
							{
								let cdata1=findFirstNode(nodeFilter,'#cdata-section');
								if((cdata1!=null)&&(cdata1.nodeValue!=""))
								{
									let cdata2=findFirstNode(nodeProp,'#cdata-section');
									if (cdata2==null)
									{
										cdata2 = nodeProp.ownerDocument.createCDATASection("");
										nodeProp.appendChild(cdata2);
									}
									cdata2.nodeValue=cdata1.nodeValue;
								}
							}
						}
						nodeProp=nodeProp.nextSibling;
					}
				}
				nodeFilter=nodeFilter.nextSibling;
			}
		}

		nodeProp=nodeProperties.firstChild;
		let newRowM=null;
		let rpos=0;
		while (nodeProp!=null)
		{
			if (nodeProp.nodeName=="type")  //Grouping fields.
			{
				let tr = document.createElement('tr');
				tr.style.cssText="background-color: var(--back-color);";
				let td = document.createElement('td');
				td.style.cssText="font-weight: bold;";
				td.colSpan = "2";
				
				let div=document.createElement('div');
				div.style.cssText='border: solid 1px black; background-color: rgba(0,0,0,0.5); width:100%; height: 300px;';
				div.innerHTML='';

				td.appendChild(div);				
				tr.appendChild(td);
				eTable.tBodies[0].appendChild(tr);
				
				let subSRec=new SRec();
				subSRec.create(div);

				//Перебираю данные из текущего запроса и пытаюсь подменить строку (до получения анных (при создании новой записи))
				let nPs=findFirstNode(this.nodeMetadata, 'properties')
				let nP=nPs.firstChild
				while (nP!=null)
				{
					if (nP.nodeName=="prop")
					{
						replaseTextInCDATA(nodeProp,"${"+nP.getAttribute("n")+"}",getCdataValue(nP));
					}
					nP=nP.nextSibling;
				}
				subSRec.f_Settings=nodeProp;
					
				subSRec.f_State='0';
				if(subSRec.request.callServer(ScriptName,'<?xml version="1.0" encoding="utf-8"?><metadata fn="0"><type n="'+nodeProp.getAttribute("n")+'"></type></metadata>'))
				{
					//obj.showProgressBar();
				}
				
			}else
			if (nodeProp.nodeName=="divide")  //Grouping fields.
			{
				let tr = document.createElement('tr');
				tr.style.cssText="background-color: var(--back-color-title);";
				let td = document.createElement('td');
				td.style.cssText="font-weight: bold;";
				td.colSpan = "2";
				td.innerHTML=nodeProp.getAttribute("d");

				tr.appendChild(td);
				eTable.tBodies[0].appendChild(tr);
			}else
			if (nodeProp.nodeName=="prop")
			{
				let bgColor='';
				let tr = null;
				let td1 = null;
				let td2 = null;
				let vt=nodeProp.getAttribute("vt");

				let row=nodeProp.getAttribute("row"); //Several fields in the 1st row.
				if(row==null)
				{
					rpos++;
					tr = document.createElement('tr');
					if (rpos%2==0) bgColor='var(--row-color-1)'; else bgColor='var(--row-color-2)';
					tr.style.backgroundColor=bgColor;
					if(nodeProp.getAttribute("visible")=='0') tr.style.display='none';
					td1 = document.createElement('td');
					td2 = document.createElement('td');
					tr.appendChild(td1);
					tr.appendChild(td2);

					let table=document.createElement('table');
					table.style.cssText="width:100%;border-spacing:0;border-collapse:collapse;border:0px;";
					td2.appendChild(table);
					newRowM=table.insertRow(0);
					td2 = newRowM.insertCell(-1);
					td2.setAttribute("width","40%");
					
					eTable.tBodies[0].appendChild(tr);
				}else
				{
					td1 = newRowM.insertCell(-1);
					td1.style.cssText="width: 10%;white-space:nowrap;";
					td2 = newRowM.insertCell(-1);
					td2.setAttribute("width","50%");
					//td2.style.width=row+"px";
				}

				if(vt==="html"){
					td1.innerHTML=nodeProp.getAttribute("d")+'<br><button class="button-secondary" onclick="showHTMLEditor(\''+nodeProp.getAttribute("d")+'\',\'prop_'+this.uid+'_'+nodeProp.getAttribute("n")+'\');">HTML ...</button>';
				}else{
					td1.innerHTML=nodeProp.getAttribute("d");
				}

				if(nodeProp.getAttribute("t")!=null) td1.title=nodeProp.getAttribute("t");
				if (nodeProp.getAttribute("maybenull")=='0') td1.style.cssText="font-weight: bold;";

				let value=getCdata(nodeProp).nodeValue;


				if(vt==="string" || vt==="str")
				{
					let table=document.createElement('table');
					table.style.cssText="width:100%;border-spacing:0;border-collapse:collapse;border:0px;";
					let newRow=table.insertRow(0); //add a row to the created table
					let newCell1 = newRow.insertCell(0); //in the created line we add a column
					newCell1.style.cssText="padding:0px; padding-right:1px; width: 100%;";
					let newCell2 = newRow.insertCell(1); //in the created line we add a column
					newCell2.style.cssText="padding:0px;";
					
					//If there is a list node with CheckBox elements, then we create them
					let nList=findNode(nodeProp, "options");
					if(nList!=null)
					{
						if(nList.getAttribute("selector")=="combo")
						{
							let select = document.createElement('select');
							select.classList.add('DBMS');
							select.style.cssText="width: 100%; height:22px; line-height: 22px;";
							select.setAttribute("name",nodeProp.getAttribute("n"));
							select.setAttribute("id","prop_"+this.uid+"_"+nodeProp.getAttribute("n"));
							select.onchange = function(thiz,node){ return function()
							{
								thiz.onComboObjectChangeHandler(node);
							};
							}(this,nodeProp);

							let nCheckbox = nList.firstChild;
							while (nCheckbox != null) {
								if (nCheckbox.nodeName == "option") {
									let option = document.createElement('option');
									option.setAttribute("value",nCheckbox.getAttribute("n"));
									option.appendChild(document.createTextNode(nCheckbox.getAttribute("d")));
									select.appendChild( option );
								}
								nCheckbox = nCheckbox.nextSibling;
							}
							//select.setAttribute("value",value);// does not work because when creating no values in the list
							newCell1.appendChild(select);
						}else{
							nodeProp.field = new TCheckboxListField(nodeProp.getAttribute("n"));
							let nCheckbox = nList.firstChild;
							while (nCheckbox != null) {
								if (nCheckbox.nodeName == "option") {
									nodeProp.field.addCheckbox(nCheckbox.getAttribute("n"), nCheckbox.getAttribute("d"));
								}
								nCheckbox = nCheckbox.nextSibling;
							}
							newCell1.appendChild(nodeProp.field.getDiv());
						}
					}else
					{
						let input = document.createElement('input');
						input.setAttribute("type","text");
						input.classList.add('DBMS');
						input.style.cssText="width: 100%;overflow:hidden;";
						input.setAttribute("name",nodeProp.getAttribute("n"));
						if(nodeProp.getAttribute("size")!=null)
							input.setAttribute("maxlength",nodeProp.getAttribute("size"),0);
						input.setAttribute("value",value);
						input.setAttribute("id","prop_"+this.uid+"_"+nodeProp.getAttribute("n"));
						
						newCell1.appendChild( input );
						//td2.appendChild( input );
						
						//Button for translation
						let tObj=findNode(nodeProp, "type");
						if(tObj!=null)
						{
							let button = document.createElement('input');
							button.classList.add('button-secondary');
							button.setAttribute("type","button");
							button.setAttribute("value","...");
							button.style.cssText="width:30px;font-size:9pt;margin:0px;padding:0px;";
							button.onclick=function(thiz,nodeProp){ return function(){
								thiz.callWindowF(nodeProp);
							};}(this,nodeProp);

							newCell2.appendChild( button );
						}
						
					}
					td2.appendChild( table );					

                }else
                if(vt==="password")
                {
					let input = document.createElement('input');
					input.classList.add('DBMS');
					input.style.cssText="width: 100%;";
					input.setAttribute("type","password");
					input.setAttribute("name",nodeProp.getAttribute("n"));
					input.setAttribute("value",value);
					input.setAttribute("id","prop_"+this.uid+"_"+nodeProp.getAttribute("n"));
					td2.appendChild( input );
                }else
				if(vt==="b")
				{
					let select = document.createElement('select');
					select.classList.add('DBMS');
					select.style.cssText="width: 100%;";
					select.setAttribute("name",nodeProp.getAttribute("n"));
					let opt=findFirstNode(nodeProp,"options");
					if(opt==null)
					{
						let option = document.createElement('option');
						option.setAttribute("value","");
						option.appendChild(document.createTextNode(""));
						option.selected = true;
						select.appendChild( option );
						option = document.createElement("option");
						option.setAttribute("value","1");
						option.appendChild(document.createTextNode(trt('Yes')));
						select.appendChild( option );
						option = document.createElement("option");
						option.setAttribute("value","0");
						option.appendChild(document.createTextNode(trt('Not')));
						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"));
								option.appendChild(document.createTextNode(opt.getAttribute("d")));
								select.appendChild( option );
							}
							opt=opt.nextSibling;
						}
					}
					select.setAttribute("id","prop_"+this.uid+"_"+nodeProp.getAttribute("n"));
					td2.appendChild( select );
				}else
				if(vt==="i4")
				{
					//If there is a node "list" with the elements "CheckBox" then create them.
					let opt=findNode(nodeProp, "options");
					if(opt!=null){ //If combobox
						let select = document.createElement('select');
						select.classList.add('DBMS');
						select.style.cssText="width: 100%;";
						select.setAttribute("name",nodeProp.getAttribute("n"));
						select.setAttribute("id","prop_"+this.uid+"_"+nodeProp.getAttribute("n"));
						opt=opt.firstChild;
						while(opt!=null)
						{
							if(opt.nodeName=="option")
							{
								let option = document.createElement("option");
								option.setAttribute("value",opt.getAttribute("val"));
								option.appendChild(document.createTextNode(opt.getAttribute("d")));
								select.appendChild( option );
							}
							opt=opt.nextSibling;
						}
						td2.appendChild( select );
					}else
					{
						let table=document.createElement('table');
						table.style.cssText="width:100%;border-spacing:0;border-collapse:collapse;border:0px;";
						let newRow=table.insertRow(0); //add a row to the created table
						let newCell1 = newRow.insertCell(0); //in the created line we add a column
						newCell1.style.cssText="padding:0px; padding-right:1px; width: 100%;";
						let newCell2 = newRow.insertCell(1); //in the created line we add a column
						newCell2.style.cssText="padding:0px; padding-right:1px;height:100%;";
						let newCell3 = newRow.insertCell(2); //in the created line we add a column
						newCell3.style.cssText="padding:0px;height:100%;";

						let input = document.createElement('input');
						input.classList.add('DBMS');
						input.style.cssText="width: 100%; height:22px;";
						input.setAttribute("type","text");
						input.setAttribute("name",nodeProp.getAttribute("n"));
						input.setAttribute("value",value);
						input.setAttribute("id","prop_"+this.uid+"_"+nodeProp.getAttribute("n"));
						newCell1.appendChild( input );
	
						let button = document.createElement('input');
						button.classList.add('button-secondary');
						button.setAttribute("type","button");
						button.setAttribute("value","+");
						button.setAttribute("title",trt("Increase_by_1"));
						button.style.cssText="height:100%;width:22px;margin:0px;padding:0px;";
						button.onclick=function(inp){return function(){inp.value=getIntVal(inp.value)+1;}}(input);
	
						newCell2.appendChild( button );
	
						button = document.createElement('input');
						button.classList.add('button-secondary');
						button.setAttribute("type","button");
						button.setAttribute("value","-");
						button.setAttribute("title",trt("Decrease_by_1"));
						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(vt==="f4")
				{
					let input = document.createElement('input');
					input.classList.add('DBMS');
					input.style.cssText="width: 100%;";
					input.setAttribute("type","text");
					input.setAttribute("name",nodeProp.getAttribute("n"));
					input.setAttribute("value",value);
					input.setAttribute("id","prop_"+this.uid+"_"+nodeProp.getAttribute("n"));
					td2.appendChild( input );
				}else
				if(vt==="object")
				{
					let input=null;
					if(nodeProp.getAttribute("selector")=="combo")
					{
						let table=document.createElement('table');
						table.style.cssText="width:100%;border-spacing:0;border-collapse:collapse;border:0px;";
						//table.setAttribute("bgColor","#0000FF");
						let newRow=table.insertRow(0); //add a row to the created table
						let newCell1 = newRow.insertCell(0); //in the created line we add a column
						newCell1.style.cssText="padding:0px;padding-right:1px;width:100%;";
						let newCell2 = newRow.insertCell(1); //in the created line we add a column
						newCell2.style.cssText="padding:0px;height:100%;";

						let select = document.createElement('select');
						select.classList.add('DBMS');
						select.style.cssText="width: 100%; height:22px; line-height: 22px;";
						select.setAttribute("name",nodeProp.getAttribute("n"));
						//select.setAttribute("value",value) does not work because when creating no values in the list
						select.setAttribute("id","prop_"+this.uid+"_"+nodeProp.getAttribute("n"));					
						select.onchange = function(thiz,node){ return function()
							{
								thiz.onComboObjectChangeHandler(node);
							};
						}(this,nodeProp);

						//td2.appendChild( select )
						newCell1.appendChild(select);
					
						//cmbInp.addEventListener(IndexChangeEvent.CHANGE,onComboObjectChangeHandler);
						
						let button = document.createElement('input');
						button.classList.add('button-secondary');
						button.setAttribute("type","button");
						button.setAttribute("value","...");
						button.style.cssText="width:30px;font-size:9pt;margin:0px;padding:0px;height:100%;";
						button.onclick=function(thiz,val){
							return function(){
								thiz.SelectObjects(val);
							};
						}(this,nodeProp.getAttribute("n"));
						newCell2.appendChild(button);

						td2.appendChild( table );

						//send a request for data (Only if creating a new record (if editing then requesting data only needs to come from the data itself because the data in the hung lists will receive data 2 times))
						/*let nTypeF = findFirstNode(nodeProp, "type");
						if(nTypeF != null) //Запрос с параметрами не можем отправить без подгрузки данных
						{
							//Add parameters to request
							nTypeF.setAttribute("c",nodeProp.getAttribute("FieldCaption"));
							nTypeF.setAttribute("pn",nodeProp.getAttribute("n"));

							let strXMLF = getXMLNodeSerialisation(nTypeF);
							let nColF=nodeProperties.firstChild;
							while(nColF != null)
							{
								if(nColF.nodeName==="prop")
								{
									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
						{							
							let xml='<?xml version="1.0" encoding="utf-8"?><metadata fn="6"><type n="'+nodeProp.getAttribute("ot")+'" c="'+nodeProp.getAttribute("FieldCaption")+'" pn="'+nodeProp.getAttribute("n")+'" fn="'+nodeProp.getAttribute("fn")+'"></type></metadata>';
							if(this.request.callServer(ScriptName,xml,true));
							{
								this.showProgressBar();
							}
						}*/
					}else
					{
						let table=document.createElement('table');
						table.style.cssText="width:100%;border-spacing:0;border-collapse:collapse;border:0px;";
						let newRow=table.insertRow(0); //add a row to the created table
						let newCell1 = newRow.insertCell(0); //in the created line we add a column
						newCell1.style.cssText="padding:0px;width: 100%;";
						let newCell2 = newRow.insertCell(1); //in the created line we add a column
						newCell2.style.cssText="padding:0px;";

						//two elements are placed in the table
						input = document.createElement('input');
						input.classList.add('DBMS');
						//After pressing "Enter" we pass the entered line to the server.
						input.onkeydown=this.onCallFV(nodeProp.getAttribute("ot"),nodeProp.getAttribute("FieldCaption"),input,nodeProp.getAttribute("n"),nodeProp.getAttribute("fn"));
						input.style.cssText="width: 100%; height:22px; line-height: 22px;";
						input.setAttribute("type","text");
						input.setAttribute("id","prop_"+this.uid+"_"+nodeProp.getAttribute("n")+"_visible");
						input.setAttribute("value","");
						newCell1.appendChild(input);
						//The hidden field where the data is saved (you can make it stored in XML)_
						let hidden = document.createElement('input');
						hidden.setAttribute("type", "hidden");
						hidden.setAttribute("id","prop_"+this.uid+"_"+nodeProp.getAttribute("n"));
						hidden.value=value;
						newCell1.appendChild(hidden);
						let button = document.createElement('input');
						button.classList.add('button-secondary');
						button.setAttribute("type","button");
						button.setAttribute("value","...");
						button.style.cssText="width:30px;font-size:9pt;margin:0px;padding:0px;";
						button.onclick=function(thiz,val){return function(){thiz.SelectObjects(val);};}(this,nodeProp.getAttribute("n"));
						newCell2.appendChild(button);

						td2.appendChild( table );
						//We request the field title by the field id (if it is filled).
						/*if ((value!="")&&(value!=-1))
						{
							let xml='<?xml version="1.0" encoding="utf-8"?><metadata fn="6"><type n="'+nodeProp.getAttribute("ot")+'" c="'+nodeProp.getAttribute("FieldCaption")+'" pn="'+nodeProp.getAttribute("n")+'" fn="'+nodeProp.getAttribute("fn")+'" id="'+value+'">';
							xml+='<objects-list><filter><column n="'+findFirstNode(this.nodeMetadata, 'type').getAttribute('ObjectID')+'"><![CDATA['+value+']]></column></filter></objects-list>';
							xml+='</type></metadata>';
							if(this.request.callServer(ScriptName,xml,true))
							{
								this.showProgressBar();
							}
						}*/
					}
				}else
				if(vt==="text") {
					let ta = document.createElement('textarea')
					ta.classList.add('DBMS');
					ta.setAttribute("id", "prop_" + this.uid + "_" + nodeProp.getAttribute("n"));
					ta.style.cssText = "width: 100%;";
					ta.setAttribute("rows", 4);
					ta.setAttribute("name", nodeProp.getAttribute("n"));
					ta.setAttribute("value", value);
					td2.appendChild(ta);

				}else
				if(vt==="html"){
					let ta = document.createElement('textarea')
					ta.classList.add('DBMS');
					ta.setAttribute("id", "prop_" + this.uid + "_" + nodeProp.getAttribute("n"));
					ta.style.cssText = "width: 100%;";
					ta.setAttribute("rows", 4);
					ta.setAttribute("name", nodeProp.getAttribute("n"));
					ta.setAttribute("value", value);
					td2.appendChild(ta);

					/*let cdv=document.createElement('div');
					cdv.innerHTML+='<a href="javascript:;" onclick="return showTinyMCE(\'prop_'+this.uid+'_'+nodeProp.getAttribute("n")+'\');">[Show]</a>';
					cdv.innerHTML+=' <a href="javascript:;" onclick="tinyMCE.get(\'prop_'+this.uid+'_'+nodeProp.getAttribute("n")+'\').hide(); return false;">[Hide]</a>';
					td2.appendChild( cdv );*/
				}else
				if(vt==="blob" || vt==="file")
				{
					let ifr=createIFrame("prop_"+this.uid+"_"+nodeProp.getAttribute("n")+'_frm', ScriptUName+"?fn=9", td2, false); //IFrame to send the file to the server.
					document.body.appendChild(ifr);

					let tbl_b=document.createElement('table');
					tbl_b.style.cssText="width:100%;border-spacing:0;border-collapse:collapse;border:0px;";
					let newRow=tbl_b.insertRow(0);
					let newCell1 = newRow.insertCell(0);
					newCell1.style.cssText="padding:0px;width: 100%;";
					let newCell2 = newRow.insertCell(1);
					newCell2.style.cssText="padding:0px;";
					let newCell3 = newRow.insertCell(2);
					newCell3.style.cssText="padding:0px;";
					let newCell4 = newRow.insertCell(3);
					newCell4.style.cssText="padding:0px;";

					//Two elements are placed in the table
					let input = document.createElement('input');
					input.classList.add('dbms');
					//After pressing Enter we pass the entered line to the server
					//input.onkeydown=this.onCallFV(nodeProp.getAttribute("ot"),nodeProp.getAttribute("FieldCaption"),input,nodeProp.getAttribute("n"),nodeProp.getAttribute("fn"))
					input.style.cssText="width: 100%; color: #777777;";
					input.setAttribute("type","text");
					input.setAttribute('readonly','readonly');
					input.setAttribute("id","prop_"+this.uid+"_"+nodeProp.getAttribute("n"));
					//input.setAttribute("value","")
					newCell1.appendChild(input);
					
					//Button to send the file to the server
					let btnSel = document.createElement('input');
					btnSel.classList.add('button-secondary');
					btnSel.setAttribute("type","button");
					btnSel.setAttribute("value","...");
					btnSel.setAttribute("title",trt('Upload'));

					btnSel.style.cssText="width:30px;font-size:9pt;margin:0px;padding:0px;";
					newCell2.appendChild(btnSel);

					let button2 = document.createElement('input');
					button2.classList.add('button-secondary');
					button2.className='button-secondary';
					button2.setAttribute("type","button");
					button2.setAttribute("value","X");
					button2.setAttribute("title",trt('Delete'));
					button2.style.cssText="height:22px;width:22px;margin:0px;padding:0px;";
					button2.onclick=function(inp,ifr){return function(){ inp.value=''; getIframeDocument(ifr).forms["form"].reset(); }}(input,ifr);
					newCell3.appendChild(button2);

					//Download button
					newCell4.innerHTML='<form action="'+ScriptDName+'" method="get" style="display:inline;" target="_blank"><input type="hidden" name="fn" value="10"/><input type="hidden" name="n" value="'+nodeProp.getAttribute('cd')+'"/><input type="hidden" name="t" value="'+nodeType.getAttribute('n')+'"/><input type="hidden" name="f" value="'+nodeProp.getAttribute('n')+'"/><input type="hidden" name="i" value="'+record_id+'"/><input class="button-secondary" style="height:22px;width:22px;" type="submit" title="'+trt('Download')+'" value="D" /></form>'

					td2.appendChild( tbl_b );

					//Send file through iframe
					ifr.onload=function(btn,inp,obj)
					{
						return function()
						{	let doc=getIframeDocument(this);
							btn.onclick=function(doc){return function(){doc.forms["form"].elements["file"].click()}}(doc) //Enable file selection by pressing
							doc.forms["form"].elements["file"].onchange = function(inp) {return function(){inp.value=this.files[0].name;/*this.value;*/};}(inp);

							if(BeforeFirst(doc.body.innerHTML,'=')=='ok')
							{
								let fName=BeforeFirst(AfterFirst(doc.body.innerHTML,'='),"\n");
								inp.value=fName;//BeforeLast(inp.value,'.')+'_'+fName;
								if(inp.value!='')
								{	obj.sendData();
								}
							}
						};
					}(btnSel,input,this);

				}else
				if(vt==="date" || vt==="dateTime")
				{
					let table=document.createElement('table');
					table.style.cssText="width:100%;border-spacing:0;border-collapse:collapse;border:0px;";
					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;";

					let input = document.createElement('input');
					input.classList.add('DBMS');
					input.style.cssText="width: 100%;";
					input.setAttribute("type","text");
					input.setAttribute("name",nodeProp.getAttribute("n"));
					input.setAttribute("value",value);
					input.setAttribute("id","prop_"+this.uid+"_"+nodeProp.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 );

					if(vt==="date")
						new Calendar({
								  inputField: input,
								  dateFormat: "%Y-%m-%d",
								  trigger: img,
								  align: "Tl",
								  bottomBar: false,
								  showTime: false,
								  onSelect: function() {
										  this.hide();
								  }
						});
					if(vt==="dateTime")
						new Calendar({
								  inputField: input,
								  dateFormat: "%Y-%m-%d %H:%M:%S",
								  trigger: img,
								  align: "Tl",
								  bottomBar: false,
								  showTime: true,
								  onSelect: function() {
										  this.hide();
								  }
						});
				}else
				{
					let input = document.createElement('input');
					input.classList.add('DBMS');
					input.style.cssText="width: 100%;";
					input.setAttribute("type","text");
					input.setAttribute("name",nodeProp.getAttribute("n"));
					input.setAttribute("value",value);
					input.setAttribute("id","prop_"+this.uid+"_"+nodeProp.getAttribute("n"));
					td2.appendChild( input );
				}
			}
			nodeProp=nodeProp.nextSibling;
		}
		//Button apply
		let tr = document.createElement('tr');
		let td = document.createElement('td');

		//Button apply
		tr = document.createElement('tr');
		td = document.createElement('td');
		td.style.cssText="padding: 5px; vertical-align: bottom;";
		td.setAttribute("colspan", "2");
		if (this.record_id==-1) td.innerHTML='<div id="add_plase_'+this.uid+'" style="float: left; white-space: nowrap;"><label><input id="readd_'+this.uid+'" type="checkbox"> '+trt('Repeat_the_addition_of_the_entry')+'</label></div>';
		else td.innerHTML='<div id="add_plase_'+this.uid+'" style="float: left; white-space: nowrap;"></div>'; 
		tr.appendChild(td);
		//let td = document.createElement('td');
		td.setAttribute("align","right");		
		let button = document.createElement('input');
		button.classList.add('button-secondary');
		button.setAttribute("type","button");
		button.style.cssText="margin:0px;margin-right:1px;";
		button.setAttribute("value",trt('Apply'));
		button.onclick=()=>this.sendData();
		td.appendChild( button );
		
		button = document.createElement('input'); //Button cancel
		button.classList.add('button-secondary');
		button.setAttribute("type","button");
		button.style.cssText="margin:0px;";
		button.setAttribute("value",trt('Cancel'));
		//button.onclick=function f_exit(this) { alert2(trt('Alert'),this.win.div);  }
		button.onclick=()=>this.win.Close();
		td.appendChild( button );
		tr.appendChild(td);
		eTable.tBodies[0].appendChild(tr);

		//Height adjust the height of the page
		//this.win.div.style.width="400px"
		//this.win.div.style.height="100px"
		//alert2(trt('Alert'),document.documentElement.scrollTop)
		//alert2(trt('Alert'),document.documentElement.clientHeight)
		
		this.win.setHeight(eTable.offsetHeight+40); //this.win.div.style.height=(eTable.offsetHeight+40)+"px";
		
		//alert2(trt('Alert'),this.win.div.style.width)
		//alert2(trt('Alert'),this.win.div.style.height)


		this.win.setCenter();
		//this.win.div.style.left=(document.documentElement.scrollLeft+(document.documentElement.clientWidth-parseInt(this.win.div.style.width))/2)+"px"
		//this.win.div.style.top=(document.documentElement.scrollTop+(document.documentElement.clientHeight-parseInt(this.win.div.style.height))/2)+"px"

		//Initialization
		if (this.record_id<0)
		{
			this.callDataSelect();
			this.fillGUIFromXML();
		}else
		{
			if(this.request.callServer(ScriptName,'<?xml version="1.0" encoding="utf-8"?><metadata fn="5"><type id="'+this.record_id+'" n="'+type_name+'" ObjectID="'+nodeType.getAttribute("ObjectID")+'"></type></metadata>',true))
			{
				this.showProgressBar();
			}
		}
	};

	//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 re-query the data
		let nodeType=findFirstNode(this.nodeMetadata, "type");
		let nodeProperties=findNodeOnPath(this.nodeMetadata, 'type/properties');
		if(nodeProperties!=null) //Creating HTML elements by XML filter
		{
			let nodeProp=nodeProperties.firstChild;
			while (nodeProp != null)
			{
				if (nodeProp.nodeName==="prop")
				{
					let nTypeF = findFirstNode(nodeProp, "type");
					if(nTypeF != null)
					{
						//Add parameters to request
						nTypeF.setAttribute("c",nodeProp.getAttribute("FieldCaption"));
						nTypeF.setAttribute("pn",nodeProp.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=nodeProperties.firstChild;
							while(nColF != null)
							{
								if(nColF.nodeName==="prop")
								{
									let elm=document.getElementById('prop_'+this.uid+'_'+nColF.getAttribute("n"));
									if(elm!=null)
									{
										let valF=elm.value;
										strXMLF=strXMLF.replace('${'+nColF.getAttribute('n')+'}', valF);
									}
								}
								nColF = nColF.nextSibling;
							}
							
							//Сохраняю новое значение в XML так как оно не сохранится после пересоздания выпадающего списка
							let option=document.getElementById("prop_"+this.uid+"_"+node.getAttribute("n"));
							setCdataValue(node,0,option.value);

							strXMLF='<?xml version="1.0" encoding="utf-8"?><metadata fn="6">'+strXMLF+'</metadata>';
							if(this.request.callServer(ScriptName,strXMLF,true))
							{
								this.showProgressBar();
							}
						}
						
					}
				}
				nodeProp = nodeProp.nextSibling;
			}
		}
	}
	
	//Request data to fill the "Object" field.
	//The result can fill the filter field with complete information or display a window with a further selection of the value.
	selObj(typeName,propname)
	{
		let win=new TWin();
		win.BuildGUI(pageX-10,pageY-10);
		let str=`
			<table id="thetable`+win+`" bgcolor="SlateGrey" style="border: 1px solid rgb(99, 99, 99);" width="100%">
				<caption></caption>
				<thead><tr><th></th></tr></thead>
				<tbody><tr><td></td></tr></tbody>
			</table>`;
		win.setContent(str);
	};
	
	//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(propname)
	{
		let nodeProp=findNodeOnPath(this.nodeMetadata, "type/properties/prop[@n='"+propname+"']");
		if(nodeProp!=null)
			this.callWindowF(nodeProp);
	}

	//Call the ShowRecord window with the parameters for the filter (not just the object name).
	callWindowF(nodeProp)
	{
		let settings="";
		let TypeName="";
		let nT=findNode(nodeProp, "type");
		if(nT!=null)
		{
			settings=getXMLNodeSerialisation(nT);
			TypeName = nT.getAttribute("n");
		}else
		{
			TypeName=nodeProp.getAttribute("ot");
		}
		//Write to XML string from GUI
		while(true)
		{
			let sub1=BeforeFirst(settings,"${");
			if(sub1==null) break;
			let sub2=AfterFirst(settings,"}");
			if(sub2==null) break;
			let val=BeforeFirst(AfterFirst(settings,"${"),"}");
			
			let obj=document.getElementById("prop_"+this.uid+"_"+val);
			if(obj!=null){
				settings=sub1+obj.value+sub2;
			}else{
				settings=sub1+sub2;
			}
		}

		let rec=new SRec();
		rec.opener=this;
		rec.create(null);
		rec.f_State=1;
		rec.f_PropName=nodeProp.getAttribute("n");
		rec.f_Settings=settings;
		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="'+TypeName+'"></type></metadata>'))
		{
			rec.showProgressBar();
		}
	};

	//Запросить данные для выпадающих списков и других объектов (только после загрузки данных полей)
	callDataSelect()
	{
		let nodeProperties=findNodeOnPath(this.nodeMetadata, 'type/properties');
		let nodeProp=nodeProperties.firstChild;
		while(nodeProp!=null)
		{
			if(nodeProp.nodeName=="prop")
			{
				if(nodeProp.getAttribute("vt")=="object")
				{
					if(nodeProp.getAttribute("selector")=="combo")
					{
						let nTypeF = findFirstNode(nodeProp, "type");
						if(nTypeF != null) //Запрос с параметрами не можем отправить без подгрузки данных
						{
							//Add parameters to request
							nTypeF.setAttribute("c",nodeProp.getAttribute("FieldCaption"));
							nTypeF.setAttribute("pn",nodeProp.getAttribute("n"));

							let strXMLF = getXMLNodeSerialisation(nTypeF);
							let nColF=nodeProperties.firstChild;
							while(nColF != null)
							{
								if(nColF.nodeName==="prop")
								{
									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
						{
							let xml='<?xml version="1.0" encoding="utf-8"?><metadata fn="6"><type n="'+nodeProp.getAttribute("ot")+'" c="'+nodeProp.getAttribute("FieldCaption")+'" pn="'+nodeProp.getAttribute("n")+'" fn="'+nodeProp.getAttribute("fn")+'"></type></metadata>';
							if(this.request.callServer(ScriptName,xml,true));
							{
								this.showProgressBar();
							}
						}
					}else
					{
						//We request the field title by the field id (if it is filled).
						/*if ((value!="")&&(value!=-1))
						{
							let xml='<?xml version="1.0" encoding="utf-8"?><metadata fn="6"><type n="'+nodeProp.getAttribute("ot")+'" c="'+nodeProp.getAttribute("FieldCaption")+'" pn="'+nodeProp.getAttribute("n")+'" fn="'+nodeProp.getAttribute("fn")+'" id="'+value+'">';
							xml+='<objects-list><filter><column n="'+findFirstNode(this.nodeMetadata, 'type').getAttribute('ObjectID')+'"><![CDATA['+value+']]></column></filter></objects-list>';
							xml+='</type></metadata>';
							if(this.request.callServer(ScriptName,xml,true))
							{
								this.showProgressBar();
							}
						}*/
					}
				}
			}
			nodeProp=nodeProp.nextSibling;
		}
	}
	
	//Function to populate the drop-down lists
	setDataSelect(node)
	{
		let prop_name,prop,option,nodeProp,id,value,cdataNode;
		let nodeType=findFirstNode(node, 'type');
		prop_name=nodeType.getAttribute("pn"); //field name
		prop=document.getElementById("prop_"+this.uid+"_"+prop_name);
		if(prop==null) return;

		let selector=null; //find what kind of object object
		let nodeFilter=findFirstNode(this.nodeMetadata, 'properties');
		let nodeCur=nodeFilter.firstChild;
		while(nodeCur!=null)
		{
			if((nodeCur.nodeName=="prop")&&(nodeCur.getAttribute("n")==prop_name))
			{
				selector=nodeCur.getAttribute("selector");
			}
			nodeCur=nodeCur.nextSibling;
		}

		if(selector=="combo") //if the drop-down list
		{
			prop.innerHTML = ""; //Закоментил потому что нужно именно обновлять а то выборка слетит при выборе....
			
			//in the full can be that the list has arrived after the arrival of all data and therefore the drop-down list must be set to the desired value here
			//select the value for this list
			let val=null;
			let nodeProperties=findFirstNode(this.nodeMetadata, 'properties');
			nodeProp=nodeProperties.firstChild;
			while(nodeProp!=null)
			{
				if((nodeProp.nodeName=="prop")&&(nodeProp.getAttribute("n")==prop_name))
				{
					val=getCdataValue(nodeProp);
					break;
				}
				nodeProp=nodeProp.nextSibling;
			}
			//log.info('Значение в XML '+prop_name+'='+val);

			//The first line in the select as NULL value = 1
			option = document.createElement('option');
			option.setAttribute("value","");
			option.appendChild( document.createTextNode(""));
			option.selected = true;
			
			if(prop!=null)
			{
				prop.appendChild( option );

				nodeProp=nodeType.firstChild;
				while (nodeProp!=null)
				{
					if (nodeProp.nodeName=="record")
					{
						id=nodeProp.getAttribute("id");
						let caption="";
						cdataNode = nodeProp.firstChild;
						while (cdataNode!=null)
						{
							if (cdataNode.nodeName=="#cdata-section")
							{
								caption+=cdataNode.nodeValue+" "; 
								//break;
							}
							cdataNode = cdataNode.nextSibling
						}
						option = document.createElement('option');
						//option.style.color="graytext"
						option.setAttribute("value",id);
						option.appendChild(document.createTextNode(caption));
						//log.info('id='+id+' val='+val);
						if (id==val) option.selected=true;
						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) alert2(trt('Alert'),trt("No_results_were_found_for_your_search"));
			else
			if(count==1) //1 item has been selected, fill in the field.
			{
				nodeProp=findFirstNode(nodeType, 'record');
				id=nodeProp.getAttribute("id");
				value=findNode(nodeProp, '#cdata-section').nodeValue;
				prop.value=id;
				let propvis=document.getElementById("prop_"+this.uid+"_"+prop_name+"_visible");
				propvis.value=value;
				propvis.select();
			}else
			if(count>1) //Display the item selection window.
			{
				let htmlString='<table width="100%" bgcolor="whitesmoke">';
				nodeProp=nodeType.firstChild;
				let i=0;
				while (nodeProp!=null)
				{
					if (nodeProp.nodeName=="record")
					{
						let bgColor='whitesmoke';
						if (i%2==0) bgColor='white';
						id=nodeProp.getAttribute("id");
						value=findNode(nodeProp, '#cdata-section').nodeValue;
						value=value.replace(/"/g, "&quot;");
						value=value.replace(/'/g, "\\'");
						value=value.replace(/\n/g, " ");
						htmlString+='<tr><td bgColor="'+bgColor+'" onClick="setPropVal('+this.uid+',\''+id+'\',\''+value+'\',\''+prop_name+'\');" style="cursor: pointer;">'+findFirstNode(nodeProp, '#cdata-section').nodeValue+'</td></tr>'+"\n";
						i++;
					}
					nodeProp=nodeProp.nextSibling;
				}
				htmlString+='</table>';

				let win=new TWin();
				win.BuildGUI(pageX-280,pageY-7);
				win.setContent(htmlString);
				win.setCaption(document.createTextNode(trt("Selection")));
				win.setParent(this.win);
				//win.obj=this
			}
		}
	};

	applyReq(req,fn,node,xmldoc,win)
	{
		this.hideProgressBar();

		if(node.errorCode>0) {
			let fullText = node.errorMessage;
			let smallText = '';
			let pos1=fullText.indexOf('[[');
			let pos2=fullText.indexOf(']]');
			if(pos1>=0 && pos2>=0 && pos1<pos2) smallText=fullText.substring(pos1+2, pos2);

			if(fullText.indexOf("id456[[")>=0){ //Если есть идентификатор того что это перезапись
				let okFunc=()=>{
					this.setValue('seq',0);
					this.sendData(); //Применить ещё раз
				};
				if (smallText != '')
					confirm2(trt('Warning'),smallText, fullText, okFunc, null);
				else
					confirm2(trt('Warning'),smallText, '', okFunc, null);
			}else {
				if (smallText != '')
					alert2(trt('Alert'), smallText, fullText);
				else
					alert2(trt('Alert'), fullText);
			}
			return;
		}

		if (fn==0) {
			this.eRecNo(node,this.record_id);
		} else
		if (fn==1) { //returned id
			this.insertRows(node);
		} else
		if (fn==2) { //Returned id and type of updated record
			this.updateRows(node);
		} else
		if (fn==3) { //Returned id of deleted record
			this.deleteRows(node);
		} else
		if (fn==5) {
			this.setData(node);
		} else
		if (fn==6) { //Fill in the drop-down lists.
			this.setDataSelect(node);
		} else
		if (fn==7) {
			this.setData(node);
		} else {
			alert2(trt('Alert'),"Unknown function! fn=\""+fn+"\"" );
		}
	};
	/**
	 * Request data to fill in the field with the button
	 *
	 * @filter - xml text: filter settings
	 * @return null
	*/
	setFilterObject(TypeName, prop_id, id, filter)
	{
		let node=findFirstNodeOnAttribute(this.nodeMetadata,'prop','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 id of the record.
			let prop=document.getElementById("prop_"+this.uid+"_"+prop_id);
			if(prop!==null) prop.value = id;
			//Request a comment on the record id from the server
			let xml = '';
			if(filter!=null){
				//Настройка для последующего вызова формы через кнопку
				xml='<prop n="'+prop_id+'"><type n="' + TypeName + '"><objects-list>'+getXMLNodeSerialisation(filter)+'</objects-list></type></prop>';
				applyNodeToNode(CreateXMLDOC(xml).documentElement, node, "n");

				//Для запроса списка значений для выпадающего списка
				xml = '<?xml version="1.0" encoding="utf-8"?>' +
					'<metadata fn="6"><type n="' + TypeName + '" c="' + name + '" pn="' + prop_id + '" fn="' + name + '">' +
					'<objects-list>' + getXMLNodeSerialisation(filter) + '</objects-list>' +
					'</type></metadata>';
			}else{
				xml = '<?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>';
			}

			if(this.request.callServer(ScriptName,xml,true))
			{
				this.showProgressBar();
			}
		}else
		{
			alert2(trt('Alert'),'Field "'+prop_id+'" not find!');
		}
	};

	//We request from the server a list of values almost as for a drop-down list
	//typeName - Object name
	//name - The name of the column for selecting values (must match the name of any filter in typeName)
	//value - Filter value text box
	//htmlid - The name of the field in the filter n
	//filterName - filter name
	callFilterVal(typeName,name,value,htmlid,filterName)
	{
		//alert2(trt('Alert')," typeName="+typeName+" name="+name+" value="+value+" htmlid="+htmlid);
		if(value!="")
		{
			let xml='<?xml version="1.0" encoding="utf-8"?><metadata fn="6"><type n="'+typeName+'" c="'+name+'" pn="'+htmlid+'"><objects-list><filter>';
			xml+='<column n="'+filterName+'"><![CDATA['+value+']]></column>';
			xml+='</filter></objects-list></type></metadata>';
			if(this.request.callServer(ScriptName,xml,true))
			{
				this.showProgressBar();
			}
		}
	};
	
	onCallFV(typeName,name,value,htmlid,filterName)
	{
		let win=this
		return function(e){
			if(e==null) e=window.event;
			if(e.keyCode==13){
				win.callFilterVal(typeName,name,value.value,htmlid,filterName);
				return false;
			}
		}
	};

	//Fill the Metadata XML node with the XML values from the received XML node
	setData(node)
	{
		if(typeof(node) != "undefined" && node!=null)
		{
			let nProps1=findFirstNode(node, 'properties')
			let nProps2=findFirstNode(this.nodeMetadata, 'properties') //Since the values came in abbreviated XML
			if(nProps1==null){ alert2(trt('Alert'),'Error, node='+getXMLNodeSerialisation(node)); return; }
			if(nProps2==null){ alert2(trt('Alert'),'Error, nodeMetadata='+getXMLNodeSerialisation(this.nodeMetadata)); return; }
			let nProp1=nProps1.firstChild
			while(nProp1!=null)
			{
				if (nProp1.nodeName=="prop")
				{
					let nProp2=findNodeOnAttribute(nProps2,"prop","n",nProp1.getAttribute("n"))
					if(nProp2!=null) getCdata(nProp2).nodeValue=getCdata(nProp1).nodeValue
				}
				nProp1=nProp1.nextSibling;
			}//nodeMetadata filled with data
		}

		this.callDataSelect(); //Запрашиваем выпадающие списки (после загрузки полей)
		this.fillGUIFromXML(); //Заполняю GUI элементы из XML
	};
	
	//I rewrite values from XML to GIU fields
	fillGUIFromXML()
	{
		let nodeProperties=findFirstNode(this.nodeMetadata, 'properties');
		let nodeProp=nodeProperties.firstChild;
		while (nodeProp!=null)
		{
			if (nodeProp.nodeName=="prop")
			{
				let value=getCdata(nodeProp).nodeValue;
				//log.info("name = "+nodeProp.getAttribute("n")+" value= "+value);

				if ((value=="true")||(value=="t")) value=1;
				if ((value=="false")||(value=="f")) value=0;
				
				if(typeof nodeProp.field == "undefined") //Если не специализированное поле а обычные HTML поля
				{
					let field=document.getElementById("prop_"+this.uid+"_"+nodeProp.getAttribute("n"));
					if(field!=null)
					{
						field.value=value;

						//For entries of the type of a whip, we request a comment on the id field, for the list, add the desired value.
						if(nodeProp.getAttribute("vt")=="object")
						{
							if(nodeProp.getAttribute("selector")=="combo")
							{
								//We sort out the elements of the list (options) and set it to the desired value (the snake is not automatically exposed by the automaton).
								for(let i=0;i<field.options.length;i++)
								{
									if(field.options[i].value==value)
									{
										field.options[i].setAttribute("selected",true);
									}
								}
							}else//Field with a button, request a comment to the field by the record id.
							{
								if ((value!="")&&(value!=-1))
								{
									let xml='<?xml version="1.0" encoding="utf-8"?><metadata fn="6"><type n="'+nodeProp.getAttribute("ot")+'" c="'+nodeProp.getAttribute("FieldCaption")+'" pn="'+nodeProp.getAttribute("n")+'" fn="'+nodeProp.getAttribute("fn")+'" id="'+value+'">';
									xml+='<objects-list><filter><column n="'+findFirstNode(this.nodeMetadata, 'type').getAttribute('ObjectID')+'"><![CDATA['+value+']]></column></filter></objects-list>';
									xml+='</type></metadata>';
									if(this.request.callServer(ScriptName,xml,true))
									{
										this.showProgressBar();
									}
								}
							}
						}
					}
				}else{
					//For special fields
					nodeProp.field.setValue(value);
				}
			}
			nodeProp=nodeProp.nextSibling;
		}
	};
	//Move data from html fields to an XML string and send to edit or update
	sendData()
	{
		let nodeProperties;
		let nodeProp;
		//Send binary data sequentially for each field
		nodeProperties=findFirstNode(this.nodeMetadata, 'properties');
		nodeProp=nodeProperties.firstChild;
		let sending=false;
		while (nodeProp!=null)
		{
			if (nodeProp.nodeName=="prop" && (nodeProp.getAttribute("vt")=="blob" || nodeProp.getAttribute("vt")=="file"))
			{
				let frm=document.getElementById('prop_'+this.uid+'_'+nodeProp.getAttribute("n")+'_frm');
				let doc=getIframeDocument(frm);
				if(doc.forms["form"].elements["file"].value!='')
				{	doc.forms["form"].submit();
					sending=true;
				}
			}
			nodeProp=nodeProp.nextSibling;
		}
		if(sending) return;

		//Sending text data
		let nodeType=findFirstNode(this.nodeMetadata, 'type')
		let nodename=nodeType.getAttribute("n")
		let s="";
		s+='<?xml version="1.0" encoding="utf-8"?>\n';
		if (this.record_id!=-1) s+='<metadata fn="2">\n'; else s+='<metadata fn="1">\n';
		s+='<type n="'+nodename+'" id="'+this.record_id+'">\n';
		s+='	<properties>\n';
		nodeProperties=findFirstNode(this.nodeMetadata, 'properties')
		nodeProp=nodeProperties.firstChild
		while (nodeProp!=null)
		{
			if (nodeProp.nodeName=="prop")
			{
				let value="";
				if(typeof nodeProp.field == "undefined")
				{
					value=document.getElementById("prop_"+this.uid+"_"+nodeProp.getAttribute("n")).value;
					if((nodeProp.getAttribute("vt")=="object")&&(nodeProp.getAttribute("selector")!="combo"))
					{	
						if(document.getElementById("prop_"+this.uid+"_"+nodeProp.getAttribute("n")+"_visible").value=="")
							value="";
					}
					//log.info("name = "+nodeProp.getAttribute("n")+" value= "+value+" object = "+document.getElementById("prop_"+this.uid+"_"+nodeProp.getAttribute("n")));
				}else{
					//For special fields (look "TCheckboxListField" class)
					value=nodeProp.field.getValue();
				}
				
				//Проверяю тип дпнных и заполненость полей
				if (!this.checkData(value,nodeProp.getAttribute("vt"),nodeProp.getAttribute("maybenull")))
				{
					alert2(trt('Alert'),trt("The_field_data_is_incorrect")+" \""+nodeProp.getAttribute("d")+"\"=\""+value+"\"!");
					return;
				}
				s+='		<prop n="'+nodeProp.getAttribute("n")+'"><![CDATA['+value+']]></prop>\n';
			}
			nodeProp=nodeProp.nextSibling;
		}
		s+='	</properties>\n';
		s+='</type>\n';
		s+='</metadata>';
		//alert2(trt('Alert'),s);
		if(this.request.callServer(ScriptName,s,true))
		{
			this.showProgressBar();
		}
	};
	//Check the field according to its type
	checkData(value,type,maybenull)
	{
		//log.info("checkData value = "+value+" type= "+type+" maybenull = "+maybenull);		
		if(value==undefined) return false;
		if(type=="i4")
		{
			if((value=="")&&(maybenull==0)) return false;
			return isInt(value)
		}else
		if(type=="f8" || type=="f4")
		{
			if((value=="")&&(maybenull==0)) return false;
			return isFloat(value);
		}else
		if(type=="object")
		{
			if(((value=="-1")||(value==""))&&(maybenull==0)) return false;
		}else
		if((type=="string")||(type=="b")||(type=="dateTime"))
		{
			if((value=="")&&(maybenull==0)) return false;
		}
		return true;
	};
	//inserting the selected record
	setPropVal(id,caption,prop_id)
	{
		//alert2(trt('Alert'),"id="+id+" caption="+caption+" prop_id="+prop_id)
		let prop=document.getElementById("prop_"+this.uid+"_"+prop_id);
		let propvis=document.getElementById("prop_"+this.uid+"_"+prop_id+"_visible");
		if ((prop!=null)&&(propvis!=null))
		{
			prop.value=id;
			propvis.value=caption;
			propvis.select();
		}
	};
	//The data was successfully added to the parent now so that he added 1 entry to the end of his list.
	insertRows(node)
	{	//Update the parent
		let typeNode=findFirstNode(node,"type");
		let typeName=typeNode.getAttribute("n");
		this.record_id=typeNode.getAttribute("id"); //let id=typeNode.getAttribute("id");
		if (this.opener!=null)
		{
			if(this.opener.f_TypeName==typeName) //It would be better to make an array of open windows then check for all and not just for the parent.
			{
				this.opener.sendFilter(this.record_id,-1); //Update data by filter with id records.
			}
		}

		let readd=document.getElementById("readd_"+this.uid);
		if(readd!==null && readd.checked){
			confirm2(trt('Warning'),trt("Successfully_added_data")+"<br>"+trt("Add_more")+"?",'',()=>{this.record_id=-1},()=>this.win.Close());
		}else
		{
			this.win.Close();
		}
		if(this.onInserted!=null) this.onInserted(this);
	};

	//The data has been updated successfully now telling the parent to update the record.
	updateRows(node)
	{
		let typeNode=findFirstNode(node,"type");
		let typeName=typeNode.getAttribute("n");
		let id=typeNode.getAttribute("id");
		if (this.opener!=null)
		{
			if(this.opener.f_TypeName==typeName) //It would be better to make an array of open windows then check for everyone.
			{
				this.opener.sendFilter(id,-1); //Update data by filter with id records.
			}
		}
		this.win.Close();
		if(this.onUpdated!=null) this.onUpdated(this);
	};
}

//Поле с галочкой (или галочками)
class TCheckboxListField
{	
	constructor(name)
	{
		this.name=name;
		this.div = document.createElement('div');
		this.array = new Array();		
	}
	
	addCheckbox(value, name) {
		let input = document.createElement('input');
		input.classList.add('DBMS');

		this.array.push(input);

		input.setAttribute("type", "checkbox");
		input.setAttribute("value", value);

		let label = document.createElement("Label");
		// label.setAttribute("for",id_from_input);
		label.appendChild(input);
		label.appendChild(document.createTextNode(" " + name + " "));

		this.div.appendChild(label);
	};
	// Return checked values divide ";"
	getValue() {
		let result = "";
		for(let i=0;i<this.array.length;i++)
		{
			if(this.array[i].checked)
			{
				result+=this.array[i].value;//+';';
			}
		}
		return result;
	};
	// Set checked values divide ";"
	setValue(val) {
		let splits;
		if(val.indexOf(';')==-1)
			splits = val.split('');
		else
			splits = val.split(';');

		for(let j=0;j<splits.length;j++)
		{
			for(let i=0;i<this.array.length;i++)
			{
				if(this.array[i].value==splits[j])
				{
					this.array[i].checked=true;
				}
			}
		}
	};

	getDiv() {
		return this.div;
	};

}
