jQuery: поиск ссылки, наилучшим образом соответствующей текущему URL

#jquery #url-routing

#jquery #url-маршрутизация

Вопрос:

У меня есть следующий код, который пытается добавить класс selected к ссылке, соответствующей URL:

 var pathname = window.location.pathname;

$(document).ready(function ()
{
    $('ul#ui-ajax-tabs li a').each(function()
    {
        if (pathname.indexOf($(this).attr('href')) == 0)
        {
            $(this).parents('li').addClass('selected');
        }
    });
});
  

1.) Так, например, если у меня есть URL /Organisations/Journal -адрес, и /Organisations/Journal/Edit ссылка с организациями и журналом будет отображаться как выбранная. Это нормально!

2.) Однако иногда у меня есть URL-адреса типа: /Organisations и /Organisations/Archived и если у меня есть ссылка на архив, то будут выбраны оба, НО я не хочу, чтобы это произошло, потому что организации, подобные, не имеют второй части URL, поэтому не должны совпадать.

Может ли кто-нибудь помочь заставить это работать для вторых типов, не нарушая первый тип? Также ничто из этого не может быть жестко запрограммированным регулярным выражением для поиска ключевых слов, поскольку URL-адреса имеют множество разных параметров!

Приветствия

ПРИМЕРЫ:

Если URL- /Organisations/ адрес Или /Organisations , то /Organisations должна быть выбрана ссылка с. Если URL-адрес является /Organisations/Journal/New ссылкой с /Organisations/Journal или /Organisations/Journal/New будет выбран.

НО если у меня есть URL с /Organisations/Recent и есть две ссылки: /Organisations и /Organisations/Recent тогда должна быть выбрана только вторая! Итак, здесь следует отметить, что у него должен быть третий параметр, прежде чем он будет искать биты URL более свободно, а не точное совпадение.

Помните, что это не всегда могут быть организации, поэтому они не могут быть жестко запрограммированы в JS!

Комментарии:

1. Не могли бы вы подробнее остановиться на своих примерах? Возможно, даже предоставить jsFiddle с двумя случаями?

2. Хорошо, я правильно понял … Вы хотите, чтобы наилучшее совпадение было выделено как текущее?

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

4. Это ограничение по времени, прежде чем я смогу принять ответ, и у меня не всегда есть время проверить, когда оно истекло, а иногда я не всегда получаю ответ, который хочу! 😉

Ответ №1:

Редактировать: мое предыдущее решение было довольно сложным. Обновленный ответ и скрипка.

 var pathname = window.location.pathname;

$(document).ready(function ()
{
    var best_distance = 999; // var to hold best distance so far
    var best_match = false;  // var to hold best match object

    $('ul#ui-ajax-tabs li a').each(function()
    {
        if (pathname.indexOf($(this).attr('href')) == 0)
        {
            // we know that the link is part of our path name.
            // the next line calculates how many characters the path name is longer than our link
            overlap_penalty = pathname.replace($(this).attr('href'), '').length;
            if (overlap_penalty < best_distance) { // if we found a link that has less difference in length that all previous ones ...
                best_distance = overlap_penalty; // remember the length difference
                best_match = this; // remember the link
            }
        }
    });

    if (best_match !== false)
    {
        $(best_match).closest('li').addClass('selected');
    }
});
  

Наилучшее совпадение вычисляется следующим образом:

Предположим, что наш путь — «/foo/bar/baz /x». У нас есть две ссылки, о которых идет речь:

  • /foo/bar/
  • /foo/bar/baz

Вот что происходит:

  1. /foo/bar/baz /x (URL-адрес первой ссылки удаляется из имени пути pathname.replace($(this).attr('href'), '') )
  2. «baz / x» — это то, что остается.
  3. Количество символов ( length ) этого остатка равно 5. это наш «штраф» за ссылку.
  4. Мы сравниваем 5 с нашим предыдущим лучшим расстоянием ( if (overlap_penalty < best_distance) ). 5 меньше (= лучше), чем 999.
  5. Мы сохраняем this (будучи объектом <a href="/foo/bar/"> DOM) для возможного последующего использования.
  6. Вторая ссылка обрабатывается таким же образом:
  7. /foo/bar/baz/x (URL-адрес второй ссылки удаляется из имени пути)
  8. «/ x» — это то, что остается.
  9. Количество символов в этом остатке равно 2.
  10. Мы сравниваем 2 с нашим предыдущим лучшим расстоянием (равным 5). 2 меньше 5.
  11. Мы сохраняем this (будучи объектом <a href="/foo/bar/baz"> DOM) для возможного последующего использования.

В конце мы просто проверяем, нашли ли мы какую-либо подходящую ссылку, и, если да, применяем addClass('selected') к ее ближайшему <li> родителю.

Комментарии:

1. Святая корова, это какой-то сложный код: P, хотя, похоже, выполняет свою работу. Есть ли шанс, что вы могли бы объяснить, что он делает в каждой строке? Хотелось бы узнать больше. Приветствия.

2. Обновлен ответ. Получайте удовольствие!

Ответ №2:

Почему вы не используете

 if($(this).attr('href') == pathname )
  

вместо

 if (pathname.indexOf($(this).attr('href')) == 0)
  

Комментарии:

1. Потому что это будет искать точные совпадения!

Ответ №3:

 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title></title>
    <script src="Scripts/jquery-1.7.1.min.js" type="text/javascript"></script>
    <script type="text/javascript">
        $(document).ready(function () {
            var windowLocationPathname = "/HTMLPage14.htm";  // For testing purpose.

            //Or

            //var windowLocationPathname = window.location.pathname;

            $('ul.ui-ajax-tab').find('a[href^="'   windowLocationPathname   '"]').addClass('currentPage');
        });
    </script>
    <style type="text/css">
        .ui-ajax-tab
        {
            list-style: none;
        }

        a.currentPage
        {
            color: Red;
            background-color: Yellow;
        }
    </style>
</head>
<body>
    <ul class="ui-ajax-tab">
        <li><a href="/HTMLPage14.htm">Test 1 (/HTMLPage14.htm)</a></li>
        <li><a href="/HTMLPage15.htm">Test 2 (/HTMLPage15.htm)</a></li>
        <li><a href="/HTMLPage16.htm">Test 3 (/HTMLPage16.htm)</a></li>
        <li><a href="/HTMLPage17.htm">Test 4 (/HTMLPage17.htm)</a></li>        
    </ul>
</body>
</html>
  

Комментарии:

1. Это будет соответствовать ТОЧНЫМ совпадениям… Это не то, чего я хотел.