Форум: Форум PHPФорум ApacheФорум Регулярные ВыраженияФорум MySQLHTML+CSS+JavaScriptФорум FlashРазное
Новые темы: 0000000
C++. Мастер-класс в задачах и примерах. Авторы: Кузнецов М.В., Симдянов И.В. PHP на примерах (2 издание). Авторы: Кузнецов М.В., Симдянов И.В. MySQL 5. В подлиннике. Авторы: Кузнецов М.В., Симдянов И.В. Самоучитель PHP 5 / 6 (3 издание). Авторы: Кузнецов М.В., Симдянов И.В. PHP 5/6. В подлиннике. Авторы: Кузнецов М.В., Симдянов И.В.
ВСЕ НАШИ КНИГИ
Консультационный центр SoftTime

Форум PHP

Выбрать другой форум

 

Здравствуйте, Посетитель!

вид форума:
Линейный форум Структурный форум

тема: Горизонтальное меню. Помогите избавиться от <li> разумным способом
 
 автор: Лена   (09.07.2008 в 11:49)   письмо автору
 
 


<?php
function showTree($parent,$level) {
global 
$list$smarty$link;
$q mysql_query("SELECT * FROM modules WHERE visib=1 and pid=$parent and id_blocks=6 ORDER BY id_mod") or die (mysql_error()); 
if (
$level && mysql_num_rows($q) > 0) {
$divopn "<div id='dropmenu2_a' class='dropmenudiv_a' style='width: 150px;'>";
$divcls "</div>";
$liopn "";
$licls "";
} else{
    
$divopn "";
    
$divcls "";
      
$liopn "<li>";
    
$licls "</li>";
    
$list .= $divopn;
    }
while (
$row mysql_fetch_row($q)) {
      
$title $row[3];
      
$list .= $liopn;
    
$list .= "<A HREF='?id=$row[0]' title=\"$title\"><span>".htmlspecialchars($title)."</span></A>";
    
showTree($row[0],$level+1);
    
$list .= $licls;
    }
$list .= $divcls;
}
$list "<div id='colortab' class='ddcolortabs'>";
$list .= "<ul>";
showTree(0,0);
$list .= "</ul>";
$list .= "</div>";
?>


Проблема такая: в результирующем коде внутри <div></div>, которые выводят подменю, появляются вложенные <li></li>. Как он них избавиться, чтобы получилось вот такое:


<div id="colortab" class="ddcolortabs">
<ul>
<li></li>
<li><a href="" title="CSS" rel="dropmenu2_a"><span>3333</span></a></li>
</ul>
</div>
<!--подменю -->
<div id="dropmenu2_a" class="dropmenudiv_a" style="width: 150px;">
<a href="">11111</a>
<a href="">22222</a>
</div>


Я не привожу стили и JS, если в этом есть необходимость, скажите.
Сейчас на данный момент все меню - и родители, и потомки выводятся в одну строку.
Заранее всем спасибо.

   
 
 автор: Trianon   (09.07.2008 в 13:45)   письмо автору
 
   для: Лена   (09.07.2008 в 11:49)
 

Вот этот оператор , похоже, у Вас живет своей жизнью. Меняется от версии к версии как бог на душу положит.
if ($level > 0 && mysql_num_rows($q) > 0) {
$divopn = "<div id='dropmenu2_a' class='dropmenudiv_a' style='width: 150px;'>";
$divcls = "</div>";
$liopn = "";
$licls = "";
} else{
    $divopn = "";
    $divcls = "";
      $liopn = "<li>";
    $licls = "</li>";
    $list .= $divopn;
    }

В ветви else Вы сами пишете - Если вложенных элементов нет, ставим $liopn = "<li>"; $licls = "</li>";

Зачем?

   
 
 автор: Лена   (09.07.2008 в 14:13)   письмо автору
 
   для: Trianon   (09.07.2008 в 13:45)
 

Если вложенных элементов нет, мы оформляем каждый элемент в виде элемента списка:
<li><A HREF='?id=24' title="О нас"><span>О нас</span></A>
Это будет список родителей.

Если же вложенные элементы есть, то внутри <li> появляется свой стиль (<div></div>). И тогда результирующий код будет вот таким:
<li>
<div id='dropmenu2_a' class='dropmenudiv_a' style='width: 150px;'>
<A HREF='?id=26' title="Информация"><span>Информация</span></A>
<A HREF='?id=27' title="Связаться с нами"><span>Связаться с нами</span></A>
</div>
</li>


Переставила у себя в коде скобку:

else{
    $divopn = "";
    $divcls = "";
      $liopn = "<li>";
    $licls = "</li>";
    } 
    $list .= $divopn;


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

   
 
 автор: Trianon   (09.07.2008 в 14:54)   письмо автору
 
   для: Лена   (09.07.2008 в 14:13)
 

Приведите пожалуйста дамп структуры и данных таблицы.
У меня уже нет сил рассуждать на уровне голой теории.

   
 
 автор: Лена   (09.07.2008 в 15:33)   письмо автору
1.9 Кб
 
   для: Trianon   (09.07.2008 в 14:54)
 

Дамп таблицы. Все, что относится к меню.

   
 
 автор: Trianon   (09.07.2008 в 15:57)   письмо автору
 
   для: Лена   (09.07.2008 в 15:33)
 

То есть уровней всего и ровно два?

   
 
 автор: Лена   (09.07.2008 в 16:32)   письмо автору
 
   для: Trianon   (09.07.2008 в 15:57)
 

Да, уровней всего два

   
 
 автор: Trianon   (09.07.2008 в 16:43)   письмо автору
 
   для: Лена   (09.07.2008 в 16:32)
 

Вот те раз...
Тогда логично предположить, что верхний уровень и нижний уровни отображаются совсем по-разному.
И тогда здесь совершенно не нужна рекурсия. Рекурсия предполагает одинаковую (или очень близкую) обработку на всех уровнях. А в Вашем случае она только мешать будет.

Вопрос номер два. Как должен выглядеть HTML-код для приведенных в предыдущем посте строк таблицы?
Похоже, проще будет написать php-код, просто зная аргумент и результат.

   
 
 автор: Лена   (09.07.2008 в 17:06)   письмо автору
9.8 Кб
 
   для: Trianon   (09.07.2008 в 16:43)
 

Мне рекурсия жить не мешает, но если здесь лучше без нее, то давайте пробовать.
Я вам высылаю все, что есть в этом меню, стили и JS, в теле - HTML-код, который должен получиться. Я не помню, как там идут по порядку пункты меню, написала в разброс, но смысл, что верхний уровень одним стилем выводится, нижний - другим.

   
 
 автор: White_Owl   (09.07.2008 в 17:28)   письмо автору
 
   для: Лена   (09.07.2008 в 17:06)
 

Честно говоря смутно представляю что Вы хотите получить. Но чтобы избавится от <li> в подменю попробуйте заменить код на следующее


<?php
function showTree($parent,$level) {
global 
$list$smarty$link;
$q mysql_query("SELECT * FROM modules WHERE visib=1 and pid=$parent and id_blocks=6 ORDER BY id_mod") or die (mysql_error()); 
if (
$level && mysql_num_rows($q) > 0) {
$divopn "<div id='dropmenu2_a' class='dropmenudiv_a' style='width: 150px;'>";
$divcls "</div>";
$liopn "";
$licls "";
} else{
    
$divopn "";
    
$divcls "";
    
//$liopn = "<li>";
    //$licls = "</li>";
    
$list .= $divopn;
    }    
    
while (
$row mysql_fetch_row($q)) {
    
$title $row[3];
    
//$list .= $liopn;
    
$list .= "<A HREF='?id=$row[0]' title=\"$title\"><span>".htmlspecialchars($title)."</span></A>";
    
showTree($row[0],$level+1);
    
//$list .= $licls;
    
}
$list .= $divcls;
}
$list "<div id='colortab' class='ddcolortabs'>";
//$list .= "<ul>";
showTree(0,0);
//$list .= "</ul>";
$list .= "</div>";
?> 


И если не сложно можно посмотреть что именно Вы заменили ?

   
 
 автор: Лена   (09.07.2008 в 17:36)   письмо автору
 
   для: White_Owl   (09.07.2008 в 17:28)
 

>Честно говоря смутно представляю что Вы хотите получить...

Не обижайтесь, но вы, похоже, вообще себе не представляете, что я хочу получить. Почитайте предыдущие посты. Там в аттачменте все файлы.

   
 
 автор: Trianon   (09.07.2008 в 18:55)   письмо автору
 
   для: Лена   (09.07.2008 в 17:06)
 

Вот примерно то, что вышло.
<?php
   
require_once('dbconfig.php');

/* Это то, что требуется получить:

<div id="colortab" class="ddcolortabs">
<ul>
<li><a href="" title="Главная"><span>Главная</span></a></li>
<li><a href="" title="Карта сайта"><span>Карта сайта</span></a></li>
<li><a href="" title="О нас" rel="dropmenu1_a"><span>О нас</span></a></li>
<li><a href="" title="Архив" rel="dropmenu2_a"><span>Архив</span></a></li>
</ul>
</div>

<div class="ddcolortabsline">&nbsp;</div>

<!--подменю -->
<div id="dropmenu1_a" class="dropmenudiv_a" style="width: 150px;">
<a href="">Контакты1</a>
<a href="">Связаться с вами1</a>
</div>
<div id="dropmenu2_a" class="dropmenudiv_a" style="width: 150px;">
<a href="">Контакты2</a>
<a href="">Связаться с вами2</a>
</div>

* А это сам код: */

   
$sql =
   
"SELECT  m.id_mod     AS mid_mod
             ,m.name         AS mname
             ,m.descr         AS mdescr
             ,e.id_mod     AS eid_mod
             ,e.name         AS ename
             ,e.descr         AS edescr
    FROM modules AS m
         LEFT JOIN modules AS e
             ON  m.id_mod = e.pid AND e.id_blocks = 6 AND e.visib=1
          WHERE m.pid = 0 AND m.id_blocks = 6 AND m.visib=1
       ORDER BY mid_mod, eid_mod"
;

    
$res mysql_query($sql) or die("Error in $sql : ".mysql_error());

    for(
$m = array(),$mhtm $ehtm $cmod $mclose $eclose '';
        
$row mysql_fetch_assoc($res) ;)
    {
        
$mid_mod $row['mid_mod'];
        
$mname htmlspecialchars($row['mname']);
        
$mdescr htmlspecialchars($row['mdescr']);
        
$eid_mod $row['eid_mod'];
        
$ename htmlspecialchars($row['ename']);
        
$edescr htmlspecialchars($row['edescr']);
        if(
$cmod != $mid_mod)
        {
           
$cmod $mid_mod;
           
$ehtm .= $eclose$eclose ='';
           
$relname $rel '';
           if(!empty(
$eid_mod))
           {
               
$relname '"dropmenu'.$cmod.'_a"';
               
$rel " rel=$relname";
           }
           
$mhtm .=   "<li><a href=\"?m=$cmod\" title=\"$mdescr\" $rel"
                    
"><span>$mname</span></a></li>\r\n";
           if(!empty(
$eid_mod))
           {
              
$ehtm .= '<div id="dropmenu'.$eid_mod.'_a "'
                     
' class="dropmenudiv_a" style="width: 150px;">'."\r\n";
              
$eclose "</div>\r\n";
           }
        }
        if(!empty(
$eid_mod))
           
$ehtm .= '<a href="'."?m=$cmod&e=$eid_mod".'">'.$ename.'</a>'."\r\n";
    }
    if(
$mclose != ''$mhtm .= $mclose;
    if(
$eclose != ''$ehtm .= $eclose;

    
$h '
<div id="colortab" class="ddcolortabs">
<ul>
'
.$mhtm.'</ul>
</div>

<div class="ddcolortabsline">&nbsp;</div>

<!--подменю -->
'
.$ehtm;
    echo 
$h;
?>

Начало со стилями, JS-кодом , и прочими весёлостями , конечно, надо добавить сверху.

   
 
 автор: Лена   (10.07.2008 в 15:26)   письмо автору
 
   для: Trianon   (09.07.2008 в 18:55)
 

В запросе разобралась. Для тех, кто еще этого не знает, - http://www.mysql.ru/docs/gruber/ или в Гугле поискать "Объединение таблиц".
Здесь - объединение таблицы самой себя, как бы создаются две ее копии и чтобы они были обработаны независимо в одном запросе, каждой присваивается псевдоним (m, e). Чтобы ссылаться к отдельным столбцам таблиц внутри запроса им тоже присваиваются псевдонимы.
Вопрос 1. Предложение FROM modules AS m в разных источниках встречается как FROM modules m. Это альтернативный синтаксис?
Когда получаем результаты выполнения запроса, в цикле for начинается их перебор.
Вопрос 2. Непонятно условие цикла $mhtm = $ehtm = $cmod = $mclose = $eclose = '';
Цикл работает до тех пор, пока эти переменные пустые. Допустим, выбирается первый ряд из таблицы - и тогда $mhtm заполняется и уже эта переменная не пустая. Объясните.
Вопрос 3.
$cmod = $mid_mod; Зачем вводить еще одну переменную, почему просто в нужном месте не использовать уже ранее определенную $mid_mod?
Все остальное понятно.
Большое человеческое спасибо, Trianon

   
 
 автор: Trianon   (10.07.2008 в 16:30)   письмо автору
 
   для: Лена   (10.07.2008 в 15:26)
 

>В запросе разобралась.
Респект.

0. Операцию JOIN обычно называют соединением. Термин "объединение" применяют для операции UNION. В остальном таки да.

1. Да. Но я привык писать AS явно. Некоторые СУБД "едят" один вариант , некоторые другой. MySQL "ест" оба.

2. for($m = array(),$mhtm = $ehtm = $cmod = $mclose = $eclose = '';
$row = mysql_fetch_assoc($res) ;)
>Непонятно условие цикла $mhtm = $ehtm = $cmod = $mclose = $eclose = '';
Это не условие. Условие в for-заголовке начинается после точки-с-запятой Это обычная операция присваивания, как и $m=array() . Можно было записать её до for отдельным оператором или даже несколькими. Всем указанным переменным до цикла присваиваются пустые строки.
Кстати, только сейчас заметил: $m=array(), вообще не нужно. Была мысль сперва сохранить строки в отдельном массиве. Потом обошелся. Так что надо сократить до for( $mhtm=$ehtm = ...

Итак, условие у нас после (точнее между) точки-с-запятой: $row = mysql_fetch_assoc($res)
На самом деле это тоже операция присваивания, и цикл оценивает её результат таким образом
($row = mysql_fetch_assoc($res)) != false
То бишь присвоить переменной $row массив с очередной строкой выборки (если строка есть) либо признак её отсутствия(если строки нету) . Присвоенное сравнить с false. признак окончания совпадет с false - массив окажется отличен.

3. переменная $cmod введена в первую очередь для создания условия
if($cmod != $mid_mod)
{
и ветви под ним. Ветвь эта выполняется лишь один раз на группу элементов подменю соответствующих одному элементу горизонтального меню.
Эта переменная (точнее это условие) позволяет разбить строки на группы.
Для второй и последующих строк группы из всего тела цикла выполняется только
if(!empty($eid_mod))
$ehtm .= '<a href="'."?m=$cmod&e=$eid_mod".'">'.$ename.'</a>'."\r\n";
и больше ничего.

Почему не использовал $mid_mod в ссылках?
Мог и её. Использовал ту, что легче написать :)

   
 
 автор: Лена   (11.07.2008 в 11:00)   письмо автору
 
   для: Trianon   (10.07.2008 в 16:30)
 

Спасибо за объяснения.
А теперь самое интересное: меню не работает.
Выводятся только родители, непослушные потомки опять куда-то исчезают.
В результирующем коде получается вот что:

//это строка родителя, у которого есть потомки
<li><a href="?m=24" title="Установление контактов с администратором сайта"  rel="dropmenu24_a"><span>О нас</span></a></li>
//а это блок подменю этого родителя
<div id="dropmenu26_a " class="dropmenudiv_a" style="width: 150px;">
<a href="?m=24&e=26">Информация</a>
<a href="?m=24&e=27">Связаться с нами</a>
</div>

Как можно объяснить, что ссылаемся мы на dropmenu24_a (rel="dropmenu24_a"), а получается <div id="dropmenu26_a "? 24 - это родитель. Зачем родительскому элементу <li> делать ссылку на себя же, когда ссылаться надо на id дочерней ветки, которая открывается?
Может, в этом причина, почему не выходит?

   
 
 автор: Trianon   (11.07.2008 в 11:24)   письмо автору
 
   для: Лена   (11.07.2008 в 11:00)
 

Само собой...
Похоже, я умудрился не последний вариант в ответ отправить.

<?


        
if($cmod != $mid_mod)
        {
           
$cmod $mid_mod;
           
$ehtm .= $eclose$eclose ='';
           
$relname $rel '';
           if(!empty(
$eid_mod))
           {
               
$relname '"dropmenu'.$cmod.'_a"';
               
$rel " rel=$relname";
               
$ehtm .= "<div id=$relname"
                     
' class="dropmenudiv_a" style="width: 150px;">'."\r\n";
               
$eclose "</div>\r\n";
           }
           
$mhtm .=   "<li><a href=\"?m=$cmod\" title=\"$mdescr\" $rel"
                    
"><span>$mname</span></a></li>\r\n";
        }
        if(!empty(
$eid_mod))
           
$ehtm .= '<a href="'."?m=$cmod&e=$eid_mod".'">'.$ename.'</a>'."\r\n";

   
 
 автор: Лена   (11.07.2008 в 12:01)   письмо автору
 
   для: Trianon   (11.07.2008 в 11:24)
 

Только не злитесь. Там еще один кусок кода есть, который я вам не прислала. Почему-то он выпал.

<script type="text/javascript">
//Синтаксис: tabdropdown.init("menu_id", [integer OR "auto"])
tabdropdown.init("colortab", 3)
</script>

Может, в этом проблема? Я его вставила в общий код, но ничего не поменялось

   
 
 автор: Trianon   (11.07.2008 в 12:22)   письмо автору
 
   для: Лена   (11.07.2008 в 12:01)
 

У меня элементы подменю выскакивали и без него. Точнее - в том комплекте, что Вы тогда прислали.
Так что врядли он сильно влияет на замеченный Вами баг.
А вот неверное определение ссылки на дочерний блок влияет однозначно.
После замены фрагмента скрипта лучше не стало?

Я злюсь? И в мыслях не было...

   
 
 автор: Лена   (11.07.2008 в 12:34)   письмо автору
 
   для: Trianon   (11.07.2008 в 12:22)
 

Нет, лучше не стало. Ни мне, ни скрипту :-)
Хотя теперь прямая ссылка из родителя, которая выводится в дочерний блок, есть.
Что будем делать?

   
 
 автор: Trianon   (11.07.2008 в 13:01)   письмо автору
5.6 Кб
 
   для: Лена   (11.07.2008 в 12:34)
 

Сравнивать. У меня вот такой набор файлов выводит Ваше меню.

   
 
 автор: Лена   (11.07.2008 в 14:36)   письмо автору
 
   для: Trianon   (11.07.2008 в 13:01)
 

We are the chempions!
Получилось!!!
Но главный chempion - это вы, Trianon :-))
Ошибки свои нашла. Спасибо, я вам очень благодарна.

   
 
 автор: HaJIuBauKa   (09.07.2008 в 18:12)   письмо автору
 
   для: Лена   (09.07.2008 в 11:49)
 

if ($level > 0 && mysql_num_rows($q) > 0) {

попробуйте так
if (($level > 0) && (mysql_num_rows($q) > 0)) {


Возможно PHP вычисляет это логическое выражение неверно

   
 
 автор: mihdan   (11.07.2008 в 16:10)   письмо автору
 
   для: Лена   (09.07.2008 в 11:49)
 

<div> не нужен, рекурсия тож

   
Rambler's Top100
вверх

Rambler's Top100 Яндекс.Метрика Яндекс цитирования