Почему jQuery не переключает этот div?

У меня есть набор div, которые представляют категории историй. В каждой категории есть блок div, содержащий заголовок категории, и блок div, содержащий краткое изложение историй.

Я начинаю со всех скрытых блоков историй, кроме категории, которая содержит историю по умолчанию; его раздел историй начинается видимым (ниже cat2):

[ cat1   < ]
[ cat2   V ]
  - story2-1
  - story2-2
[ cat3   < ]

Когда я нажимаю на любой из других заголовков категорий, я удаляю «расширенный» класс, который устанавливает значок треугольника вниз во всех разделах заголовка категории, скрываю все разделы истории, а затем переключаю «расширенный» класс на заголовке категории, по которому щелкнули. , и, наконец, переключите блок историй, который является братом заголовка категории, по которому щелкнули.

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

ПРОБЛЕМА: если я нажму на развернутую в данный момент заголовок категории, чтобы свернуть ее, так что они будут свернуты ВСЕ, ничего не произойдет. Или, более конкретно, когда я регистрирую результаты, я вижу, что элемент истории получает свойство «отображать», установленное на «блокировать», а затем сразу же снова на «нет». Почему???

Код

<html>
<head>
<style type="text/css">
    .category        { width: 200px; }
    .category-hed    { cursor: pointer; }
    .category-hed h2 {
        background-image: url( /_img/b/category-hed-arrow-collapsed.gif );
        background-repeat: no-repeat;
        background-position: center right;
    }
    .category-hed h2.expanded    {
        background-image: url( /_img/b/category-hed-arrow-expanded.gif );
    }
    .category .stories  {   /* default hidden; clicking category-hed will toggle it */
        display: none;
    }
</style>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<script type="text/javascript">
    $(function () {
        // set click handlers on the category section headers to expand/collapse the sections
        $(".category-hed").click( function() {
            $(".category-hed h2").removeClass("expanded");      // unset the 'expanded' indicators in all categories
            $(".stories").hide();                               // hide the "stories" divs in all categories

            // TODO: this doesn't collapse an already-expanded section... why?
            $("h2", this).toggleClass("expanded");  // 2nd arg to $() sets context of the selection: h2 under this
            $(this).siblings(".stories").toggle();  // show this category's "stories" div
        });
        // the default story's category section should initially be expanded
        var defaultStoryCatID = "#category-2";
        $( "h2", defaultStoryCatID ).toggleClass("expanded");
        $( ".stories", defaultStoryCatID ).show();
    });
</script>

</head>
<body>
    <div class="category" id="category-1">
        <!-- nested H2 below to aid border styling; CSS omitted -->
        <div class="category-hed"><h2>Category 1</h2></div>
        <div class="stories">
            <div class="story">
                <h3>cat 1 story1 head</h3>
                <p>... the story...</p>
            </div>
            <div class="story">
                <h3>cat 1 story2 head</h3>
                <p>... another story...</p>
            </div>
        </div>
    </div>
    <div class="category" id="category-2">
        <div class="category-hed"><h2>Category 2</h2></div>
        <div class="stories">
            <div class="story">
                <h3>cat 2 story1 head</h3>
                <p>... the story...</p>
            </div>
            <div class="story">
                <h3>cat 2 story2 head</h3>
                <p>... another story...</p>
            </div>
        </div>
    </div>
    <div class="category" id="category-3">
        <div class="category-hed"><h2>Category 3</h2></div>
        <div class="stories">
            <div class="story">
                <h3>cat 3 story1 head</h3>
                <p>... the story...</p>
            </div>
            <div class="story">
                <h3>cat 3 story2 head</h3>
                <p>... another story...</p>
            </div>
        </div>
    </div>
</body>
</html>

person Val    schedule 09.12.2010    source источник


Ответы (2)


Во-первых, ваш код искажен. Например,

<div class="category" id="category-3">
    <div class="category-hed"><h2>Category 3</h2></div>
        <div class="stories">
            <div class="story">
                <h3>cat 3 story1 head</h3>
                <p>... the story...</p>
            </div>
            <div class="story">
                <h3>cat 3 story2 head</h3>
                <p>... another story...</p>
            </div>
        </div>
    </div>
</div>

содержит слишком много тегов /div. Это должно выглядеть так...

<div class="category" id="category-3">
    <div class="category-hed"><h2>Category 3</h2></div>
    <div class="stories">
        <div class="story">
            <h3>cat 3 story1 head</h3>
            <p>... the story...</p>
        </div>
        <div class="story">
            <h3>cat 3 story2 head</h3>
            <p>... another story...</p>
         </div>
    </div>
</div>

Я немного переупорядочил функцию щелчка...

    $(".category-hed").click( function() {
        // TODO: this doesn't collapse an already-expanded section... why?
        $("h2", this).toggleClass("expanded");  // 2nd arg to $() sets context of the selection: h2 under this
        $(this).siblings(".stories").toggle();  // show this category's "stories" div

        $(".category-hed").not(this).find("h2").removeClass("expanded");      // unset the 'expanded' indicators in all categories
        $(".category-hed").not(this).siblings(".stories").hide();             // hide the "stories" divs in all categories
    });

Попробуйте это и дайте мне знать, как это работает!

person mikesir87    schedule 09.12.2010
comment
Дох, дополнительные разделы были ошибкой очистки кода - я должен был это увидеть, потому что раздел историй является родным братом раздела категории, а не дочерним элементом. Фиксированный. Ваша переупорядоченная функция щелчка работает отлично - спасибо!!! - person Val; 09.12.2010

Если я правильно понимаю ваш вопрос, это потому, что когда вы нажимаете на уже развернутый category-hed, он сначала «сворачивается» (путем удаления класса expanded), затем сразу же повторно добавляется класс expanded .toggleClass(). В вашем коде всегда будет что-то, что в конечном итоге будет расширено, потому что предыдущее состояние не учитывается. Что-то настолько простое, как это, должно решить проблему:

$(".category-hed").click( function() {
            if($(this).hasClass("expanded")
               var dont_reexpand = true;
            $(".category-hed h2").removeClass("expanded");      // unset the 'expanded' indicators in all categories
            $(".stories").hide();                               // hide the "stories" divs in all categories
            if(!dont_reexpand) {
                // TODO: this doesn't collapse an already-expanded section... why?
                $("h2", this).toggleClass("expanded");  // 2nd arg to $() sets context of the selection: h2 under this
                $(this).siblings(".stories").toggle();  // show this category's "stories" div
            }
        });

Вероятно, есть лучшие способы сделать это, но вы поняли идею.

person Riley Dutton    schedule 09.12.2010
comment
Вы правы в том, что не учитываете предыдущее состояние. Но ваш пример не сработал для меня, даже после устранения некоторых незначительных синтаксических проблем (отсутствует закрывающая скобка в первом операторе if; Майк сработал из коробки. Спасибо! - person Val; 09.12.2010