Изменение активного класса ссылки с помощью twitter bootstrap css в python/flask
Я получил следующий html-фрагмент с моей страницы template.html
.
<ul class='nav'>
<li class="active"><a href='/'>Home</a></li>
<li><a href='/lorem'>Lorem</a></li>
{% if session['logged_in'] %}
<li><a href="/account">Account</a></li>
<li><a href="/projects">Projects</a>
<li><a href="/logout">Logout</a></li>
{% endif %}
{% if not session['logged_in'] %}
<li><a href="/login">Login</a></li>
<li><a href="/register">Register</a></li>
{% endif %}
</ul>
Как вы можете видеть в строке 2, класс активен. Это подчеркивает активную вкладку с помощью CSS файла twitter bootstrap. Теперь это будет нормально работать, если я посетил бы www.page.com/
, но не тогда, когда я бы посетил www.page.com/login
, например. Он по-прежнему выделял бы домашнюю ссылку как активную вкладку.
Конечно, я мог бы легко сделать это с помощью Javascript/jQuery, но я бы предпочел не использовать это в этой ситуации.
Там уже работает решение для ruby on rails, но я не знаю, как преобразовать его в python/jinja (я довольно новичок в jinja/flask, никогда не работал с рубином вообще)
Ответы
Ответ 1
Вы смотрели на это? http://jinja.pocoo.org/docs/tricks/
Выделение активных пунктов меню
Часто вы хотите иметь панель навигации с активным элементом навигации. Это действительно просто достичь. Поскольку назначения вне блоков в дочерних шаблонах являются глобальными и выполняются до оценки шаблона макета, можно определить активный элемент меню в дочернем шаблоне:
{% extends "layout.html" %}
{% set active_page = "index" %}
Затем шаблон макета может получить доступ к active_page
. Кроме того, имеет смысл определить значение по умолчанию для этой переменной:
{% set navigation_bar = [
('/', 'index', 'Index'),
('/downloads/', 'downloads', 'Downloads'),
('/about/', 'about', 'About')
] -%}
{% set active_page = active_page|default('index') -%}
...
<ul id="navigation">
{% for href, id, caption in navigation_bar %}
<li{% if id == active_page %} class="active"{% endif
%}><a href="{{ href|e }}">{{ caption|e }}</a>
</li>
{% endfor %}
</ul>
Ответ 2
Вот еще один простой способ, если у вас есть меню, распространяемые по всей странице. Этот способ использует встроенные операторы if для печати класса active.
<ul>
<li class="{{ 'active' if active_page == 'menu1' else '' }}">
<a href="/blah1">Link 1</a>
</li>
<li class="{{ 'active' if active_page == 'menu2' else '' }}">
<a href="/blah2"> Link 2 </a>
</li>
</ul>
Класс активен для выделения
Вам все равно нужно установить переменную на каждой странице, чтобы пометить ее
{% extends "master.html" %}
{% set active_page = "menu1" %}
или
{% set active_page = "menu2" %}
Ответ 3
Для пользователей jinja/flask/bootstrap:
Если вы определяете свой nav, как в блоге, http://getbootstrap.com/examples/blog/
просто назначьте идентификаторы вашим ссылкам, которые соответствуют вашим аргументам url_for, и вам просто нужно изменить шаблон макета, остальные просто работают #magic.
<nav class="blog-nav">
<a id="allposts" class="blog-nav-item" href="{{ url_for('allposts')}}">All Posts</a>
<a id="index" class="blog-nav-item" href="{{ url_for('index')}}">Index</a>
<a id="favorites" class="blog-nav-item" href="{{ url_for('favorites')}}">Favorites</a>
</nav>
В нижней части шаблона base/layout просто добавьте этот
<script>
$(document).ready(function () {
$("#{{request.endpoint}}").addClass("active"); })
</script>
и нужные элементы будут активны.
РЕДАКТИРОВАТЬ:
Если у вас есть макет с элементами в списке, например:
<nav class="blog-nav">
<ul class="nav navbar-nav">
<li>
<a id="allposts" class="blog-nav-item" href="{{ url_for('allposts')}}">All Posts</a>
</li>
<li>
<a id="index" class="blog-nav-item" href="{{ url_for('index')}}">Index</a>
</li>
<li>
<a id="favorites" class="blog-nav-item" href="{{ url_for('favorites')}}">Favorites</a>
</li>
</ul>
</nav>
используйте функцию parent(), чтобы получить элемент li вместо ссылки.
<script>
$(document).ready(function () {
$("#{{request.endpoint}}").parent().addClass("active"); })
</script>
Ответ 4
Добавьте следующий CSS где-нибудь на своей странице:
a[href $= {{ page_name|default("'/'"|safe) }}]{ [INSERT YOUR ACTIVE STYLING HERE] }
Теперь для каждого шаблона определите page_name
, например:
{% extends "template.html" %} {% set page_name = "gallery" %}
Это кажется намного проще и проще, чем другие варианты.
РЕДАКТИРОВАТЬ:
Почти год спустя я возвращаюсь, чтобы исправить это намного проще, потому что установка имени страницы на каждой странице довольно неэффективна.
Вместо этого создайте такую функцию:
@app.context_processor
def context_processor():
out = {}
out['request'] = request # Make sure you import request from flask
return out
Это позволит вам неявно передавать переменные в jinja, в этом случае мы передаем запрос на доступ к request.url_rule
который содержит маршрут, к которому обращается пользователь. В предыдущей версии мы просто изменили {{ page_name|default("'/'"|safe) }}
на "{{ request.url_rule|safe }}"
. Гораздо чище.
Ответ 5
Мне понравился подход @philmaweb, но на самом деле нет причин требовать дублирования конечной точки в id каждого элемента.
base.js:
$(document).ready(function () {
var scriptElement = $('#baseScript')[0];
var path = scriptElement.getAttribute('data-path');
$('a[href="'+path+'"]').addClass("active");
});
base.html
<script id="baseScript" src="{{ url_for('static', filename='js/base.js') }}"
data-path="{{ request.path }}"></script>
Почему бы просто не вставить этот скрипт в строку? Конечно, можно, но использование встроенного JS - это кошмар безопасности. Вы должны использовать CSP на своем сайте (например, Flask-Talisman), который не позволяет использовать встроенный JS. С data-*
не сложно сделать это безопасным способом.
NB. Если у вас есть несколько ссылок, ведущих на одну и ту же текущую страницу, и вы хотите, чтобы только ОДНА из них была помечена как "активная", то этот подход может не сработать для вас.