Инструменты пользователя

Инструменты сайта


limb2:ru:howtos:nested_navigations

Создание и вывод вложенных навигаций

Проблема

Во фронтальной части требуется отобразить под-меню, которая состоит из дочерних элементов текущего элемента навигации. Допустим у нас есть навигация, называемая «continents» (путь /root/navigation/continents). В этой навигации мы выводим ссылки на определенные объекты-документы (/root/continents). В навигации «continents» есть дочерние элементы, для каждого континета (/root/navigation/continents/europe, /root/navigation/continents/america), а внутри них элементы для отдельных стран (/root/navigation/continents/europe/germany, /root/navigation/continents/europe/italy). Объекты, которые содержат данные по каждой стране, хранятся совсем в другой папке, нежели /root/continents, например /root/countries.

Мы щелкаем на элемент навигации «continents», например europe, и требуется, что бы кроме контента текущей страницы (например, это объект-документ), вывелись бы ссылки на определенные элементы навигации, например, «Spain», «Italy», «Germany» со ссылками на совершенно другие документы.

Тема обсуждалась на англоязычной ветке форума: http://limb-project.com/forum/viewtopic.php?t=75

Вариант : таких объектов мало и максимальный уровень вложенности - 2

Все зависит от того, как объекты организованы в дереве сайта и как много уровней навигации требуется отобразить. Допустим, что есть только 2 уровня объектов, таких объектов немного, а объекты навигации имеют те же самые идентификаторы, что и документы или другие объекты, которые навигация представляет. В этом случае мы можем создать специальный datasource, который будет загружать навигационный элемент, относящийся к текущему объекту, а затем дочерние навигационные элементы и возвращать именно их.

Код будет выглядеть приблизительно так:

class second_level_navigation_datasource extends datasource()
{
  function & get_dataset()
  {
    $requested_object_data = fetch_requested_object();
    $parent_navigation_item = fetch_one_by_path('/root/navigation/main/' . $requested_object_data['identifier']);
   
    if (!$parent_navigation_item)
      return new empty_dataset();
     
    $counter = 0; 
    $items = fetch_sub_branch($parent_navigation_item['path'], 'navigation_item', $counter);
   
    if (!$items)
      return new empty_dataset();
   
    return new array_dataset($items);
  } 
} 

Вариант: уровней вложенности слишком много

Пусть у нас есть ссылка вида /root/continents/europe. И нам необходимо вывести 2-же не одну навигацию, а две: по континентам и по странам европы. В этом случае больше пользы будет от рекурсивной загрузки элементов навигации. Ниже показан пример datasource класса, который грузит элементы навигации рекурсивно, начиная от определенного уровня, указанного в шаблоне, а далее до тех пор пока элементы пути текущего запроса находятся в дочерних элементах навигации (обратите внимание на строчку is_integer($res = $uri→compare_path($nav_uri))).

require_once(LIMB_DIR . '/core/datasource/fetch_sub_branch_datasource.class.php');
 
class special_navigation_datasource extends fetch_sub_branch_datasource
{
  function & _fetch(&$counter, $params)
  {
    $result =& parent :: _fetch($counter, $params);
    $uri = new uri($_SERVER['PHP_SELF']);   
 
    foreach($result as $key => $data)
    {
      $nav_uri = new uri($data['url']);
 
      if ($uri->get_host() != $nav_uri->get_host())
        continue;
 
      if(is_integer($res = $uri->compare_path($nav_uri)))
      {
        if($res >= 0)
        {
          $result[$key]['in_path'] = true;
          $params['path'] = $data['path'];
          $result[$key]['items'] = $this->_fetch(&$counter, $params);
        } 
        if($res == 0)
          $result[$key]['selected'] = true;
      }
    }
    return $result;
  }
 
}

Теперь код шаблона:

<fetch:SUB_BRANCH target="menu" >
  <core:PARAMETER name='loader_class_name' value='navigation_item' >
  <core:PARAMETER name='datasource_path' value='special_navigation_datasource' >
  <core:PARAMETER name='path' value='/root/navigation/continents' >
  <core:PARAMETER name='order' value='priority=ASC'>
</fetch:SUB_BRANCH>
 
<grid:LIST id='menu'>
<table width=140 border=0 cellspacing=3 cellpadding=0 class=menu>
<grid:ITERATOR>
  <core:OPTIONAL for='selected'>
  <tr>
    <td class="active"><a href='{$url}'>{$title}</a></td>
  </tr>
  </core:OPTIONAL>
  <core:DEFAULT for='selected'>
  <tr>
    <td><a href='{$url}'>{$title}</a></td>
  </tr>
  </core:DEFAULT>
 
  <core:OPTIONAL for='items'>
   <core:DATA_TRANSFER hash_id='items' target='second_menu'>
  </core:OPTIONAL>
</grid:ITERATOR>
</table>
</grid:LIST>
 
 
<grid:LIST id='second_menu'>
<table width=140 border=0 cellspacing=3 cellpadding=0 class=menu>
  <grid:ITERATOR>
    <core:OPTIONAL for='selected'>
    <tr>
      <td class="active"><a href='{$url}'>{$title}</a></td>
    </tr>
    </core:OPTIONAL>
    <core:DEFAULT for='selected'>
    <tr>
      <td><a href='{$url}'>{$title}</a></td>
    </tr>
    </core:DEFAULT>
  </grid:ITERATOR>
 </table>
</grid:LIST>

Замечания

Проблемой может быть сихронизация идентификаторов элементов навигации и объектов, которые эти элементы навигации представляют. К сожалению, в Limb2 нет встроенных средств для того, чтобы делать это автоматически, поэтому реализацию придется делать руками или просто следовать четкому правилу - элемент навигации должен иметь тот же идентификатор, что и объект, который он представляет.

Обсуждение

Ваш комментарий. Вики-синтаксис разрешён:
   ___    ___    _  __ ______  _      __
  / _ \  / _ )  | |/_//_  __/ | | /| / /
 / , _/ / _  | _>  <   / /    | |/ |/ / 
/_/|_| /____/ /_/|_|  /_/     |__/|__/
 
limb2/ru/howtos/nested_navigations.txt · Последние изменения: 2010/11/10 10:02 (внешнее изменение)