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

Форум PHP

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

 

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

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

тема: как в рекурсии разные уровни выводить с разными стилями
 
 автор: Лена   (25.06.2008 в 14:01)   письмо автору
 
 

Помогите, пожалуйста, сделать вот такую штуку в горизонтальном выпадающем меню. Нулевой уровень должен выводиться одним стилем, первый уровень - с другим стилем. Как мне в моем коде отделить уровни один от другого, чтобы в шаблон передавалось две переменные: $list = список тех разделов меню, которые принадлежат к 0 уровню, $sub_list = список тех разделов, которые принадлежат к следующему уровню. А там уже в шаблоне к каждому уровню прикручивается свой стиль.

Вот весь код:

<?php
require ("smarty/Smarty.class.php");
include(
"configs/dbopen.php");

$list "";
$sub_list "";
function 
ShowTree($parent_id$lvl)
{
global 
$link$lvl;
global 
$list$sub_list;
    
$lvl++;
    
$sql "SELECT *  FROM `modules` WHERE pid = " $parent_id " AND id_blocks = 6 AND visib = 1 ORDER BY id_mod ";
    
$result mysql_query($sql$link);
    if(
mysql_num_rows($result) > 0) {

        
$list.= "<ul id='nav'>";
        while ( 
$row mysql_fetch_assoc($result) )
        {
        
$id $row['id_mod'];
        
$list.= "<li class='top'><A HREF='?id=$id' class='top_link'>{$row['name']}</A>&nbsp;&nbsp;</li>";
        
//print "<pre>";
        //print_r($row);
        //print "</pre>";
        
if($parent_id!=0){
            
$sub_list.= print "<div class='sub'>"
            
$sub_list.= ShowTree($id$lvl);
            
$sub_list.= print "</div>";
            }
        
$lvl--;
        }
    
$list.= "</UL>";
    }
$a = array($list$sub_list);    
return 
$a;
}
$a ShowTree(00);


$smarty->assign('list',$a[0]);
$smarty->assign('sub_list',$a[1]);
$output=$smarty->fetch("gor_menu.tpl");
print 
$output;
?>

   
 
 автор: mihdan   (25.06.2008 в 16:50)   письмо автору
 
   для: Лена   (25.06.2008 в 14:01)
 

HTML

<ul class="level<?=$lvl?>">
....
</ul>


CSS

ul.level1 {
}
ul.level2 {
}
ul.level3 {
}

   
 
 автор: Axxil   (25.06.2008 в 17:11)   письмо автору
 
   для: Лена   (25.06.2008 в 14:01)
 

Лишняя констукция
"<div class='sub'>"

оставьте просто
$sub_list.= ShowTree($id, $lvl);

а перед этим пишите так:
$list.= "<ul id='level_'.$lvl.''>";


а стиль см. выше у mihdan

И ещё, элемент <li> для вложенного списка должен быть открыт. Т.е. должно получится что-то типа
<ul id="level_0">
  <li>Item1</li>
  <li>Item2</li>
  <li>
    <ul id="level_1">
      <li>Item1</li>
      <li>Item2</li>
   </ul>
  </li>
</ul>

   
 
 автор: sim5   (25.06.2008 в 18:35)   письмо автору
 
   для: Лена   (25.06.2008 в 14:01)
 

Времени нет, поэтому только основное:

<?
function showTree($parent,$level) {
  global 
$list;
  
//проблема в том, что не проверяется уровень: родитель-потомок
  
$q mysql_query("SELECT * FROM modules WHERE visib=1 and pid=$parent ORDER BY name"); 
  
//определяем класс элементов
  
$class $level "sub" "top";
  
//если потомок и получен ряд из запроса
  //(если не определять получен ли ряд из запроса,
  //то в коде будет появляться пустое вложение элементов UL)
  
if ($level && mysql_num_rows($q) > 0) {
     
//убираем закрывающй тег LI (вложение потомка)
     
$list substr($list0, -5);
     
//устанавливаем вложенные элементы UL и закрываем родительский элемент LI
     
$ulopn "<ul class=\"sub\">";
     
$ulcls "</ul></li>";
  } else 
$ulopn $ulcls "";
  
$list .= $ulopn;
  while (
$row mysql_fetch_assoc($q)) {
     
//если требуется обработка массива вне функции (добавление элементов HTML-кода),
     //то необходимо возвращать уровень вложения, тогда можно так:
     //до цикла объявить массив: $a = array();
     //а в цикле выполнять это:
     //$row['name'] = htmlspecialchars($row['name']);
     //$row['level'] = $level;
     //$a[] = $row;
     //$b = showTree($row['id_mod'],$level++);
     //$a = array_merge($a, $b);
     //вернуть из функции массив $a
     
$list.= "<li class\"$class\"><A 
         HREF=\"?id=
$row[id_mod]\" 
         class='top_link'>"
.htmlspecialchars($row['name'])."</A></li>";
     
showTree($row['id_mod'],$level++);
  }
  
$list .= $ulcls;
  
//если переменная объявлена как глобальная, 
  //и мы работаем с ней, то возвращать из функции ничего не требуется
}
//определяем корневого родителя
$list "<ul id='nav'>";
//получаем элементы меню
showTree(0,0);
//закрываем корневой элемент
$list .= "</ul>";
?>

PS. Небольшое замечание: это рекурсия, поэтому не ставьте в запросе *, а пропишите в запросе конкретные поля (и лучше mysql_fetch_row()), которые нужны для отображения меню и для работы самой функции.

   
 
 автор: Лена   (26.06.2008 в 10:36)   письмо автору
 
   для: sim5   (25.06.2008 в 18:35)
 

Спасибо, sim5, но у меня не так получилось. Сама функция:

<?php
function showTree($parent,$level) {
 global 
$list;
 
$q mysql_query("SELECT * FROM modules WHERE visib=1 and pid=$parent and id_blocks = 6 ORDER BY id_mod") or die (mysql_error());
 
$class $level "sub" "top";
if (
$level && mysql_num_rows($q) > 0) {
   
$open "<ul>";
   
$clos "</ul>";
   } else 
$open $clos "";

 
$list .= $open;
 while (
$row mysql_fetch_assoc($q)) {
  
$list.= "<li class = \"$class\"><A HREF=\"?id=$row[id_mod]\" class='top_link'><span $tt>".htmlspecialchars($row['name'])."</span></A>";
  
showTree($row['id_mod'],$level+1);
  
$list.= "</li>";
 }
 
$list .= $clos;
}
?>


И еще одна мелочь. Есть $tt = "class='down'" - еще один стиль. В коде он определяется в <span>:

<?php
$list
.= "<li class = \"$class\"><A HREF=\"?id=$row[id_mod]\" class='top_link'><span $tt>".htmlspecialchars($row['name'])."</span></A>";
?>


Смысл $tt: если стиль работает, напротив элемента-родителя появляется маленький треугольничек (острием вниз), который показывает, что у этого элемента есть потомки. Вдобавок к этому без действия этого стиля потомки выводятся искаженно: текст больше, чем фон под ними. Поэтому, чтобы было все красиво, надо добавить $tt. Как задать условие вот такое: если у элемента есть вложения, то подключаем этот стиль, если нет - не подключаем?

<?php
if() $tt "class='down'" "";
else 
$tt =""
?>


Что нужно поставить в if()?

   
 
 автор: sim5   (26.06.2008 в 11:47)   письмо автору
 
   для: Лена   (26.06.2008 в 10:36)
 

Сперва надо разобраться с классами, например, у вас не будет выпадать список подкатегории, так как в коде не указан класс для вложенного элемента UL. Нужно так: $open = "<ul class=\"sub\">"; Стрелка скорее всего уже нарисована на фоновом рисунке, который будет определяться для стилей элементов имеющих вложения. Которые его не имеют, скорее всего будут иметь такой же рисунок но без стрелки. Надо посмотреть внимательно CSS файл и сценарий скрипта.
PS. Мне известно, что кроме имен модулей, ваша таблица имеет их дескрипторы и прочее. Почему вы гоняете в рекурсии лишние поля таблицы? Что будет, если вы решите добавить еще модуль, который будет отображаться в этом меню, и который нужно будет ставить не последним, и вторым например? Это же касается и пунктов вложенных элементов меню. Сортировака в этом случае ни по имени, ни по id модуля никак не подойдет, значит надо... А еще нужно учитывать минимальное разрешение по ширине - 1024 рх.

   
 
 автор: Лена   (26.06.2008 в 14:49)   письмо автору
 
   для: sim5   (26.06.2008 в 11:47)
 

Вот у меня почему список не выпадал... Теперь уже все в порядке.
От лишних полей избавилась:
$q = mysql_query("SELECT id_mod, pid, id_blocks, name, visib FROM modules WHERE visib=1 and pid=$parent and id_blocks = 6 ORDER BY id_mod");
По сортировке. Допустим вставляю модуль 6 где-то посредине, между 2 и 3 модулем, можно ли поставить указатель, что модуль вставляется в это место? Нужно получается указать позицию модуля по отношению к другим, которые уже имеют свои позиции? Тогда нужно в таблицу еще одно поле добавить - pos, и потом отсортировать по позиции? Если я сказала глупость, сразу скажите, а если нет - буду думать в этом направлении.
О минимальном разрешении. Это делается с помощью JS.
<script>
var ws = screen.width;
var hs = screen.height;
alert(ws+'x'+hs)
</script>
Как передать это на сервер, пока не знаю, буду читать. На все нужно время.

   
 
 автор: sim5   (26.06.2008 в 15:53)   письмо автору
 
   для: Лена   (26.06.2008 в 14:49)
 

Если кратко то так:
Из всех полей таблицы в меню используются только id_mod, name, поэтому остальные получать нет смысла, если только они не потребуются для определения чего либо, например, для проверки при логике построения самого меню (те что в логике WHERE указаны, получать не нужно).
Именно добавление поля в таблицу, которое бы указывало позицию пункта в меню, позволит вам его сортировать независимо от их имен или id номера - номер может в последствии добавления (или удаления) потерять стройный порядок, ну а имена, тем более не подойдут. Эту сортировку желательно иметь всем, включая вложения, так, чтобы получалось логично, например, в меню программ, меню "Помощь" -> "Помощь" -> "..." -> "О программе", а не наоборот.
О минимальном разрешении я не в том смысле. Его даже и получать нет необходимости. Ну получите вы его, узнаете, что 1024 и что? Если ваше меню будет содержать количество кнопок, которые не будут помещаться по горизонтали в этом разрешении, тогда что? То есть, нужно либо ограничиваться кнопками в меню, либо иметь меню с возможностью трансформации, либо выбирать меню иной структуры, в две строки, например, или искать иное решение. И это нужно делать сразу - 1024 это пока массовое разрешение и вы должны это учитывать.

   
 
 автор: Лена   (27.06.2008 в 11:50)   письмо автору
 
   для: sim5   (26.06.2008 в 15:53)
 

Появилась еще одна проблемма.
Тот вариант кода, где при вложении потомков вырезается (substr())закрывающий тэг </li>, в IE (6 версия) получается ступеньками: каждый модуль расположен на ступеньку ниже предыдущего, что это может быть? А в FireFox - все нормально. Тот вариант меню, где тэг </li> не вырезается (см. выше) - в IE отображается нормально.
Кнопки решила немного уменьшить, чтобы все влезло в размер экрана.

   
 
 автор: sim5   (27.06.2008 в 12:43)   письмо автору
 
   для: Лена   (27.06.2008 в 11:50)
 

Это уже разница "во вкусах к HTML" разных браузеров, и касается HTML раздела. Просмотрите сам исходник меню (тот кторый вы где-то взяли, его пример) в разных браузерах - если он также будет отображаться различно, то нужно править CSS, если нет, то где-то допускается ошибка в указании стилей при формировании меню.

   
 
 автор: Лена   (27.06.2008 в 12:53)   письмо автору
 
   для: sim5   (27.06.2008 в 12:43)
 

нет, исходник отображается везде нормально, значит надо в стилях искать

   
 
 автор: mihdan   (29.06.2008 в 02:10)   письмо автору
 
   для: Лена   (27.06.2008 в 12:53)
 

float: left

для тега li, для тега a float не нужен(иначе ступеньки пойдут)

   
 
 автор: Лена   (02.07.2008 в 09:57)   письмо автору
 
   для: mihdan   (29.06.2008 в 02:10)
 

Где именно для тега li, для тега a (как вы написали) float не нужен?
Вот кусок кода, где встречается float:

#nav {padding:0; margin:0; list-style:none; height:38px; background:#fff url(three_0.gif) repeat-x; position:relative; z-index:500; font-family:arial, verdana, sans-serif;}
#nav li.top {display:block; float:left; height:38px;}
#nav li a.top_link {display:block; float:left; height:35px; line-height:33px; color:#ccc; text-decoration:none; font-size:11px; font-weight:bold; padding:0 0 0 12px; cursor:pointer;background: url(three_0.gif);}
#nav li a.top_link span {float:left; display:block; padding:0 24px 0 12px; height:35px; background: url(three_0.gif) right top no-repeat;}
#nav li a.top_link span.down {float:left; display:block; padding:0 24px 0 12px; height:35px; background: url(three_0a.gif) no-repeat right top;}

#nav li:hover a.top_link, 
#nav li.iehover a.top_link {color:#fff; background: url(three_1.gif) no-repeat; cursor:pointer;}
#nav li:hover a.top_link span,
#nav li.iehover a.top_link span {background:url(three_1.gif) no-repeat right top; cursor:pointer;}
#nav li:hover a.top_link span.down,
#nav li.iehover a.top_link span.down {background:url(three_1a.gif) no-repeat right top; cursor:pointer;}

/* Default list styling */

#nav li:hover {position:relative; z-index:200; cursor:pointer;}

#nav li:hover ul.sub
{left:1px; top:38px; background: #bbd37e; padding:3px; border:1px solid #5c731e; white-space:nowrap; width:90px; height:auto; z-index:300; cursor:pointer;}
#nav li:hover ul.sub li
{display:block; height:20px; position:relative; float:left; width:90px; font-weight:normal; cursor:pointer;}



Могу привести весь код

   
 
 автор: serjinio   (30.06.2008 в 22:41)   письмо автору
 
   для: Лена   (26.06.2008 в 10:36)
 

Ваш код прекрасно работает, только не хватает первого<UL> в начале списка(можно посмотреть в коде)надо добавить перед функцией....
$list.="<ul>\n";
function showTree($parent,$level) {
 global $list;.............

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

   
 
 автор: kukuikar   (01.07.2008 в 10:08)   письмо автору
 
   для: serjinio   (30.06.2008 в 22:41)
 

а у меня MySQL client ran out of memory

   
 
 автор: mihdan   (03.07.2008 в 18:42)   письмо автору
 
   для: serjinio   (30.06.2008 в 22:41)
 

Через css естественно

   
 
 автор: serjinio   (06.07.2008 в 00:22)   письмо автору
 
   для: mihdan   (03.07.2008 в 18:42)
 

Очень мудрый ответ...
вот для этого примера стили категории и субкатегории ,что я использую...
.top{font-size:14px;font-weight:bold;padding-top: 10px;padding-left: 5px;}
.sub{font-size:11px;font-weight:normal;padding-left:10px;}

ну и как изменить цвет шрифта?????если б все так было просто...

   
 
 автор: sms-send   (06.07.2008 в 00:33)   письмо автору
 
   для: serjinio   (06.07.2008 в 00:22)
 

Через свойство color не получается?)

   
 
 автор: serjinio   (06.07.2008 в 10:55)   письмо автору
 
   для: sms-send   (06.07.2008 в 00:33)
 

Дело в том что вывод будет в виде...
<li class='top'><A HREF='?id=$id' </A>1111111</li>"; 
<li class='sub'><A HREF='?id=$id' </A>22222</li>"; 

те класс применяется только к li ,и не распространяется на ссылку внутри списка...Я имею ввиду цвет ссылки....
Хм...сначала написал, потом дошло ...применил классы к A...все запустилось....

   
Rambler's Top100
вверх

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