Делаем navbar | Блог python программиста
Изображение гика

Блог питониста

Делаем navbar

5 ноября 2017 г.

Иногда нужно сделать navbar и переключать класс active на выбранной ссылке. Это можно сделать по-разному, расскажу об одном решении. Допустим у нас есть простое Flask - приложение:

 1from flask import Flask, render_template
 2app = Flask(__name__)
 3
 4
 5@app.route('/')
 6def main():
 7    return render_template('base.html')
 8
 9
10@app.route('/about')
11def about():
12    return render_template('base.html')

И base.html:

 1<!DOCTYPE html>
 2<html lang="en">
 3<head>
 4  <meta charset="UTF-8">
 5  <title>Document</title>
 6<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css" integrity="sha384-/Y6pD6FV/Vv2HJnA6t+vslU6fwYXjCFtcEpHbNJ0lyAFsXTsjBbfaDjzALeQsN6M" crossorigin="anonymous">
 7<link rel="stylesheet" href="{{ url_for('static',filename='css/mysite.css') }}">
 8</head>
 9<body>
10
11  <nav class="nav">
12    <a class="nav-link" href="/">Блог</a>
13    <a class="nav-link" href="/about">Об авторе</a>
14  </nav>
15
16  <script
17    src="https://code.jquery.com/jquery-3.2.1.slim.min.js"
18    integrity="sha256-k2WSCIexGzOj3Euiig+TlR8gA0EmPjuc79OEeY5L45g="
19    crossorigin="anonymous"></script>
20  <script src="{{ url_for('static',filename='js/mysite.js') }}"></script>
21</body>
22</html>

mysite.css:

1.active {
2    background-color: grey;
3}

И хочется добавлять класс active при клике на каждую ссылку в navbar'e. Можно использовать передачу переменных в шаблон:

1@app.route('/')
2def main():
3    return render_template('base.html', tab="")
4
5
6@app.route('/about')
7def about():
8    return render_template('base.html', tab="about")
1<nav class="nav">
2  <a class="nav-link {% if tab == "" %}active{% endif %}" href="/">Блог</a>
3  <a class="nav-link {% if tab == "about" %}active{% endif %}" href="/about">Об авторе</a>
4</nav>

Но можно ведь использовать js, сначала хочется сделать что-то вроде (mysite.js):

1var selector = '.nav-link';
2$(selector).on('click', function(){
3    $(selector).removeClass('active');
4    $(this).addClass('active');
5});

Но это не будет работать, потому что после переключения класса страница обновится, и класс исчезнет со ссылки. Можно сделать по-другому:

1<nav class="nav">
2  <a class="nav-link" href="/">Блог</a>
3  <a class="nav-link" href="/about">Об авторе</a>
4</nav>
 1$(document).ready(function() {
 2    const regex = /http:\/\/.*\/(.*)/g;
 3    const match = regex.exec(window.location.href);
 4    // iterate over all and find match
 5    if (match) {
 6        $(".nav-link").each(function() {
 7            if ($(this).attr("href").slice(1) == match[1]) {
 8                $(this).addClass("active");
 9            }
10        });
11    }
12    // set active first element
13    else {
14        $(".nav-link:first").addClass("active");
15    }
16});

Тоесть используя  window.location.href получаем текущий адрес, регулярным выражением пытаемся получить правую часть адреса, если не получается, то ставим active на первую ссылку, в другом случае находим соответствующую ссылку и ставим класс ей.

Говорят, что если у тебя есть проблема, и ты ее решаешь с помощью регулярных выражений, то у тебя две проблемы. Пожалуй, лучше переписать этот код, не используя регулярки:

 1$(document).ready(function() {
 2    const href = window.location.href.split('/');
 3    const last = href[href.length - 1];
 4    // iterate over all and find match
 5    if (last) {
 6	    $(".nav-link").each(function() {
 7	        if ($(this).attr("href").slice(1) == last) {
 8	            $(this).addClass("active");
 9	        }
10	    });
11    }
12    // set active first element
13    else {
14        $(".nav-link:first").addClass("active");
15    }
16});

Есть разные способы решить данную проблему, я описал некоторые из них, надеюсь для кого-то это было полезно.

Метки

js
Если вам понравился пост, можете поделиться им в соцсетях: