Вначале хочу извиниться за небольшую неточность, случайно допущенную мной в предыдущем
выпуске рассылки, в примере файла меню mnu.js. Чтобы меню отображалось
правильно, необходимо, чтобы символы табуляции входили в состав частей текстовых строк
и были внутри кавычек. А в приведенном примере в строках 5-8 отступы табуляции оказались
слева от кавычек. Для корректной работы необходимо, чтобы символ кавычек стоял в первой
позиции строки.
Нам осталось рассмотреть еще несколько элементов, чтобы разрабатываемое древовидное
меню навигации начало работать. Ключевым моментом здесь является, конечно индексный
HTML-файл. Название "индексный" здесь условное. Имя файла может быть любое. Просто
по-умолчанию первой грузится страница с именем "index" или "default" - я выбрал первый
вариант. Рассмотрим его состав в сокращенном виде:
Что здесь наиболее важно? В заголовке файла указано, что вначале надо загрузить пять
файлов JavaScript. Конечно, вы можете объединить код всех пяти файлов
в один и разместить код непосредственно в данном HTML-файле. Но если нам надо использовать
отдельные блоки кода повторно, то логично разделить их в разные файлы по смысловому
содержанию. Кроме того, так удобнее модифицировать код, когда чисто зрительно видишь
логически завершенный и работающий компактный блок кода.
Назначение первых трех модулей нам уже известно: mnu.js - это содержание
меню; stack.js - структура, описывающая класс стека;
simptree.js - структура, описывающая класс древовидной структуры. Кроме этих
файлов появились еще два - это контроллер, который отвечает за работу
структуры меню на HTML страничке, за внешний вид меню и отклик на события мыши. И файл
hdrtree.js, который я условно назвал "конструктор". Этот файл выполняет
непосредственное построение структуры меню, используя информацию, полученную из
массива, описывающего меню в файле mnu.js.
/* Файл "treecon.js"
создание древовидного контроллера
----------------------------------*/
function TreeController(theOb,theTree){
// alert(theOb);
this.theOb = theOb; // Указывает на элемент, куда вставлять меню
this.theTree = theTree; // Указывает, что вставлять
this.name = theOb.id;
TreeController[this.name]=this;
this.init(); //формирует контроллер
}
function tc_init(){
// фомирует контроллер меню и заносит его в указанный элемент страницы
this.path = '';
this.path+="TreeController."+this.name+".";
var HT = this.consControl(this.theTree,"");
this.theOb.innerHTML = HT.length==0?"Меню недоступно.":HT;
//замена текста "Загрузка меню..." в указанном элементе
this.setULs(this.theTree,this.theOb);
}
function tc_setULs(tree,ob){
tree.ul=ob; // создает UL таги
for(var i=0;i<tree.numChildren();i++)
tc_setULs(tree.getNth(i),ob.children[1+2*i])
}
function tc_toggle(imageObj,ev){
// переключатель иконок в меню
var tAddr = imageObj.name.substring(2);
var T=this.theTree.getSubTree(tAddr);
var ul=T.ul;
if(!ul){alert("help, no list for image "+imageObj.name); return;}
if(ul.className=="closed"){ul.className="open";imageObj.src='open.gif';}
else {ul.className="closed";imageObj.src='close.gif';}
ev.cancelBubble=true;
}
function tc_consTitle(label,tAddr,hasChildren){
// формирует заголовки меню
var imclickStr= " onclick='"+this.path+"toggle(this,event)'";
var imStr;
if(hasChildren) {
imStr="<IMG name='im"+tAddr+"' SRC='close.gif'"+imclickStr+
" style="\""cursor:hand;\" title=\"развернуть/свернуть ветвь\"> ";
} else {
imStr="<IMG SRC=\"empty.gif\"> ";
}
var S="<SPAN>"+ imStr + label + "<BR></SPAN>";
return S;
}
function tc_consControl(tree,tAddr){
//формирование HTML текста меню для вывода в броузер
if(!tree)return "";
var N=tree.numChildren();
tree.tAddr=tAddr;
if(!this.showTop && tAddr==""){
var S="";
for(var i=0;i<N;i++)S+=this.consControl(tree.getNth(i),""+(i+1));
return S;
}
var S= this.consTitle(tree.label,tAddr,N>0);
S+= "<UL class=closed name='ul"+tAddr+"'>\n ";
for(var i=0;i<N;i++){
S+=this.consControl(tree.getNth(i),tAddr+"."+(i+1));
}
return S+"</UL>\n";
}
function tc_openTree(addr){ // Открывает ветку
if(!addr)return; var T=this.theTree;
addr=addr.split(".");
for(var i=0;i<addr.length;i++){
var N=parseInt(addr[i],10)-1;
var img=T.ul.children[2*N].children[0]; if(!img)return;
img.src="open.gif";
T=T.getNth(N);
T.ul.className="open";
}
}
function tc_closeTree(){// Закрывает ветку
var A=new Array(); A[0]=this.theTree;
while (A.length>0){
var T=A[A.length-1];A.length-=1;
if(T.ul)T.ul.className="closed";
for(var i=0;i<T.numChildren();i++){
A[A.length]=T.getNth(i);
var img=T.ul.children[2*i].children[0];
if(img)img.src="close.gif";
}
}
}
TreeController.prototype.init=tc_init;
TreeController.prototype.setULs=tc_setULs;
TreeController.prototype.toggle = tc_toggle;
TreeController.prototype.consTitle = tc_consTitle;
TreeController.prototype.consControl = tc_consControl;
TreeController.prototype.openTree=tc_openTree;
TreeController.prototype.closeTree=tc_closeTree;
// файл hdrtree.js
// ====================
function headerController(mnuTag,mnuArray){
var hTree=getTopHeaderTree(mnuArray);
var TC= new TreeController(mnuTag,hTree);
}
function getTopHeaderTree(MnuArrow){
var HG=new Traverser(MnuArrow);
var T= makeHeaderTree(HG);
return T;
}
function makeHeaderTree(HG){
// Функция формирования дерева меню
var item = HG.current;
var strMnu;
strMnu = getText(item);
if (!(getHref(item)==-1)) {
strMnu = "<A class=\"mnu\" href=\"" +
getHref(item) + "\" title=\"" +
getTitle(item) + "\" target=\"" + mnuTarget + "\">" + strMnu + "</A>";
}
var T=new Tree(strMnu);
HG.getNext(); // the next header after "item"
while(myhdrLevel(HG.current) > myhdrLevel(item))
T.addLeg(makeHeaderTree(HG));
return T;
}
function getText(item) {
// Получение текста ссылки
if (!item) return -1;
else {
tmpArr=new Array();
tmpArr=item.split("|");
return tmpArr[0];
}
}
function getHref(item) {
// Возвращает адрес ссылки, если он существует
if (!item) return -1;
else {
tmpArr=new Array();
tmpArr=item.split("|");
if (!tmpArr[1]) return -1;
else return tmpArr[1];
}
}
function getTitle(item) {
// Возвращает подсказку для ссылки
if (!item) return -1;
else {
tmpArr=new Array();
tmpArr=item.split("|");
if (!tmpArr[2]) return "";
else return tmpArr[2];
}
}
// Подсчет табуляторов перед строкой меню
function myhdrLevel(str){
if (!str) return -1;
else{
var k=0;
for(var i=0;str.length;i++){
if(str.charAt(i)=="\t"){
k++;
}else{return k}}
return k;
}
}
/*class: конструктор и один метод */
function Traverser(mArr){
// Заносим в стек все элементы массива меню
this.Stk=new Stack();
for(var i=mArr.length-1;i>=0;i--){
this.Stk.push(mArr[i]);
}
}
function trav_Next(){
while(true){
if(this.Stk.isEmpty())return this.current = null;
var x=this.Stk.pop();
return this.current = x;
}
}
Traverser.prototype.getNext=trav_Next;
Вам еще понадобится три графических файла - иконки обозначающие
закрытую ветвь, раскрытую ветвь, и прозрачный .GIF для выравнивания.
Вот в общем и все. После загрузки HTML странички в броузер событие
onload вызывает функцию с двумя параметрами onload="headerController(window.mnuTree,myHTMLmnu)".
Первый параметр (window.mnuTree) указывает на идентификатор HTML - элемента,
расположенного на страничке, который обозначает место, где расположить меню.
Текст в этом элементе будет заменен текстом меню после загрузки.
Второй параметр (myHTMLmnu) указывает на имя массива, откуда берется
информация для построения меню (массив расположен в файле mnu.js).
Рабочий пример меню с комментариями расположен на script.inc.ru.
Eсли Вы ищете качественный и недорогой web-хостинг, лично я рекомендую
PeterHost.Ru.
Российский (поддержим наших!), прекрасные каналы, сервис "на уровне".