Как реализовать навигацию по «выбранному» пункту - PullRequest
1 голос
/ 08 декабря 2011

Мне нужно реализовать меню навигации на веб-странице, возможно, с несколькими уровнями вкладок. Я использовал способ CSS всякий раз, когда CSS находится под моим контролем, но теперь я сталкиваюсь с проблемами при использовании существующей библиотеки CSS (в данном случае Bootstrap Twitter).

Во-первых, это способ CSS, который я использовал. Пример HTML:

<html>
<head>
    <title>Example page</title>
</head>
<body class="articles">

<div class="navigation">
    <ul>
        <li class="frontpage"><a href="#">Frontpage</a></li>
        <li class="articles"><a href="#">Articles</a></li>
    </ul>
</div>

<p>Blah blah.</p>

</body>
</html>

... и CSS:

body.frontpage div.navigation li.frontpage,
body.articles div.navigation li.articles {
    background-color:red;
    color:white;
}

Достаточно просто. Нужно было изменить только класс тела, когда ученик.

Теперь Bootstrap, похоже, использует стиль на основе классов для выбора элементов навигации (верхняя панель, вкладки, таблетки). Пример:

...
<div class="navigation">
    <ul class="tabs">
        <li class="active"><a href="#">Frontpage</a></li>
        <li><a href="#">Articles</a></li>
    </ul>
</div>
...

Сначала я думал о том, чтобы сделать что-то вроде

navigation = ('frontpage',)
# or
navigation = ('articles', 'categories', 'foo',)

в контроллере, а затем передать этот кортеж шаблонам, но каким-то образом у него есть атмосфера "делать это неправильно".

Итак, вопрос в том, что, поскольку мне действительно нужно распечатать выбор класса в шаблонах, как мне отслеживать текущее местоположение (например, где в дереве навигации находится эта страница), учитывая, что страница может иметь несколько уровней вкладок или других элементов навигации? Есть ли предпочтительный способ сделать это?

Я использую Pyramid в стиле маршрута с шаблонами Mako, но также приветствуются общие ответы.

Ответы [ 2 ]

3 голосов
/ 18 декабря 2011

Я делаю нечто подобное (также Pyramid & Bootstrap), но только для одного уровня навигации.

Первым делом я создал объект «представление», который передает параметры каждому рендеру, например, заголовок, заголовок, get_data и т. Д. Например.

class View_Controller(object):
    def __init__(self, request, **kwargs):
        self.request = request
        self.nav = kwargs.get('nav', None)

    @property
    def page(self):
        return request.GET.get('page', 1)

@view_config(route_name='home', renderer='templates/homepage.mako')
def Homepage_View(request):
    view = View_Controller(request, nav='homepage')
    stuff = DBSession.query(Stuff).all()
    return {'view': view, 'stuff': stuff}

Я установил атрибут nav вкаждая страница рендеринга, но есть nav = None, когда никакой элемент навигации не активирован.Затем я создал шаблон для элементов навигации в Мако:

<%def name="navelements(things)">
% for a in things:
<li${' class="active"' if nav == a[1] else '' | n }><a href="#">a[0]</a></li>
% endfor
</%def>

Где «вещи» - это кортеж всех элементов в навигации.[0] - это отображаемое имя, а [1] - внутреннее имя.«| N» необходим для экранирования символов html.Пример:

<%! things = [['Frontpage', 'homepage'], ['Articles', 'arts'], ['Categories', 'cats'], ['Foo', 'foo']] %>

% if things:
<div class="navigation">
  <ul class="tabs">
    ${navelements(things)}
  </ul>
</div>
% else:
<hr />
% endif

Теперь вы можете устанавливать параметры либо в шаблоне, либо в контроллере через представление.У меня есть предложение «если что-то», если вам нужен универсальный шаблон вкладки, который вызывается на каждой странице;Вы можете отключить вкладки, просто установив вещи = Нет в контроллере.

Это только один уровень вкладок, но вы можете сделать то же самое, сделав список более сложным.Я бы все усложнил, чтобы по сравнению с тем, как он выглядит в настоящее время, это выглядело бы так:

things = [['displayname1', 'elementname1', things1], ['displayname2', 'elementname2', things2], ...]

Затем я бы сделал рекурсивные navelements (которые Мако не поддерживает, поэтому я просто сделал быдве копии функции navelements и позволяют им вызывать друг друга) и реализовать поддержку нескольких уровней nav:

<%def name="navelements1(things, level=0)">
% for a in things:
<li${' class="active"' if nav[level] == a[1] else '' | n }><a href="#">a[0]</a></li>
   % if a[2]:
     <ul class="tabs">
       ${navelements2(a[2], level+=1)}
     </ul>
   % endif
% endfor
</%def>

Где nav выглядит примерно так:

nav = ['frontpage', 'best', None, ...]

Надеюсь, что ответит на вашвопрос.Просто убедитесь, что ваши списки имеют правильную длину, чтобы избежать ошибок.

0 голосов
/ 30 сентября 2015

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

Затем измените активную ссылку на (пример в jinja2, но она должна быть похожей)

<li {% if view.__name__ == "fixtures" %} class="active" {% endif %}>
  <a href="#">Link</a>
</li>

Больше информации на http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/templates.html#system-values-used-during-rendering

...