//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='';
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;i2)
{
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='
Подождите пожалуйста...';
return;
}
for(var i=0;i';
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'
for(var i=0;i';
}
xmlstring+='';
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';
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: inline-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'+getXMLNodeSerialisation(nodeParameters)+'';
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=''+getXMLNodeSerialisation(nodeParameters)+'';
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';
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('');
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: inline-block;";
cnt.innerHTML='
Подождите пожалуйста...';
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='';
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(_('Alert'),_('Wrong_XML_document')+"!\n"+xmlHttpRequest.responseText);
return;
}
let node = xmldoc.documentElement;
if((node==null)||(node.getAttribute("fn")==null)) alert2(_('Alert'),_('Error')+"\n"+_('No_data')+"!\n"+xmlHttpRequest.responseText);
else
{
var fn = node.getAttribute("fn");
if (fn==0)
{
alert2(_('Alert'),findFirstNode(node,"#cdata-section").nodeValue);
}else
if (fn==1)
{
this.addNode(node);
this.OpenTreeOnPath(this.m_path);
}else
alert2(_('Alert'),"Unknown function! fn=\""+fn+"\"" );
}
}else
{
alert2(_('Alert'),_('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='
Подождите пожалуйста...';
fid=node.getAttribute("fid");
treeid=node.getAttribute("treeid");
nodeName=node.getAttribute("t");
nodeParameters=findFirstNode(node,"columns");
//если нет ни одного дочернего tree то запрашиваем данные иначе раскрываем список
xmlstring=''+getXMLNodeSerialisation(nodeParameters)+'';
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;i1 && 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;iname"
this.getTXTPath=function()
{ n=null;
for(var i=0;i'+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_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('');
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='
Подождите пожалуйста...';
}