Javascript-форум (https://javascript.ru/forum/)
-   Элементы интерфейса (https://javascript.ru/forum/dom-window/)
-   -   Компактное дерево (https://javascript.ru/forum/dom-window/3421-kompaktnoe-derevo.html)

SAY 17.04.2009 12:43

Компактное дерево
 
Добрый день!

есть скрипт древовидного меню:
<style>

p { margin: 0px }
body { font-size: 11px; font-family: verdana; line-height: 17px }
.sub { padding-left: 20px; display: block }
.menu { cursor: pointer; display: block }
a { text-decoration: none; color: #000000 }

</style>

<script language=JavaScript>

function show(obj) {

if (document.getElementById(obj).style.display == 'none')
document.getElementById(obj).style.display = 'block';
else document.getElementById(obj).style.display = 'none';

}

</script>

<span class="menu" onclick="show('sub1')">+ Статьи</span>

<span class="sub" id="sub1" style="display: none">
<p><a href='http://'>Интернет</a></p>
<p><a href='http://'>JavaScript</a></p>
</span>

<span class="menu" onclick="show('sub2')">+ Рейтинг</span>

<span class="sub" id="sub2" style="display: none">
<p><a href='http://'>Главная</a></p>
<p><a href='http://'>Регистрация</a></p>
<p><a href='http://'>Статистика</a></p>
</span>

<span class="menu" onclick="show('sub3')">+ Форум</span>

<span class="sub" id="sub3" style="display: none; border: 3px">
<p><a href='http://www.webobzor.net'>Регистрация</a></p>
<p><a href='http://www.webobzor.net'>Cообщения</a></p>
<p><a href='http://www.webobzor.net'>Поиск</a></p>
</span>


Как сделать что бы при открытии ветки меню, остальные ранее открытые ветки закрывались?
Спасибо!

x-yuri 18.04.2009 20:49

в show находишь все span'ы с классом sub и скрываешь все, кроме того, который показываешь

SAY 19.04.2009 09:07

Цитата:

Сообщение от x-yuri (Сообщение 17040)
в show находишь все span'ы с классом sub и скрываешь все, кроме того, который показываешь

А можно поподробнее, нашел в инете функцию getElementsByClassName, но она работает только в ff3 и safari3, а хотелось бы, что бы скрипт работал во всех браузерах.

AzriMan 20.04.2009 18:12

видимо, пользоваться поиском по форуму не учили:
function getElementsByClass(searchClass,node,tag) {
 	 //Dustin Diaz's getElementsByClass implementation
	var classElements = new Array();
	if ( node == null )
		node = document;
	if ( tag == null )
		tag = '*';
	var els = node.getElementsByTagName(tag);
	var elsLen = els.length;
	var pattern = new RegExp("(^|\\s)"+searchClass+"(\\s|$)");
	for (i = 0, j = 0; i < elsLen; i++) {
		if ( pattern.test(els[i].className) ) {
			classElements[j] = els[i];
			j++;
		} //if
	} //for
	return classElements;
}



if(document.getElementsByClassName) {
	var anal_tables  = document.getElementsByClassName("sub");
	//Firefox 3  C++ native implementation
} else {
	var anal_tables  = getElementsByClass("sub", document, "span");
	//Dustin Diaz's getElementsByClass implementation 
}

SAY 24.04.2009 10:33

чего то я не догоню никак, как теперь скрыть то :help:
пытался сделать
document.getElementByClassname("sub").style.display = 'none';

но ничего не получается

Gvozd 24.04.2009 10:55

getElementByClassname возвращают коллекцию объектов, а не один объект.
а getElementsByClass возвращает массив.но не один объект
обращайтесь к конкретному элементу по индексу.
либо перебирайте в цикле все элементы

AzriMan 24.04.2009 11:28

ай опередил меня :)

ЫФН 24.04.2009 12:28

Спасибо всем за помощь!
Сделал сам :dance: только по другому:
function show(obj) {
if (document.getElementById(obj).style.display == 'none')
{
    if(typeof old == "undefined")
    {
       old="";
    }
    else
    {
       document.getElementById(old).style.display = 'none';
    }
    document.getElementById(obj).style.display = 'block';
    old=obj;
    return (old);
}
    else document.getElementById(obj).style.display = 'none';
}

AzriMan 24.04.2009 14:02

если честно - не красиво...

SAY 24.04.2009 14:06

Цитата:

Сообщение от AzriMan (Сообщение 17504)
если честно - не красиво...

Да я и сам уже понял, что кривовато, переделал:
function show(obj) {
if (document.getElementById(obj).style.display == 'none')
{
    if(typeof old != "undefined")
    {
       document.getElementById(old).style.display = 'none';
    }
    document.getElementById(obj).style.display = 'block';
    old=obj;
    return (old);
}
else document.getElementById(obj).style.display = 'none';
}

x-yuri 24.04.2009 17:57

я бы сделал как-то так:
<style>
 
p { margin: 0px }
body { font-size: 11px; font-family: verdana; line-height: 17px }
.sub { padding-left: 20px; display: block }
.menu { cursor: pointer; display: block }
a { text-decoration: none; color: #000000 }
 
</style>
 
<script language=JavaScript>
 
function show( node ) {
 
	if( arguments.callee.prv )
		arguments.callee.prv.style.display = 'none';
 	do {
		node = node.nextSibling;
	} while (! node.tagName);
	arguments.callee.prv = node;
	node.style.display = 'block';
}
 
</script>
 
<span class="menu" onclick="show(this)">+ Статьи</span>
 
<span class="sub" id="sub1" style="display: none">
<p><a href='http://'>Интернет</a></p>
<p><a href='http://'>JavaScript</a></p>
</span>
 
<span class="menu" onclick="show(this)">+ Рейтинг</span>
 
<span class="sub" id="sub2" style="display: none">
<p><a href='http://'>Главная</a></p>
<p><a href='http://'>Регистрация</a></p>
<p><a href='http://'>Статистика</a></p>
</span>
 
<span class="menu" onclick="show(this)">+ Форум</span>
 
<span class="sub" id="sub3" style="display: none; border: 3px">
<p><a href='http://www.webobzor.net'>Регистрация</a></p>
<p><a href='http://www.webobzor.net'>Cообщения</a></p>
<p><a href='http://www.webobzor.net'>Поиск</a></p>
</span>

1) нету глобальной переменной, 2) не нужно задавать id для всех подменю и привязывать обработчики к своим подменю - функция show сама все находит

SAY 29.04.2009 11:18

Вот блин! Потребовалось сделать компактное дерево с неограниченным количеством уровней
<style>                                                                               
p { margin: 0px }                                                                     
body { font-size: 11px; font-family: verdana; line-height: 17px }                     
.sub { padding-left: 20px; display: block }                                           
.menu { cursor: pointer; display: block }                                             
a { text-decoration: none; color: #000000 }                                           
</style>                                                                              

<script language=JavaScript>
function show(obj) {  
if (document.getElementById(obj).style.display == 'none') 
{                                                         
    if (typeof old != "undefined")
    {                                                          
          document.getElementById(old).style.display = 'none'; 
    }                                                          
    document.getElementById(obj).style.display = 'block';      
    old=obj;                                                   
    return (old);                                     
}                                                              
else document.getElementById(obj).style.display = 'none';      
}                                                              

</script>

<span class="menu" onclick="show('sub1')">+ Статьи</span>

<span class="sub" id="sub1" style="display: none">
<p><a href='http://'>Интернет</a></p>             
<p><a href='http://'>JavaScript</a></p>           
</span>                                           

<span class="menu" onclick="show('sub2')">+ Рейтинг</span>

<span class="sub" id="sub2" style="display: none">
<p><a href='http://'>Главная</a></p>              
<p><a href='http://'>Регистрация</a></p>          
<p><a href='http://'>Статистика</a></p>           
</span>                                           

<span class="menu" onclick="show('sub3')">+ Форум</span>

<span class="sub" id="sub3" style="display: none; border: 3px">
<a href='http://'>Регистрация</a></p>                          
<span class="menu" onclick="show('sub4')">+ Cообщения</span>
              <span class="sub" id="sub4" style="display: none">          
              <p><a href='http://'>Главная</a></p>                        
              <p><a href='http://'>Регистрация</a></p>                    
              <p><a href='http://'>Статистика</a></p>                     
              </span>
<p><a href='http://'>Поиск</a></p>                              
</span>


И чего то я застрял, возникла идея вызывать функцию show, в которой будет указан еще и уровень вложения, например:
... onclick="show('sub4','2')" ....

а как это применить не соображу :help:

x-yuri 29.04.2009 18:17

зачем тебе уровень передавать? Оно и так должно работать. Просто есть разные варианты реализации... чем тебя твой не устраивает? Ну или вообще, как ты представляешь работу многоуровневого меню?

SAY 30.04.2009 14:04

Цитата:

Сообщение от x-yuri (Сообщение 17877)
Ну или вообще, как ты представляешь работу многоуровневого меню?

Примерно так:
<style>                                                                                                                                                      
p { margin: 0px }                                                                                                                                            
body { font-size: 11px; font-family: verdana; line-height: 17px }                                                                                            
.sub { padding-left: 20px; display: block }                                                                                                                  
.menu { cursor: pointer; display: block }                                                                                                                    
a { text-decoration: none; color: #000000 }                                                                                                                  
</style>                                                                                                                                                     

<script language=JavaScript>
old = new Array(10);        
function show(obj,level) {  
if (document.getElementById(obj).style.display == 'none') 
{                                                         
    if ((typeof last != "undefined")&&(lastlevel != "undefined"))
    {                                                            
       if (level<lastlevel)                                      
       {                                                         
          for (var n=level; n<=lastlevel; n++) {                 
               document.getElementById(old[n]).style.display = 'none';
          }                                                      
       }
       if (lastlevel==level)
       {
          document.getElementById(last).style.display = 'none';
       }
    }
    document.getElementById(obj).style.display = 'block';
    last=obj;
    old[level]=obj;
    lastlevel=level;
    return (last,lastlevel,old);
}
else document.getElementById(obj).style.display = 'none';
}

</script>

<span class="menu" onclick="show('sub1','1')">+ 1</span>

<span class="sub" id="sub1" style="display: none">
<p><a href='http://'>1.1</a></p>
<p><a href='http://'>1.2</a></p>
</span>

<span class="menu" onclick="show('sub2','1')">+ 2</span>

<span class="sub" id="sub2" style="display: none">
<p><a href='http://'>2.1</a></p>
<p><a href='http://'>2.2</a></p>
<p><a href='http://'>2.3</a></p>
</span>

<span class="menu" onclick="show('sub3','1')">+ 3</span>

<span class="sub" id="sub3" style="display: none; border: 3px">
<a href='http://'>3.1</a></p>
<span class="menu" onclick="show('sub4','2')">+ 3.2</span>
    <span class="sub" id="sub4" style="display: none">
    <p><a href='http://'>3.2.1</a></p>
    <span class="menu" onclick="show('sub6','3')">+ 3.2.2</span>
        <span class="sub" id="sub6" style="display: none">
        <p><a href='http://'>3.2.2.1</a></p>
        <p><a href='http://'>3.2.2.2</a></p>
        <p><a href='http://'>3.2.2.3</a></p>
        </span>
    <p><a href='http://'>3.2.3</a></p>
    <p><a href='http://'>3.2.4</a></p>
    </span>
<span class="menu" onclick="show('sub5','2')">+ 3.3</span>
    <span class="sub" id="sub5" style="display: none">
    <p><a href='http://'>3.3.1</a></p>
    <p><a href='http://'>3.3.2</a></p>
    <p><a href='http://'>3.3.3</a></p>
    </span>
<p><a href='http://'>3.4</a></p>
</span>


Сделал, только остался вопрос. Почему не желательно использовать глобальные переменные?

x-yuri 30.04.2009 14:44

потому что это может приводить к неожиданным багам, которые может быть нелегко найти. Потому что разные части кода могут непреднаеренно использовать одну и ту же переменную, и если это происходит одновременно...
Крайний случай: ключевое слово var всячески игнорируется - т.е. все переменные глобальные
p.s. и чем больше скриптов на странице (учитывая внешние библиотеки, если такие есть) - тем это актуальнее

SAY 30.04.2009 15:05

Цитата:

Сообщение от x-yuri (Сообщение 17945)
потому что это может приводить к неожиданным багам, которые может быть нелегко найти. Потому что разные части кода могут непреднаеренно использовать одну и ту же переменную, и если это происходит одновременно...
Крайний случай: ключевое слово var всячески игнорируется - т.е. все переменные глобальные
p.s. и чем больше скриптов на странице (учитывая внешние библиотеки, если такие есть) - тем это актуальнее

Значит если я захочу избавиться от проблем, мне нужно будет или:
1) имена переменных придумывать позакавырестее
2) или cкрывать все элемены меню, с помощью функции getElementByClass, искать все родительские ветки и делать им style.display = 'block' ?

AzriMan 30.04.2009 15:38

проблемы возникнут в том, что у вас переменная может называться content и в каком-то скрипте может существовать такая-же переменная. и результаты того, что участки кода, использующие эти переменные, могут выполняться одновременно - вы можете представить сами.
пойдем от обратного.

Цитата:

Почему не желательно использовать глобальные переменные
Цитата:

Крайний случай: ключевое слово var всячески игнорируется - т.е. все переменные глобальные
таким образом, если не игнорировать ключевое слово var, то переменные будут локальными.
пример.
a=5;
for (i=0;i<5;i++)
{alert (a);}

пять раз выведется 5
a=5;
for (i=0;i<5;i++)
{var a=4; alert (a);}
alert(a);

пять раз выведется 4, а потом выведется 5.

понятно?

SAY 01.05.2009 16:40

С глобальными переменными все ясно!

Спасибо всем за помощь!

x-yuri 01.05.2009 17:37

AzriMan, неудачный пример, 6 раз выведется 4. Лучше что-то типа
function a() {
    for( i=0; i<2; i++ )
        b();
}
function b() {
    for( i=0; i<2; i++ )
       alert('b');
}
a();

AzriMan 04.05.2009 14:45

x-yuri, хм, да, действительно. а почему?

Kolyaj 04.05.2009 14:55

Потому что i, в данном случае, глобальная.

AzriMan 04.05.2009 15:32

хм. такой пример:
<html><head>
<script type="text/javascript">
var a=5;
for (var i=0;i<5;i++)
{var a=4; alert (''+a+i);}
alert('!'+a+i);
</script>
</head><body></body></html>

i, теоретически, должна быть видима в пределах цикла. но последним выводом будет "!45". все равно не пойму..

Kolyaj 04.05.2009 15:52

Цитата:

Сообщение от AzriMan
i, теоретически, должна быть видима в пределах цикла

С теорией C/C++ путаете.

AzriMan 04.05.2009 16:16

Цитата:

Сообщение от Kolyaj (Сообщение 18189)
С теорией C/C++ путаете.

хм. вполне может быть, потому что в теорию JS не вникал. требуемый код писал интуитивно, даже не читая книжек. при возникновении вопросов искал ответы в разных манах/примерах (раздел аналогов функций PHP на JS помогал-некоторые вопросы отпадали после изучения примеров).

но, я думаю, всё встало на свои места. раз i в этом случае глобальная, следовательно var a, созданный в цикле, тоже будет глобальным. следовательно, созданный ранее var a=5; будет затерт ноым глобальным значением. вот и ответ.

буду знать, что в JS, все-таки, есть некие отличия от C/C++ в области видимости. спасибо.

x-yuri 04.05.2009 23:46

потому что есть 3 типа исполняемого кода: глобальный, функция и eval. Объявление переменных происходит перед выполнением, а присваивание - во время и не важно, что переменная объявлена в for:
alert(a); // если бы не было var a, то здесь бы выполнение прекратилось - ошибка
for( var i=0; i<1; i++ ) {
    var a=4; // значение присваивается здесь
}
alert(a);

вроде так

Kolyaj 04.05.2009 23:53

Цитата:

Сообщение от x-yuri
Объявление переменных происходит перед выполнением

В начале скопа.


Часовой пояс GMT +3, время: 10:12.