Files
Metadata_PHP/metadata/tree/tree.js
2024-07-24 10:05:45 +05:00

1064 lines
40 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//Copyright (C) Ivanov I.M.
//Site: http://www.tiptopcity.com/
//Элемент дерева (меню)
//node - Сам XML узел (Из чего создан)
//tree - Владелец
function TTreeNode(node,tree)
{
//Присвоить текст документа соответствующему HTML элементу
this.setCaption=function(val)
{ getCdata(this.node).nodeValue=val;
var obj=document.getElementById(this.tree.m_pr+'text'+this.node.getAttribute("htmlid"));
if(obj)
{
obj.innerHTML=" "+val+"\u00A0";
}
};
//Получить путь к данному узлу в виде строки
this.getTreePath=function()
{ var n=this;
var c='';
while(n!=null)
{
if(n.treeid=='' || n.fid=='') break; //Чтоб пропустить корень дерева
c=n.treeid+';'+n.fid+';'+c;
n=n.parent;
}
return c;
};
//Параметр из базы/XML по имени
this.getParam = function(name)
{
for (var i = 0; i < this.params.length; i++)
{
if(this.params[i][0]==name)
return this.params[i][1];
}
return '';
};
this.htmlid=getUID(); //HTML id
this.obj=null; //User data
this.node=node; //XML node
this.tree=tree; //Owner
this.parent=null; //Родительский TTreeNode
this.childs=new Array(); //Дочерние узлы TTreeNode
this.params=new Array(); //Параметры для под узлов
this.label='';
this.c='1'; //'1' то есть дети а если childs.length=0 то они ещё неподгружены
this.wch=false; //Ждём ли мы прихода детей
this.treeid=''; //Идентификатор ветки дерева
this.fid=''; //Идентификатор записи
this.ddl=false; //Раскрывать ли как выпадающий список в низ (drop down list)
}
/** Для меню должно подгружаться видемый и все не видимые под меню
* v_obj - main html object,
* v_scr - server script,
* v_imgpth - path to images (TODO удалить)
* v_treepath - Путь с которого отображать элементы дерева
*/
function TMenu(v_obj,v_scr,v_treepath) //Горизонтальное меню
{
// Начать загрузку данны
this.Start=function()
{
//if(typeof(this.m_treepath)=="undefined") this.m_treepath='-1';
var xml='<?xml version="1.0" encoding="utf-8"?><metadata fn="2" htmlid="0" treeid="-1"><columns></columns></metadata>';
this.callServer(this.m_scr,xml);
};
//отправить XML запрос на сервер
this.callServer=function(url,xmlString)
{
if(url=='' || xmlString=='') return;
var call=new myXMLHttpRequest(this);
call.callServer(url,xmlString);
};
//Построить дерево объектов TTreeNode из XML файла рекурсией (TODO XML потом удалять)
//nOs - родительский объект
//nTs - родительский XML
this.buildTree=function(nOs,nTs)
{
var nT=nTs.firstChild;
while(nT!=null)
{
if(nT.nodeName=="tree")
{
var nO=new TTreeNode(nT,this);
nO.label=getCdataValue(nT);
nO.c=nT.getAttribute("c");
nO.treeid=nT.getAttribute("treeid");
nO.fid=nT.getAttribute("fid"); // getCdata(findNodeOnAttribute(np, 'param','n',n.getAttribute('ObjectID'))).nodeValue;
nO.ddl=(nT.getAttribute("ddl") == "1");
//Переписываем параметры для под узлов
var nC=findNode(nT,'columns');
if(nC!=null) nC=nC.firstChild;
while(nC!=null)
{
if(nC.nodeName=='param')
{
var len=nO.params.length;
nO.params.push(new Array());
nO.params[len][0]=nC.getAttribute('n');
nO.params[len][1]=getCdataValue(nC);
}
nC=nC.nextSibling;
}
nO.parent=nOs;
nOs.childs.push(nO);
this.m_tn.push(nO);
nT.setAttribute("htmlid",nO.htmlid); //проставить уникальные HTML ID для детей узла
//!!!Рекурсия!!!
this.buildTree(nO,nT);
}
nT=nT.nextSibling;
}
};
//Найти TTreeNode узел по его htmlid
this.findNode=function(htmlid, treeid, fid)
{
if(typeof(htmlid)=='undefined') htmlid='';
if(typeof(treeid)=='undefined') treeid='';
if(typeof(fid)=='undefined') fid='';
for(var i=0;i<this.m_tn.length;i++)
{
if((htmlid=='' || htmlid==this.m_tn[i].htmlid) && (treeid=='' || treeid==this.m_tn[i].treeid) && (fid=='' || fid==this.m_tn[i].fid))
return this.m_tn[i];
}
return null;
};
//Пришли данные с сервера
this.processReqChange=function(xmlHttpRequest,url,xmlString)
{
//delay(1000)
if (typeof(xmlHttpRequest.readyState)=='undefined' || xmlHttpRequest.readyState == 4)
{
if(typeof(xmlHttpRequest.status)=='undefined' || xmlHttpRequest.status == 200) // only if "OK"
{
if(typeof(xmlHttpRequest.responseXML)=='undefined' && xmlHttpRequest.contentType.match(/\/xml/)) //For IE XDomainRequest
xmlHttpRequest.responseXML=CreateXMLDOC(xmlHttpRequest.responseText);
//загрузился xml документ начинаем его разбирать (по id функции в документе)
let xmldoc = xmlHttpRequest.responseXML;
if(xmldoc==null){
alert2(trt('Alert'),trt('Wrong_XML_document')+"!\n"+xmlHttpRequest.responseText);
return;
}
let node = xmldoc.documentElement;
//alert2(trt('Alert'),"Данные=\n"+xmlHttpRequest.responseText);
if((node==null)||(node.getAttribute("fn")==null)) alert2(trt('Alert'),trt('Error')+"\n"+trt('No_data')+"!\n"+xmlHttpRequest.responseText);
else
{
var fn = node.getAttribute("fn");
if (fn=='0')
{
alert2(trt('Alert'),findFirstNode(node,"#cdata-section").nodeValue);
}else if (fn=='1')
{
var tn=this.findNode(node.getAttribute("htmlid")); //Родительский узел
tn.wch=false; //Не ждём прихода детей
this.buildTree(tn,node); //Рекурсивно построить дерево объектов из XML
//Если контейнер видим то обновляем значения пересоздав его
var cnt=document.getElementById(this.m_pr+tn.htmlid+'tb');
if(cnt!=null) this.createList(tn.htmlid); //Создать HTML кнопки
}else if(fn=='2')
{
var tn=this.findNode(node.getAttribute("htmlid")); //Родительский узел
tn.wch=false; //Не ждём прихода детей
this.buildTree(tn,node); //Рекурсивно построить дерево объектов из XML
//Если контейнер видим то обновляем значения пересоздав его
var cnt=document.getElementById(this.m_pr+tn.htmlid+'tb');
if(cnt!=null) this.createList(tn.htmlid); //Создать HTML кнопки
}else
alert2(trt('Alert'),"Unknown function! fn=\""+fn+"\"" );
}
}else
{
alert2(trt('Alert'),trt('Failed_to_get_data')+"\n URL: "+url+"\n" + xmlHttpRequest.statusText);
}
}
};
//Создать список кнопок HTML (при наведении на кнопку эта же функция вызывается)
this.createList=function(htmlid)
{
//Ищем узел со списком кнопок которые мы должны создать
var ptn=null;
if(this.m_treepath!='') //Путь для пропуска узлов дерева
{
var mpath=this.m_treepath.split(';');
if(mpath.length>2)
{
ptn=this.findNode('',mpath[mpath.length-3],mpath[mpath.length-2]);
this.m_treepath='';
}
}
if(ptn==null) ptn=this.findNode(htmlid,'','');
//Ищем ищем родительскую кнопку чтоб задать положение для контейнера
var btn=document.getElementById(this.m_pr+htmlid+'bt'); //Кнопка родитель
var cnt=document.getElementById(this.m_pr+htmlid+'tb'); //Контейнер для создаваемых кнопок
delChild(cnt); //Удалить дочерние HTML элементы из контейнера
if(cnt==null) //Если контейнер не создан создаём его
{
cnt=document.createElement('div');
cnt.setAttribute('id',this.m_pr+htmlid+'tb');
cnt.style.cssText="display: inline-block; position: absolute; z-index: 999;";
if(btn!=null) //устанавливаем положение контейнера и задаём в качерстве родителя кнопку
{
var crd_m=ElemCoords(this.m_obj);
var coord=ElemCoords(btn);
coord.x=coord.x-crd_m.x;
coord.y=coord.y-crd_m.y;
if(ptn.ddl) //Если нужно отобразить как выпадающий список те. в низу
{
cnt.style.left='0px';
cnt.style.top=parseInt(btn.offsetHeight)+'px';
}else //Если как меню (TODO Если как дерево можно добавить)
{
//if(tn.node.parentNode.parentNode.nodeName!='tree')
//{
// coord.x+=parseInt(this.offsetWidth)
// coord.y+=parseInt(this.offsetHeight)
//}else
//{
coord.x+=parseInt(btn.offsetWidth);
//coord.y+=parseInt(this.offsetHeight)
//}
cnt.style.left=coord.x+'px';
cnt.style.top=coord.y+'px';
//cnt.style.display='inline-block';
//btn.appendChild(cnt); //Кнопка будет владельцем контейнера
}
}
this.m_obj.appendChild(cnt);
}
if(ptn.wch) //TODO проверить нужно или нет здесь
{
cnt.innerHTML='<nobr id="qwery"><img src="../resources/metadata/tree/icons/loading.gif" alt=" "><font color="#999999"><b> Подождите пожалуйста...</b></font></nobr>';
return;
}
for(var i=0;i<ptn.childs.length;i++) //Пробегаемся по дочерним текущего узла и создаём кнопки
{
var tn=ptn.childs[i];
//Создаём HTML кнопку
cdiv=document.createElement('div');
cdiv.setAttribute('id',this.m_pr+tn.htmlid+'bt');
cdiv.style.cssText="width: 100%; display: block;";
cnt.appendChild(cdiv);
//if(nodeTree.getAttribute('visible')=='0') cdiv.style.display='none'; //Видимость кнопки
//Ищем HTML шаблон для текущего узла если его нет поднимаемся выше и используем родительский
var str='';
var pn=tn;
while(pn!=null)
{
for(var j=0; j<this.m_patterns.length; j++)
{
if(this.m_patterns[j].id==pn.treeid)
{ str=this.m_patterns[j].str;
break;
}
}
if(str!='') break;
pn=pn.parent;
}
//Шаблон кнопки по умолчанию
if(str=='') str='<div style="border: 1px solid #dddddd;" onClick="window.location.href = \'./?path=${path}\'" onMouseOver="this.style.backgroundColor=\'#ffffff\'; this.style.textDecoration=\'underline\';" onMouseOut="this.style.backgroundColor=\'#dddddd\'; this.style.textDecoration=\'none\';"><table style="width: 100%;"><tr><td style="vertical-align: middle;"><nobr>&nbsp;&nbsp;<a href="?path=${path}" style="${select}">${name}</a>&nbsp;&nbsp;</nobr></td><td style="vertical-align: middle; width: 10px; padding-right: 4px;"><img src="./img/next.gif" alt="" align="right" style="vertical-align: middle; display: ${none};"></td></tr></table></div>';
str=str.replace(/\${path}/g, tn.getTreePath());
str=str.replace(/\${hash}/g, crc32(tn.getTreePath()));
str=str.replace(/\${name}/g, tn.label);
str=str.replace(/\${none}/g, tn.c=='1' ? 'block' : 'none');
for (var itn = 0; itn < tn.params.length; itn++)
{
if(tn.params[itn][1]!='')
{ str=str.replace(new RegExp("\\${"+tn.params[itn][0]+"}",'g'), tn.params[itn][1]);
}
}
str=str.replace(/\${url}/g, crc32(tn.getTreePath()));
//Если узел в пути отмечаем эту кнопку
if(this.m_path.indexOf(tn.treeid+';'+tn.fid+';')>=0)
{
str=str.replace(/\${select}/g, 'text-decoration: underline;');
}
cdiv.innerHTML=str;
cdiv.onmouseover=function(tn,thiz)
{ return function()
{
tn.tree.m_hide=0; //чтоб отменить функцию скрытия меню при наведении
//Строим массив TTreeNode от выделеного в верх по дереву
var tmp=new Array();
var pn=tn;//.parent;
while(pn!=null)
{ tmp.push(pn);
pn=pn.parent;
}
//Скрываем все элементы кроме родителей выделеного
for(var i=0;i<tn.tree.m_tn.length;i++)
{
var tnt=tn.tree.m_tn[i];
var del=true;
for(var j=0;j<tmp.length;j++) if(tmp[j]==tnt) { del=false; break;}
if(del)
{
var obj=document.getElementById(tn.tree.m_pr+tnt.htmlid+'tb');
if(obj!=null) deleteHTML(obj); //obj.style.display='none';
}
}
if(tn.c=='0') return; //если нет детей выходим
//Если данных нет то запрашиваем их и ставим признак ожидания
if(!tn.wch && tn.childs.length==0)
{
tn.wch=true; //Признак ожидания детей
xmlstring='<?xml version="1.0" encoding="utf-8"?><metadata fn="2" htmlid="'+tn.htmlid+'" treeid="'+tn.treeid+'"><columns>'
for(var i=0;i<tn.params.length;i++)
{
xmlstring+='<param n="'+tn.params[i][0]+'"><![CDATA['+tn.params[i][1]+']]></param>';
}
xmlstring+='</columns></metadata>';
tn.tree.callServer(tn.tree.m_scr,xmlstring);
}
thiz.createList(tn.htmlid); //Строим подменю
};
}(tn,this);
cdiv.onmouseout=function(tn)
{ return function()
{
tn.tree.m_hide=tn.htmlid;
//После потери фокуса ждём пол секунды и выполняем функцию по скрытию элементов
setTimeout(function(tn){ return function(){
if(tn.tree.m_hide==tn.htmlid)
{
for(i=0;i<tn.tree.m_tn.length;i++)
{
if(tn.tree.m_tn[i]!=tn.tree.m_root)
{
var obj=document.getElementById(tn.tree.m_pr+tn.tree.m_tn[i].htmlid+'tb');
if(obj!=null) deleteHTML(obj); //obj.style.display='none';
}
}
tn.tree.m_hide=0;
} }}(tn),500);
};
}(tn);
}
};
//Добавить узел в XML дерево
this.addNodes=function(node)
{
if(node==null) return;
var htmlid=node.getAttribute("htmlid"); //parent id
var pdiv=document.getElementById(this.m_pr+htmlid+'tb'); //Контейнер
if(pdiv==null) return;
delChild(pdiv);
var pnode=findFirstNodeOnAttribute(this.XMLTree,"tree","htmlid",htmlid);
var nodeTree=node.firstChild;
while(nodeTree!=null)
{
if(nodeTree.nodeName=="tree")
{
//Перемещяем пришедшие узлы дерева в основное дерево
nodeTree.parentNode.removeChild(nodeTree);
pnode.appendChild(nodeTree);
this.m_tn[this.m_tn.length]=new TTreeNode(nodeTree,this);
nodeTree.setAttribute("htmlid",this.m_tn[this.m_tn.length-1].htmlid); //проставить уникальные HTML ID для детей узла
//Ищем HTML шаблон для текущего узла если его нет поднимаемся выше и используем родительский
var str='';
var nTmp=nodeTree;
while(nTmp!=null)
{
if(nTmp.nodeName=="tree")
{
var tid=nTmp.getAttribute("treeid");
for(var i=0; i<this.m_patterns.length; i++)
{
if(this.m_patterns[i].id==tid)
{ str=this.m_patterns[i].str;
break;
}
}
}
if(str!='') break;
nTmp=nTmp.parentNode;
}
if(str=='') str='<div style="border: 1px solid #dddddd;" onClick="window.location.href = \'./?path=${path}\'" onMouseOver="this.style.backgroundColor=\'#ffffff\'; this.style.textDecoration=\'underline\';" onMouseOut="this.style.backgroundColor=\'#dddddd\'; this.style.textDecoration=\'none\';"><table style="width: 100%;"><tr><td style="vertical-align: middle;"><nobr>&nbsp;&nbsp;<a href="?path=${path}">${name}</a>&nbsp;&nbsp;</nobr></td><td style="vertical-align: middle; width: 10px; padding-right: 4px;"><img src="./img/next.gif" alt="" align="right" style="vertical-align: middle; display: ${none};"></td></tr></table></div>';
str=str.replace(/\${path}/g, this.m_tn[this.m_tn.length-1].getTreePath());
str=str.replace(/\${name}/g, getCdataValue(nodeTree));
str=str.replace(/\${none}/g, nodeTree.getAttribute("c")=='1' ? 'block' : 'none');
//создаём кнопку меню
cdiv=document.createElement('div');
cdiv.style.cssText="width: 100%; display: block;";
pdiv.appendChild(cdiv);
if(nodeTree.getAttribute('visible')=='0') cdiv.style.display='none';
cdiv.innerHTML=str;
cdiv.onmouseover=function(tn,cdiv,thiz)
{ return function()
{
tn.tree.m_hide=0;
var tmp=new Array();
var pn=tn.node.parentNode;
while(true)
{
if(pn==null || pn.nodeName!='tree') break;
tmp.push(tn.tree.m_pr+pn.getAttribute("htmlid")+'tb');
pn=pn.parentNode;
}
//Скрываем все элементы кроме родителей выделеного
for(i=0;i<tn.tree.m_tn.length;i++)
{
hid=tn.tree.m_pr+tn.tree.m_tn[i].node.getAttribute("htmlid")+'tb';
dis='none';
for(var j=0;j<tmp.length;j++) if(tmp[j]==hid) { dis='block'; break;}
obj=document.getElementById(hid);
if(obj!=null) obj.style.display=dis;
}
if(tn.node.getAttribute("c")=='0') return; //если нет детей выходим
//Получить
var crd_m=ElemCoords(thiz.m_obj); //Абсолютные коордионаты главного элемента
var coord=ElemCoords(cdiv); //Абсолютные коордионаты текущего элемента
coord.x=coord.x-crd_m.x;
coord.y=coord.y-crd_m.y;
//if(tn.node.parentNode.parentNode.nodeName!='tree')
//{
// coord.x+=parseInt(this.offsetWidth)
// coord.y+=parseInt(this.offsetHeight)
//}else
//{
coord.x+=parseInt(this.offsetWidth);
//coord.y+=parseInt(this.offsetHeight)
//}
var tb=document.getElementById(tn.tree.m_pr+tn.node.getAttribute("htmlid")+'tb');
if(tb==null)
{
tb=document.createElement('div');
tb.style.cssText="width: 100%; display: none; position: absolute; z-index: 999;";
tb.setAttribute('id',tn.tree.m_pr+tn.node.getAttribute("htmlid")+'tb');
tb.innerHTML='<nobr><img src="../resources/metadata/tree/icons/loading.gif" alt=" "><font color="#999999"><b> Подождите пожалуйста...</b></font></nobr>';
tn.tree.m_obj.appendChild(tb);
fid=tn.node.getAttribute("fid");
treeid=tn.node.getAttribute("treeid");
nodeName=tn.node.getAttribute("t");
nodeParameters=findFirstNode(tn.node,"columns");
//если нет ни одного дочернего tree то запрашиваем данные иначе раскрываем список
xmlstring='<?xml version="1.0" encoding="utf-8"?><metadata fn="2" htmlid="'+tn.node.getAttribute("htmlid")+'" treeid="'+treeid+'" fid="'+fid+'" n="'+nodeName+'">'+getXMLNodeSerialisation(nodeParameters)+'</metadata>';
tn.tree.callServer(tn.tree.m_scr,xmlstring);
}
tb.style.left=coord.x+'px';
tb.style.top=coord.y+'px';
tb.style.display='inline-block';
//При наведении запрашиваем под узлы если они ещё не загружены и небыли запрошены
//var pnode=findFirstNodeOnAttribute(tb,'nobr','id','qwerty')
/*nod=tn.node.firstChild
while(nod!=null)
{
if(nod.nodeName=='tree')
{
if(nod.getAttribute('c')=='1' && document.getElementById(tn.tree.m_pr+nod.getAttribute("htmlid")+'tb')==null)
{
fid=nod.getAttribute("fid")
treeid=nod.getAttribute("treeid")
nodeName=nod.getAttribute("t")
nodeParameters=findFirstNode(nod,"columns")
//если нет ни одного дочернего tree то запрашиваем данные иначе раскрываем список
xmlstring='<?xml version="1.0" encoding="utf-8"?><metadata fn="2" htmlid="'+nod.getAttribute("htmlid")+'" treeid="'+treeid+'" fid="'+fid+'" n="'+nodeName+'">'+getXMLNodeSerialisation(nodeParameters)+'</metadata>';
tn.tree.callServer(tn.tree.m_scr,xmlstring)
//TODO зделать табличку подождите пожалуйста
}
}
nod=nod.nextSibling
}*/
};
}(this.m_tn[this.m_tn.length-1],cdiv,this);
cdiv.onmouseout=function(tn)
{ return function()
{
tn.tree.m_hide=tn.htmlid;
setTimeout(function(tn){ return function(){
if(tn.tree.m_hide==tn.htmlid)
{
for(i=0;i<tn.tree.m_tn.length;i++)
{
var obj=document.getElementById(tn.tree.m_pr+tn.tree.m_tn[i].node.getAttribute("htmlid")+'tb');
if(obj!=null) obj.style.display='none';
}
tn.tree.m_hide=0;
} }}(tn),500)
}
}(this.m_tn[this.m_tn.length-1]);
//Информируем слушателей о загрузке узла
for(i=0;i<this.m_lsl.length;i++)
if(this.m_lsl[i]!=null) this.m_lsl[i].OnLoadNode(this.m_tn[this.m_tn.length-1]);
nodeTree=node.firstChild;
}else
nodeTree=nodeTree.nextSibling;
}
};
//Добавить слушателя нажатия на кнопку
this.addListener=function(listener)
{ if(listener.OnClickNode==null) alert2(trt('Alert'),'У объекта нет функции "OnClickNode()"!');
this.m_ls[this.m_ls.length]=listener;
};
//Удалить слушателя
this.remListener=function(listener)
{ for(var i=0;i<this.m_ls.length;i++)
{ if(this.m_ls[i]==listener)
this.m_ls[i]=null;
}
};
//Добавить HTML шаблон для постраения кнопок по id узла
this.addPattern=function(id,str)
{
var p={ "id":id, "str":str };
this.m_patterns.push(p);
};
//Выделить цветом узлы меню в соответствии с переданным путём
this.selectNodes=function(path)
{
this.m_path=path;
mas = path.split(';');
for(i=0;i<mas.length;i+=2)
{
var tn=this.findNode('',mas[i],mas[i+1]);
if(tn!==null)
{
var cdiv=document.getElementById(this.m_pr+tn.htmlid+'bt');
cdiv=findFirstNode(cdiv, 'a');
if(cdiv!==null)
{
cdiv.style.textDecoration='underline';
}
}
}
};
//Public:
this.m_patterns=new Array();
//Private:
this.m_obj=v_obj; //Main HTML object
this.m_pr='mnu'+getUID()+'_'; //Prefix for HTML ids
this.m_obj.innerHTML='<table id="'+this.m_pr+'table0" style="border: 0px solid rgb(0, 0, 0);" cellpadding="0px" cellspacing="0px"><caption></caption><thead></thead><tbody></tbody></table>';
this.m_scr=v_scr;
this.m_treepath=v_treepath; // Стартовый путь
this.m_htmlid=0; //Запрошеный пользователем htmlid
//c - have child; fid - id from database
this.XMLTree=CreateXMLDOC('<?xml version="1.0" encoding="utf-8"?><metadata><tree c="1" htmlid="0" s="0" treeid="-1" fid="" ObjectID=""></tree></metadata>');
this.m_root=new TTreeNode(null,this); //Корневой узел
this.m_root.wch=true; //Признак ожидания детей
this.m_tn=new Array(); //TTreeNode list
this.m_tn.push(this.m_root);
this.m_ls=new Array(); //listener list
this.m_lsl=new Array(); //listener list load
this.m_path=''; //путь для выделения (подсвечивания) кнопочек
this.m_exp=false;
this.m_hide=0;
//Создаём самый верхний контейнер с 0м HTMLID
var cnt=document.createElement('div');
cnt.setAttribute('id',this.m_pr+this.m_root.htmlid+'tb');
cnt.style.cssText="width: 100%; display: block;";
cnt.innerHTML='<nobr id="qwery"><img src="../resources/metadata/tree/icons/loading.gif" alt=" "><font color="#999999"><b> Подождите пожалуйста...</b></font></nobr>';
this.m_obj.appendChild(cnt);
}
//v_obj - main html object, v_pr - html id prefix, v_scr - server script, v_pth - path to images
function TTree(v_obj,v_pr,v_scr,v_pth,v_imgsize) //Дерево
{
//Запускает запрос корня дерева с сервера
this.Start=function()
{ xmlstring='<?xml version="1.0" encoding="utf-8"?><metadata fn="2" htmlid="0" treeid="-1"><columns></columns></metadata>';
this.callServer(this.m_scr,xmlstring);
};
//отправить XML на сервер
this.callServer=function(url,xmlString)
{
var call=new myXMLHttpRequest(this);
call.callServer(url,xmlString);
};
this.processReqChange=function(xmlHttpRequest,url,xmlString)
{
if (typeof(xmlHttpRequest.readyState)=='undefined' || xmlHttpRequest.readyState == 4)
{
if(typeof(xmlHttpRequest.status)=='undefined' || xmlHttpRequest.status == 200) // only if "OK"
{
if(typeof(xmlHttpRequest.responseXML)=='undefined' && xmlHttpRequest.contentType.match(/\/xml/)) //For IE XDomainRequest
xmlHttpRequest.responseXML=CreateXMLDOC(xmlHttpRequest.responseText);
//загрузился xml документ начинаем его разбирать (по id функции в документе)
let xmldoc = xmlHttpRequest.responseXML;
if(xmldoc==null){
alert2(trt('Alert'),trt('Wrong_XML_document')+"!\n"+xmlHttpRequest.responseText);
return;
}
let node = xmldoc.documentElement;
if((node==null)||(node.getAttribute("fn")==null)) alert2(trt('Alert'),trt('Error')+"\n"+trt('No_data')+"!\n"+xmlHttpRequest.responseText);
else
{
var fn = node.getAttribute("fn");
if (fn==0)
{
alert2(trt('Alert'),findFirstNode(node,"#cdata-section").nodeValue);
}else
if (fn==1)
{
this.addNode(node);
this.OpenTreeOnPath(this.m_path);
}else
alert2(trt('Alert'),"Unknown function! fn=\""+fn+"\"" );
}
}else
{
alert2(trt('Alert'),trt('Failed_to_get_data')+"\n URL: "+url+"\n" + xmlHttpRequest.statusText);
}
}
};
//развернуть дерево создать либо удалить (если нет данных то подгрузить)
//Результат true если уже загружен и false если ещё нет те отправили запрос на загрузку
//v_o - 1 open 0 - close else invert
this.openTree=function(htmlid,v_o)
{
var thetable=document.getElementById(this.m_pr+'table'+htmlid);
if (thetable==null) return false;
var node=findFirstNodeOnAttribute(this.XMLTree.documentElement,"tree","htmlid",htmlid);
if(node==null) return false;
if(node.getAttribute("c")!='1' && v_o==1) return true; //false
//ищем ячейку "подождите пожалуйста" и удаляем её
w=document.getElementById(this.m_pr+'pw'+htmlid);
if(w!=null) w.parentNode.removeChild(w);
if(thetable.rows.length<2)//развернуть дерево
{
if(node.getAttribute("o")==null) node.setAttribute ("o","0");
if(findFirstNode(node,"tree")==null)
{
//ячейка подождите пожалуйста
thetr = thetable.insertRow(thetable.rows.length);
thetr.setAttribute("id",this.m_pr+'pw'+htmlid);
thetd = thetr.insertCell(thetr.cells.length);
thetd.appendChild(document.createTextNode(" "));
thetd = thetr.insertCell(thetr.cells.length);
thetd.innerHTML='<nobr><img src="'+this.m_pth+'icons/loading.gif" alt=" "><font color="#999999"><b> Подождите пожалуйста...</b></font></nobr>';
fid=node.getAttribute("fid");
treeid=node.getAttribute("treeid");
nodeName=node.getAttribute("t");
nodeParameters=findFirstNode(node,"columns");
//если нет ни одного дочернего tree то запрашиваем данные иначе раскрываем список
xmlstring='<?xml version="1.0" encoding="utf-8"?><metadata fn="2" htmlid="'+htmlid+'" treeid="'+treeid+'" fid="'+fid+'" n="'+nodeName+'">'+getXMLNodeSerialisation(nodeParameters)+'</metadata>';
this.callServer(this.m_scr,xmlstring);
return false;
}
//добавляем таблицы
var nodeTree=node.firstChild;
while (nodeTree!=null)
{
if (nodeTree.nodeName=="tree")
{
hid=nodeTree.getAttribute("htmlid");
id=nodeTree.getAttribute("id");
iid=nodeTree.getAttribute("iid");
fid=nodeTree.getAttribute("fid");
o=nodeTree.getAttribute("o");
t=nodeTree.getAttribute("t");
var name=getCdataValue(nodeTree);
thetr = thetable.insertRow(thetable.rows.length);
thetd = thetr.insertCell(thetr.cells.length);
thetd.appendChild(document.createTextNode(" "));
thetd = thetr.insertCell(thetr.cells.length);
//thetd.setAttribute("width","100%")
table=document.createElement('table');
table.style.cssText="border-spacing:0px; border-collapse: separate;";
table.setAttribute('border','0');
table.setAttribute("id",this.m_pr+"table"+hid);
table.cellspacing=0;
table.cellpadding=0;
newRow=table.insertRow(0); //добавляем строку в созданной таблице
newCell = newRow.insertCell(0); //в созданной строке добавляем столбец
newCell.style.cssText="padding:0px;";
if(nodeTree.getAttribute("c")=="1")
{
img=document.createElement('img');
img.setAttribute("id",this.m_pr+"table"+hid+"f1");
if(o==1) { img.src=this.m_pth+'icons/minus.png'; img.setAttribute("alt","-"); } else { img.src=this.m_pth+'icons/plus.png'; img.setAttribute("alt","+"); }//рикунок + или -
img.style.cssText="cursor: pointer;";
img.onclick=function(obj,val1){
return function(){
obj.openTree(val1);
};
}(this,hid);
}else
{
img=document.createElement('img');
img.src=this.m_pth+'icons/blank24.gif';
img.setAttribute("alt"," ");
}
newCell.appendChild(img);
newCell = newRow.insertCell(1);
newCell.style.cssText="padding:0px; width:100%; cursor: pointer; vertical-align: top;";
newCell.setAttribute('noWrap', 'true');
//Цвет и событие нажатия должно применяться к одному и томуже DOM объекту !
newCell.setAttribute("id",this.m_pr+'cell'+hid); //Для снятия выделения
if(nodeTree.getAttribute("s")=="1") newCell.style.backgroundColor='#dddddd';
newCell.onmouseover=function(node){
return function(){
if(node.getAttribute("s")!="1") this.style.backgroundColor='#d1d1d1';
};
}(nodeTree);
newCell.onmouseout=function(node){
return function(){
if(node.getAttribute("s")!="1") this.style.backgroundColor='transparent';
};
}(nodeTree);
//Нажатие на текст узла (слушателю XML этого узла)
nObj=null;
for(var i=0;i<this.m_tn.length;i++)
{
if(this.m_tn[i].htmlid==hid)
{ nObj=this.m_tn[i]; break;
}
}
newCell.onclick=function(obj,cell){
return function(){
obj.tree.clearS();
obj.node.setAttribute("s","1");
//cell.style.backgroundColor="#dddddd";
this.style.backgroundColor='#dddddd';
//Информируем слушателей
for(var i=0;i<obj.tree.m_ls.length;i++)
if(obj.tree.m_ls[i]!==null)
obj.tree.m_ls[i].OnClickNode(obj);
};
}(nObj,null);
cntTbl=document.createElement('table');
cntTbl.style.cssText="width:100%; border-spacing:0px; border-collapse: separate;";
cntTbl.setAttribute('border','0');
cntTbl.cellspacing=0;
cntTbl.cellpadding=0;
cntRow=cntTbl.insertRow(0); //добавляем строку в созданной таблице
cntCell = cntRow.insertCell(0);
cntCell.style.cssText="padding:0px;";
cntCell.appendChild(createImg(this.m_pth+'icons/ico'+this.m_imgsize+'_'+iid+'.png',this.m_imgsize+'px',this.m_imgsize+'px'));
cntCell = cntRow.insertCell(1); //в созданной строке добавляем столбец
cntCell.style.cssText="width:100%; padding:0px; padding-left:5px;";
a=document.createElement('a');
a.innerHTML=" "+name+"\u00A0";
a.setAttribute("id",this.m_pr+'text'+hid);
a.style.cssText="cursor: pointer; text-decoration: none; color: #166EC0;";
cntCell.appendChild(a);
newCell.appendChild(cntTbl);
thetd.appendChild(table);
//если данный узел открыт то подгружаем и открываем его
if(o=="1")
{
this.openTree(hid); //рекурсия
}
}
nodeTree=nodeTree.nextSibling;
}
//меняем значёк узла с + на -
img=document.getElementById(this.m_pr+'table'+htmlid+'f1');
if(img!=null){ img.src=this.m_pth+'icons/minus.png'; img.setAttribute("alt","-"); }
node.setAttribute ("o","1");
}else
if(thetable.rows.length>1 && v_o!=1)//свернуть дерево
{
//удалить все строки в таблице кроме первой
var tbl=document.getElementById(this.m_pr+'table'+htmlid);
while (tbl.rows.length>1) tbl.tBodies[0].deleteRow(1);
node.setAttribute ("o","0");
img=document.getElementById(this.m_pr+'table'+htmlid+'f1');
if(img!=null){ img.src=this.m_pth+'icons/plus.png'; img.setAttribute("alt","+"); }
}
return true;
};
//add node to tree
this.addNode=function(node)
{
if(node==null) return;
var htmlid=node.getAttribute("htmlid"); //parent id
var pnode=findFirstNodeOnAttribute(this.XMLTree,"tree","htmlid",htmlid);
var nodeTree=node.firstChild;
while (nodeTree!=null)
{
if(nodeTree.nodeName=="tree")
{
nodeTree.parentNode.removeChild(nodeTree);
pnode.appendChild(nodeTree);
this.m_tn[this.m_tn.length]=new TTreeNode(nodeTree,this);
nodeTree.setAttribute("htmlid",this.m_tn[this.m_tn.length-1].htmlid); //проставить уникальные HTML ID для детей узла
for(var i=0;i<this.m_lsl.length;i++)
if(this.m_lsl[i]!=null) this.m_lsl[i].OnLoadNode(this.m_tn[this.m_tn.length-1]);
nodeTree=node.firstChild;
}else
nodeTree=nodeTree.nextSibling;
}
//this.setHTMLID(pnode);
this.openTree(htmlid);
if(this.m_exp)
{
var nodeTree=pnode.firstChild;
while (nodeTree!=null)
{
if(nodeTree.nodeName=="tree")
{
this.openTree(nodeTree.getAttribute("htmlid"),1);
}
nodeTree=nodeTree.nextSibling;
}
}
};
//Добавить слушателя
this.addListener=function(listener)
{ if(listener.OnClickNode==null) alert2(trt('Alert'),'У объекта нет функции "OnClickNode()"!');
this.m_ls[this.m_ls.length]=listener;
};
//Удалить слушателя
this.remListener=function(listener)
{ for(var i=0;i<this.m_ls.length;i++)
{ if(this.m_ls[i]==listener)
this.m_ls[i]=null;
}
};
//Добавить слушателя
this.addListenerLoad=function(listener)
{ if(listener.OnLoadNode==null) alert2(trt('Alert'),'У объекта нет функции "OnLoadNode(node)"!');
this.m_lsl[this.m_lsl.length]=listener;
};
//Удалить слушателя
this.remListenerLoad=function(listener)
{ for(i=0;i<this.m_lsl.length;i++)
{ if(this.m_lsl[i]==listener)
this.m_lsl[i]=null;
}
};
//Отменить выделенное
this.clearS=function()
{ for(var i=0;i<this.m_tn.length;i++)
{ if(this.m_tn[i].node.getAttribute("s")=="1")
{ hid=this.m_tn[i].node.getAttribute("htmlid");
obj=document.getElementById(this.m_pr+'cell'+hid);
if(obj!=null) obj.style.backgroundColor="transparent";
}
this.m_tn[i].node.setAttribute("s","0");
}
};
//Path format "id node tree;id data;id node tree;id data;..."
this.OpenTreeOnPath=function(path)
{
this.m_path=path;
var n=findFirstNode(this.XMLTree.documentElement,'tree');
if(findFirstNode(n, 'tree')==null) return;
var mas = path.split(";");
for(var i=0;i<(mas.length-1)/2;i++)
{
var fn=null;
if(n!=null) n=n.firstChild;
while(n!=null)
{ if(n.nodeName=='tree' && n.getAttribute('treeid')==mas[i*2] && n.getAttribute('fid')==mas[i*2+1])
{ fn=n;
break;
}
n=n.nextSibling;
}
if(fn==null){ this.m_path=''; return; }
if(!this.openTree(fn.getAttribute('htmlid'),1))
return;
if(i==(mas.length-1)/2-1) //select lact node
{
n.setAttribute("s","1");
div=document.getElementById(this.m_pr+'cell'+n.getAttribute('htmlid'));
div.style.backgroundColor="#dddddd";
}
}
this.m_path='';
};
//Путь от корня к выделенному в виде "id node tree;id data;id node tree;id data;..."
this.getTreePath=function()
{ var n=null;
for(var i=0;i<this.m_tn.length;i++)
{ if(this.m_tn[i].node.getAttribute("s")=="1")
{ n=this.m_tn[i].node;
break;
}
}
var c='';
while(n!=null && n.nodeName=='tree')
{ np=findNode(n,'columns');
if(np!=null)
{ c=getCdata(findNodeOnAttribute(np, 'param','n',n.getAttribute('ObjectID'))).nodeValue+';'+c;
c=n.getAttribute('treeid')+';'+c;
}
n=n.parentNode;
}
return c;
};
//Путь от корня к выделенному в виде заголовков "name->name"
this.getTXTPath=function()
{ n=null;
for(var i=0;i<this.m_tn.length;i++)
{ if(this.m_tn[i].node.getAttribute("s")=="1")
{ n=this.m_tn[i].node;
break;
}
}
c='';
while(n!=null && n.nodeName=='tree')
{ c=getCdata(n).nodeValue+'->'+c;
n=n.parentNode;
}
return c.substring(2,c.length-2);
};
//Обновить детей заданного узла (TODO Доделать)
this.updateNode=function(htmlid)
{
//var n=findFirstNodeOnAttribute(this.XMLTree.documentElement,"tree","htmlid",htmlid)
//while(n.hasChildNodes()) n.removeChild(n.firstChild)
//openTree(htmlid)
};
//Раскрыть все элементы заданного узла
this.expandAll=function(htmlid)
{ this.m_exp=true;
//if (typeof htmlid == "undefined") htmlid = 1;
//this.openTree(htmlid,1)
//var n=findFirstNodeOnAttribute(this.XMLTree.documentElement,'tree','htmlid',htmlid);
//openTree()
};
//Свернуть все элементы заданного узла
this.collapseAll=function(htmlid)
{ for(var i=0;i<this.m_tn.length;i++)
{ if(this.m_tn[i].node.getAttribute('o')=='1')
this.openTree(this.m_tn[i].node.getAttribute('htmlid'),0);
}
};
//Получить выделенный XML узел
this.getSelNode=function()
{ for(var i=0;i<this.m_tn.length;i++)
{ if(this.m_tn[i].node.getAttribute('s')=='1')
return this.m_tn[i];
}
return null;
};
this.m_obj=v_obj;
this.m_obj.innerHTML='<table id="'+v_pr+'table0" border="0px" style="border: 0px solid rgb(0, 0, 0); width:100%;" cellpadding="0px" cellspacing="0px"><caption></caption><thead></thead><tbody></tbody></table>';
this.m_pr=v_pr; //Prefix for HTML ids
this.m_scr=v_scr;
this.m_pth=v_pth;
this.m_imgsize=v_imgsize;
//c - have child; fid - id from database
this.XMLTree=CreateXMLDOC('<?xml version="1.0" encoding="utf-8"?><metadata><tree c="1" htmlid="0" s="0" treeid="-1" fid="" ObjectID=""></tree></metadata>');
this.m_tn=new Array(); //TTreeNode list
this.m_ls=new Array(); //listener list
this.m_lsl=new Array(); //listener list load
this.m_path='';
this.m_exp=false;
//ячейка подождите пожалуйста
var thetable=document.getElementById(this.m_pr+'table0');
thetr = thetable.insertRow(thetable.rows.length);
thetr.setAttribute("id",this.m_pr+'pw0');
thetd = thetr.insertCell(thetr.cells.length);
thetd.appendChild(document.createTextNode(" "));
thetd = thetr.insertCell(thetr.cells.length);
thetd.innerHTML='<nobr><img src="'+this.m_pth+'icons/loading.gif" alt=" "><font color="#999999"><b> Подождите пожалуйста...</b></font></nobr>';
}