Что может привести к тому, что html и script будут отличаться от разных итераций цикла for?

Я пытаюсь создать боковую навигационную панель, где указаны категории, и при нажатии на категорию соответствующий подкатегорий подкатегорий показан прямо под категорией. И если категория нажата снова, подписок списывается.

Итак, я запускаю цикл через объекты категории. Внутри этого внешнего цикла я включаю внутренний цикл для перечисления подкатегорий и script, который скрывает подменю и slidetoggles его только при нажатии на категорию. Я использую теги шаблона django, чтобы динамически назначать имена классов для моих элементов html, а также ссылаться на них в script. Итак, в конце концов для итераций цикла есть список подкатегорий и выделенный script для каждой категории, и у них есть уникальные имена классов, поэтому нет возможности перекрытия. Итак, странная часть, это отлично работает для большинства категорий, но некоторые категории и их подменю остаются открытыми и при нажатии на категорию перезагружается страница.

Я не понимаю, что может привести к тому, что тот же самый код (запущенный в цикле for) будет вести себя по-другому?

Это мой код:

{% load staticfiles %}
{% load i18n pybb_tags forumindexlistbycat %}
{% catindexlist as catindexlisted %}

{% block body %}<div class="col-sm-12 col-md-12 col-xs-12 col-lg-12 body-container leftsidenavigator" style="margin-top:15px;">
    <div class="col-sm-12 col-md-12 col-xs-12 col-lg-12 leftsidenavigator-inner" style="padding:0px;">
         <h2><center>Categories</center></h2>
             <ul class="catindexlist catlistcat nav-collapse89">
                   {% for category in catindexlisted %}
                         <li class="catindexlistitem category-name{{category.name}}{{category.name}}" style="font-weight:600;padding-right:20px;"><a href="">{{category.name}}</a></li>
                         <ul style="padding:0px;" class="nav-collapse88">
                         {% for forum in category|forumindexlistbycat %}
                               <li class="catlistforum{{category.name}}{{category.name}} forum-name" style="padding-right:10px;"><a href="{{ forum.get_absolute_url }}">{{forum.name}}</a></li>
                         {% endfor %}</ul><script>

                         $(function() {
                              $(".catlistforum{{category.name}}{{category.name}}").hide();
                                    $(".category-name{{category.name}}{{category.name}} a").click(function(e) {
                                     e.preventDefault();
                                     $(".catlistforum{{category.name}}{{category.name}}").slideToggle();
                                          if(!($(this).parent('li').siblings('div').children('ul').children('div').is(":visible"))){
                                              $(this).parent('li').siblings('div').children('ul').children('div').is(":visible").slideToggle();
                                          }});
                                      })
                                </script>
                           {% endfor %}
                           </ul>
                      </div>
                      </div>
                  {% endblock %}
     {% block theme_script %}<script src="{% static "pinax/js/theme.js" %}"></script>{% endblock %}

Ответ 1

Наиболее вероятной причиной является использование {{category.name}} для имен классов.

Фрагмент кода не показывает, какие значения принимаются для category.name, и я предполагаю, что он может быть введен пользователем? См. правила именования в разделе Атрибут Значения, действительные для имен классов.

Его можно решить, используя шаблонный тег slugify ({{category.name | slugify}}), но моя рекомендация - попробовать повторно -разложите решение немного.

Ответ 2

Есть ли вероятность, что имя категории содержит пробелы?

Просто подсказка: вы не используете хорошую практику в своем коде. ИМО вы должны получить свой javascript-код за пределами forloop и удалить классы {{ category_name }}. catindexlistitem при щелчке следует переключать скрытый класс (я заметил, что вы используете bootstrap) к нему дочерняя ul.

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

Ответ 3

Попробуйте написать функцию javascript после внешнего цикла, иногда это может перекрываться и перенаправляться. А также попробуйте указать пробелы между именами категорий внутри "li".

Ответ 4

Мой совет - очистить JS, сделав одну функцию для обработки всех кликов. Вы уже используете класс по щелчкам, поэтому почему бы не одна функция обрабатывать все клики?

<script>
  $(function() {
    // Hide all elements with a class starting with catlistforum
    $('[class^="catlistforum"]').hide();

    // Assign clicks to all links whose parent has a class starting with catlistforum
    // (Though why are you hiding the parents? How will they click the links?)
    $('[class^="catlistforum"] a').on("click", function(e) {
      e.preventDefault();

      // Delegate slideToggle to each click target
      $(e.target).slideToggle();

      // This seems redundant, but hopefully it will behave the way you want it to behave
      if(!($(e.target).parent('li').siblings('div').children('ul').children('div').is(":visible"))) {
        $(e.target).parent('li').siblings('div').children('ul').children('div').is(":visible").slideToggle();
      }
    });
  })
</script>

Конечно, если бы я был вами, я бы просто определил два новых класса (например, catlistforum-hide и catlistforum-toggle), которые я бы применил ко всем элементам, которые я хотел скрыть и переключить соответственно.