Xpoint
   [напомнить пароль]

Меню на PHP с вложениями

Метки: [без меток]
2011-07-16 18:45:17 [обр] Serg(0/14)[досье]
Возникла необходимость создания меню на PHP с вложениями.
Главная проблема из имеющихся решений то, что меню не имеет полного листинга html-кода собственно меню.
Submenu для того или иного раздела подставляется в меню только после клика на заголовок раздела и перезагруки страницы.
Остальные разделы не имеют submenu, а только ссылки заголовков разделов.
Может, кто подскажет нужное решение.
Меню подобного рода на JavaScript не предлагать.
Могу выложить листинг скрипта, где происходит формирование меню.
спустя 2 часа 32 минуты [обр] Thirteensmay(17/157)[досье]
Подправьте листинг так чтобы меню формировалось сразу все, с сабменю. Или вы хотите чтобы это ктото сделал за вас ? Тогда так и говорите.
спустя 4 минуты [обр] Serg(0/14)[досье]
<?php
// Main menu items

  $mainMenu['Index']      = 'index.php';
  $mainMenu['Projects']  = 'projects.php';
  $mainMenu['About']  = 'about.php';
  $mainMenu['Листинг скрипта menu.php']  = 'list.php';
  $mainMenu['Листинг html-кода меню']  = 'htmlmenu.php';

// Sub menu items
  $subMenu['Index']['Index-1'] = 'index1.php';
  $subMenu['Index']['Index-2'] = 'index2.php';

  $subMenu['Projects']['Projects-1'] = 'product1.php';
  $subMenu['Projects']['Projects-2'] = 'product2.php';

  $subMenu['About']['About-1']   = 'about1.php';
  $subMenu['About']['About-2']   = 'about2.php';
  

class maxNavigation {

   function showMenu(){
      global $mainMenu,$subMenu;

      $actualPage = $_SERVER['PHP_SELF'];
      $actualPath = $_SERVER['REQUEST_URI'];

      $actualPageName = basename($actualPage);

      $actMenu = '';
      foreach ($mainMenu as $menu => $link) {
          if ($link == $actualPageName) $actMenu = $menu;
          if (isset($subMenu[$menu])){
             foreach ($subMenu[$menu] as $menuSub => $linkSub) {
                  if ($linkSub == $actualPageName) $actMenu = $menu;
             }
          }
       }


       // Now display the menu
       foreach ($mainMenu as $menu => $link) {
         $class = ' class="mainMenuLink" ';
         if ($actualPageName == $link) $class=' class="mainMenuLinkSelected" ';

         echo '<a'.$class.' href="'.$link.'"><em></em>'.$menu.'</a>';

         if ( ($actMenu == $menu) && (isset($subMenu[$menu])) ){
             foreach ($subMenu[$menu] as $menuSub => $linkSub) {
                 $class = ' class="subMenuLink" ';
                 if ($actualPageName == $linkSub) $class=' class="subMenuLinkSelected" ';
                  echo '<a'.$class.' href="'.$linkSub.'"><em></em>'.$menuSub.'</a>';
             }
          }
     }


   }

}

$navi = new maxNavigation();
$navi->showMenu();

?>
Может быть еще, что-то надо?
спустя 2 минуты [обр] Serg(0/14)[досье]
На <em></em> не оращаем внимания, забыл удалить.
Да и еще никакого обращения к базам данных быть не должно,
все скрипт и меню в одном файле, желательно :)
спустя 2 дня 14 часов [обр] Jared(3/26)[досье]

Serg[досье],
 - если можете не использовать 'global' - не используйте... передавайте нужные данные параметрами функции/метода.
 - если вы не пишете одноразовую фигню на коленке, никогда не мешайте PHP и HTML код, это ужасно. Шаблонизаторов в сети over9k, используйте их. Если используете в качестве шаблонизатора сам PHP, разделите файлы на шаблоны, отвечающие только за выдачу и файлы с основным кодом, которые в том числе готовят данные для шаблонов.
 - если у вас класс без свойств с единственным статическим методом, скорее всего вам не нужен класс.

Ну и на последок... весь этот запутанный листинг не нужен. Ваша задача решается в 5 значимых строк. Примерно так (быстро, на коленке, грязно, не тестил):

<?
//-------------------- Data ------------------------
// Main menu items

$mainMenu['Index']      = 'index.php';
$mainMenu['Projects']  = 'projects.php';
$mainMenu['About']  = 'about.php';
$mainMenu['Листинг скрипта menu.php']  = 'list.php';
$mainMenu['Листинг html-кода меню']  = 'htmlmenu.php';

// Sub menu items
$subMenu['Index']['Index-1'] = 'index1.php';
$subMenu['Index']['Index-2'] = 'index2.php';

$subMenu['Projects']['Projects-1'] = 'product1.php';
$subMenu['Projects']['Projects-2'] = 'product2.php';

$subMenu['About']['About-1']   = 'about1.php';
$subMenu['About']['About-2']   = 'about2.php';

//-------------------- Code ------------------------
foreach(array_keys($mainMenu) as $mmk)
{
   // main menu item
   print '<a class="main_menu_item'.(basename($_SERVER['PHP_SELF']) === $mainMenu[$mmk]?' mainMenuLinkSelected').'" href="'.$mainMenu[$mmk].'">'.$mmk.'</a>';

   // sub menu items
   if(array_key_exists($mmk,$subMenu))
   {
      foreach(array_keys($subMenu[$mmk]) as $smk)
         print '<a class="submenu_item'.(basename($_SERVER['PHP_SELF']) === $subMenu[$mmk][$smk]?' mainMenuLinkSelected').'" href="'.$subMenu[$mmk][$smk].'">'.$smk.'</a>';
   }

}
?>
спустя 1 час [обр] Serg(0/14)[досье]

Jared[досье] Спасибо, посмотрю.
Если честно, то вообще не разбираюсь в программировании :(
Оригинальное меню взято здесь - _http://www.phpf1.com
Но похоже и ваш вариант не решает проблемы.
Если рассмотреть по пунктам, как нужно, то:

  1. При первом открытии страницы, меню свернуто, доступны только заголовки разделов, если смотреть html-код
<a class="mainMenuLink" href="index.php">Index</a>
<a class="mainMenuLink" href="projects.php">Projects</a>
<a class="mainMenuLink" href="about.php">About</a>
<a class="mainMenuLink" href="list.php">Листинг скрипта menu.php</a>
<a class="mainMenuLink" href="htmlmenu.php">html-код меню</a>
  1. При клике на заголовке любого раздела после перезагрузки страницы меню принимает вид:
<a class="mainMenuLink" href="index.php">Index</a>
  <a class="subMenuLink" href="index1.php">Index-1</a>
  <a class="subMenuLink" href="index2.php">Index-2</a>

<a class="mainMenuLink" href="projects.php">Projects</a>
<a class="mainMenuLink" href="about.php">About</a>
<a class="mainMenuLink" href="list.php">Листинг скрипта menu.php</a>
<a class="mainMenuLink" href="htmlmenu.php">html-код меню</a>

  1. Как видим в других разделах submenu не подгружено, а надо чтобы всегда весь листинг html-кода меню был загружен и не важно свернуто ли меню полностью, открыт какой либо раздел, полный html-код должен присутствовать всегда
спустя 2 часа 50 минут [обр] Jared(3/26)[досье]
Serg[досье], мой код всегда показывает все пункты меню. Это то что нужно?
спустя 35 минут [обр] Serg(0/14)[досье]

Jared[досье]
Добрался наконец до Денвера.
Вот, что пишет:

Parse error:  syntax error, unexpected ')' in Z:\home\test.ru\www\menuphp\menu.php on line 25

Что-то с кавычками не ладно, а может и не в них дело, не понимаю :)

спустя 40 минут [обр] Serg(0/14)[досье]
У меня строка под номером 25 такая:
print '<a class="main_menu_item'.(basename($_SERVER['PHP_SELF']) === $mainMenu[$mmk]?' mainMenuLinkSelected').'" href="'.$mainMenu[$mmk].'">'.$mmk.'</a>';
спустя 1 час 38 минут [обр] Jared(3/26)[досье]
Serg[досье], пардон. Так должно работать:
<?
//-------------------- Data ------------------------
// Main menu items

$mainMenu['Index']      = 'index.php';
$mainMenu['Projects']  = 'projects.php';
$mainMenu['About']  = 'about.php';
$mainMenu['Листинг скрипта menu.php']  = 'list.php';
$mainMenu['Листинг html-кода меню']  = 'htmlmenu.php';

// Sub menu items
$subMenu['Index']['Index-1'] = 'index1.php';
$subMenu['Index']['Index-2'] = 'index2.php';

$subMenu['Projects']['Projects-1'] = 'product1.php';
$subMenu['Projects']['Projects-2'] = 'product2.php';

$subMenu['About']['About-1']   = 'about1.php';
$subMenu['About']['About-2']   = 'about2.php';

//-------------------- Code ------------------------
foreach(array_keys($mainMenu) as $mmk)
{
   // main menu item
   print '<a class="main_menu_item'.(basename($_SERVER['PHP_SELF']) === $mainMenu[$mmk] ? ' mainMenuLinkSelected' : '').'" href="'.$mainMenu[$mmk].'">'.$mmk.'</a>';

   // sub menu items
   if(array_key_exists($mmk,$subMenu))
   {
      foreach(array_keys($subMenu[$mmk]) as $smk)
         print '<a class="submenu_item'.(basename($_SERVER['PHP_SELF']) === $subMenu[$mmk][$smk] ? ' mainMenuLinkSelected' : '').'" href="'.$subMenu[$mmk][$smk].'">'.$smk.'</a>';
   }

}
?>
спустя 2 часа 7 минут [обр] Serg(0/14)[досье]
Jared[досье]
Спасибо, ошибка пропала, работает.
Сейчас стили перепишу.
Надо, чтобы не были видны submenu у всех разделов, как сейчас все сразу,
а появлялись у соотвествующий раздела, только после клика на заголовок этого раздела.
Может быть классов хватит для этих целей.
спустя 15 минут [обр] Jared(3/26)[досье]
Serg[досье], думаю, несколько строк на js решат вашу проблему.
спустя 24 минуты [обр] Serg(0/14)[досье]
Jared[досье]
А на PHP нельзя?
Может подскажете, как реализовать смену классов в ссылках,
как это сделано в оригинальном файле?
Скажем все submenu с помощью класса у которого прописан стиль dispaly:none; спрятаны,
клик по заголовку раздела в ссылки submenu этого раздела,
вместо класса у которого есть dispaly:none;
получает класс с dispaly:block;
Клик на заголовок другого раздела должен привести к тому, чтобы ранее открытое submenu свернулось, а нужное развернулось.
 
Если пристраивать JS, то стоит или огород городить, любой аккордеон с куками решает все проблемы,
а нужно меню именно на PHP. Хотя, как вариант рассмотреть можно, может у вас есть что-то на примете?
спустя 2 часа 10 минут [обр] Jared(3/26)[досье]

Serg[досье]

А на PHP нельзя?

Вам на клиенте надо или на сервере? Опишите задачу детально, с указанием что пользователь делает и что происходит (что открывается, что закрывается и происходит ли переход по ссылке).

Может подскажете, как реализовать смену классов в ссылках

Что значит смену классов? Мой текущий код даст класс main_menu_item ссылке первичного меню (дополнительно класс mainMenuLinkSelected если мы на той странице, куда ссылается ссылка) и submenu_item для пункта дочернего подменю (дополнительно класс mainMenuLinkSelected если мы на той странице, куда ссылается ссылка). Поменять имена классов, думаю, труда не составит. Стили к классам прикручивать стоит отдельной таблицей, а не инлайн-стилями.

Куки тут ну совсем не причем.

Задача, как бы она не была поставлена, в любом случае тривиальна. Делается за 5 минут несколькими строками кода и прикручиввать никаких сторонних решений с десятком-другим классов набитых говнокодом нет никакой нужды.

Все тот же мой говнокод с JS, точнее с кодом на jQuery для сворачивания-разворачивания подменю при нажатии на ссылку-родителя:

//-------------------- Code ------------------------
foreach(array_keys($mainMenu) as $mmk)
{
   // main menu item
   print '<div><a onclick="$(this).nexAll().toggle(); return false;" class="main_menu_item'.(basename($_SERVER['PHP_SELF']) === $mainMenu[$mmk] ? ' mainMenuLinkSelected' : '').'" href="'.$mainMenu[$mmk].'">'.$mmk.'</a>';

   // sub menu items
   if(array_key_exists($mmk,$subMenu))
   {
      foreach(array_keys($subMenu[$mmk]) as $smk)
         print '<a class="submenu_item'.(basename($_SERVER['PHP_SELF']) === $subMenu[$mmk][$smk] ? ' mainMenuLinkSelected' : '').'" href="'.$subMenu[$mmk][$smk].'">'.$smk.'</a>';
   }

   print '</div>';

}
спустя 49 минут [обр] Serg(0/14)[досье]
Jared[досье]
Вот тут попытался описать алгоритм работы, есть скриншоты и простенький пример на JS, поясняющий,
что надо в конечном итоге, если этого не достаточно могу более подробно расписать.
http://trifler.ru/blog/post_1310563716.html
Также сказано о причинах почему нужно именно меню на php, а не на JavaScript.
спустя 1 день 11 часов [обр] Jared(3/26)[досье]
Попробуйте такой код:
//-------------------- Code ------------------------
foreach(array_keys($mainMenu) as $mmk)
{
   // Main menu item activeness flag
   $mmenu_active = false;

   // If we are on a main menu item targeted page
   if(basename($_SERVER['PHP_SELF']) === $mainMenu[$mmk]) $mmenu_item_active = true;
   $smenu_wrapped = '';


   if(array_key_exists($mmk,$subMenu))
   {
      foreach(array_keys($subMenu[$mmk]) as $smk)
      {
         // we are on a submenu item targeted page
         if(basename($_SERVER['PHP_SELF']) === $subMenu[$mmk][$smk])
         {
            $mmenu_active = true;
            // Generating submenu
            foreach(array_keys($subMenu[$mmk]) as $smkw)
            {
               $smenu_wrapped .= '<a href="'.$subMenu[$mmk][$smkw].'" class="subMenuLink'
                  .(basename($_SERVER['PHP_SELF']) === $subMenu[$mmk][$smkw] ? ' subMenuLinkActive' : '')
                  .'">'.$smkw.'</a>';
            }

            break 2;
         }
      }
   }

   // main menu item
   print '<a class="mainMenuLink'.( $mmenu_active ? ' mainMenuLinkSelected' : '').'" href="'.$mainMenu[$mmk].'">'.$mmk.'</a>';
   print $smenu_wrapped;

}
спустя 53 минуты [обр] Филипп Ткачев(20/112)[досье]
Полезно было бы вообще про деревья почитать http://phpclub.ru/faq/Tree?v=w5u
спустя 1 час 59 минут [обр] Jared(3/26)[досье]
Филипп Ткачев[досье], с деревьями все понятно. Я отталкиваюсь от структуры данных, данной автором.
спустя 8 часов [обр] Филипп Ткачев(20/112)[досье]
Jared[досье], ссылка скорее для автора, чем для вас.
Я бы использовал рекурсию для отрисовки дерева и его узлов. В данном подходе нет проблемы с глубиной дерева.
Плюс - вложенные штуки из тегов <ul>, <li>. Дизайнеры любят такие вещи.
спустя 14 часов [обр] Serg(0/14)[досье]

Jared[досье]
Нет не работает :(
Выводятся только заголовки разделов, клик по ним не приводит к появлению submenu.
В html-коде есть только ссылки разделов, полный листинг меню отсутствует.

Всем окликнувшимся спасибо.

Изначально html-код меню должен быть таким:

<ul class="menuphp">
  <li><a href="#">Раздел № 1 </a>
    <ul class="none">
      <li><a href="#">Пункт № 1.1 </a></li>
      <li><a href="#">Пункт № 1.2 </a></li>
    </ul>
  </li>
  <li><a href="#">Раздел № 2 </a>
    <ul class="none">
      <li><a href="#">Пункт № 2.1 </a></li>
      <li><a href="#">Пункт № 2.2 </a></li>
    </ul>
  </li>
</ul>

url'ы и прочие атрибуты проставляем руками.
Клик по любому заголовку должен привести к такому:

<ul class="menuphp">
  <li><a href="#">Раздел № 1 </a>
    <ul class="none">
      <li><a href="#">Пункт № 1.1 </a></li>
      <li><a href="#">Пункт № 1.2 </a></li>
    </ul>
  </li>
  <li><a class="selected" href="#">Раздел № 2 </a>
    <ul class="block">
      <li><a href="#">Пункт № 2.1 </a></li>
      <li><a href="#">Пункт № 2.2 </a></li>
    </ul>
  </li>
</ul>

В заголовок "Раздел № 2" подставляется класс "selekted" и класс "none" в этом разделе меняется на класс "block"
Два варианта развития:

  1. Клик на ссылку в открытом разделе
  1. Юзер решил открыть певый раздел

Состояние меню после клика на ссылку в открытом разделе:

<ul class="menuphp">
  <li><a href="#">Раздел № 1 </a>
    <ul class="none">
      <li><a href="#">Пункт № 1.1 </a></li>
      <li><a href="#">Пункт № 1.2 </a></li>
    </ul>
  </li>
  <li><a class="selected" href="#">Раздел № 2 </a>
    <ul class="block">
      <li><a href="#">Пункт № 2.1 </a></li>
      <li><a class="selected" href="#">Пункт № 2.2 </a></li>
    </ul>
  </li>
</ul>

В выбранную ссылку открытого раздела должен упасть класс "selekted" все остальное без изменений.

Если выбран "Раздел № 1", то состояние меню такое:

<ul class="menuphp">
  <li><a class="selected" href="#">Раздел № 1 </a>
    <ul class="block">
      <li><a href="#">Пункт № 1.1 </a></li>
      <li><a href="#">Пункт № 1.2 </a></li>
    </ul>
  </li>
  <li><a href="#">Раздел № 2 </a>
    <ul class="none">
      <li><a href="#">Пункт № 2.1 </a></li>
      <li><a href="#">Пункт № 2.2 </a></li>
    </ul>
  </li>
</ul>

При добавлении множества разделов все должно происходить по описаному алгоритму.

Скорее всего потребуется вводить опозновательные метки для корректной работы меню, а именно - открытие подменю по заголовку которого был совершен переход. Это все усложняет, но желательно, чтобы и скрипт и html-код меню были в одном файле.

Powered by POEM™ Engine Copyright © 2002-2005