Вопрос

Я постараюсь быть кратким.Я пытаюсь создать текстовые поля, которые скрываются или отображаются, когда пользователь нажимает кнопку развертывания.Я использую метод toggle().

Разметка такая:

<span id="toggle0">+</span>
<div id="toggle0Container">
    blablabla...
<div>

<span id="toggle1">+</span>
<div id="toggle1Container">
    blablabla...
<div>

<span id="toggle2">+</span>
<div id="toggle2Container">
    blablabla...
<div>

// etc

Предполагается, что #toggle0 переключает #toggle0Container, #toggle1 переключает #toggle1Container и так далее.Все это генерируется PHP, поэтому таких контейнеров может быть любое количество.

Вот код JQuery:

$(document).ready(function() {
    // array of numbers, it's pretty redundant, there will never be more than 30 containers
    var arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9 , 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36];
    // hide all containers first
    jQuery.each(arr, function() {
        $('#toggle' + this + 'Container').hide();
    });
    // now the toggle buttons
    jQuery.each(arr, function() {
        $('#toggle' + this).click(function() {
            // this line is not working
            $('#toggle' + this + 'Container').slideToggle('slow');
            // and this just changes the toggle button from + to -
            if ($(this).html() == '+') {
                $(this).html('-');
            } else {
                $(this).html('+');
            }
        });
    });
});

Это работает, за исключением части переключения (я добавил комментарий над строкой, которая не работает).В чем проблема?

Это было полезно?

Решение

Я бы последовал подходу mgroves, но если вы действительно хотите работать с массивом или просто хотите понять, как правильно использовать функциюeach(), вот как вам следует ее использовать:

$(document).ready(function() {
    // array of numbers, it's pretty redundant, there will never be more than 30 containers
    var arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9 , 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36];
    // hide all containers first
    jQuery.each(arr, function(index, item) {
        $('#toggle' + item + 'Container').hide();
    });
    // now the toggle buttons
    jQuery.each(arr, function(index, item) {
        $('#toggle' + item).click(function() {
            // this line is not working
            $('#toggle' + item + 'Container').slideToggle('slow');
            // and this just changes the toggle button from + to -
            if ($(this).html() == '+') {
                $(this).html('-');
            } else {
                $(this).html('+');
            }
        });
    });
});

Другие советы

Это потому, что «this» теперь находится в другой области и относится к фактическому элементу #toggleN DOM, а не к одному из чисел в массиве.

Я бы посоветовал вам отказаться от массива чисел и использовать другой селектор, например:


$("div[id^=toggle][id$=container]").hide();

$("span[id^=toggle]").click(function() {
     $(this).find("span[id^=toggle][id$=container]").slideToggle("slow");
     // .. do your other html stuff
}

Просто откажитесь от этих элементов и замените переключатели переключателей на них.

РЕДАКТИРОВАТЬ

Мне больше нравится решение mgroves для вашего конкретного случая использования, но я оставлю свой ответ, в котором объясняется, как вы можете принять индекс и элемент в качестве параметра метода .each.

ОРИГИНАЛЬНЫЙ ОТВЕТ

Как уже говорили другие, контекст этот это не то, что вы думаете в тот момент, когда вы на него ссылаетесь.Вот отличная статья Реми Шарпа под названием «jQuery это:демистифицированный", который я рекомендую вам прочитать.

функция .each может принимать два параметра, которые вам очень помогут, и вам не понадобится этот массив чисел.

$('span[id^=toggle']').each(function(idx, elem) {

    // idx is the current index of the jQuery object
    $('#toggle' + idx).click(function() {

        // elem is the current element
        $(elem).next('#toggle' + idx + 'Container').slideToggle('slow');

        if ($(elem).html() == '+') {
            $(elem).html('-');
        } else {
            $(elem).html('+');
        }

    });

});

Я бы предложил поместить класс в кнопку переключения (диапазон), например «toggler», и в контейнер переключения, например «контейнер» или что-то в этом роде, чтобы упростить ваш javascript:

$(function() {
    // hide all containers first
    $(".container").hide();
    // now the toggle buttons
    $(".toggler").click(function() {
          var container = $("#" + $(this).attr("id") + "Container");
          container.slideToggle("slow");

          $(this).html(container.is(":visible") ? "-" : "+");
    });
});

Попробуйте.

Как сказал Мгроувс, ваша область действия становится все более сложной при использовании каждого().Видеть этот Чтобы получить больше информации.

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

$(function() {
  // hide all containers first
  $(".container").hide();
  // now the toggle buttons
  $(".toggler").click(function() {
    $(this).next().slideToggle("slow");

    if (container.is(":visible")) {
      $(this).html("-");
    }
    else {
      $(this).html("+");
    }
  });
});

Если вы не можете легко получить классы в диапазонах, вы, вероятно, можете создать аналогичный селектор, используя что-то вроде $('#SpanContainer>span'), чтобы выбирать их по имени тега, начиная с содержащего их элемента.

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

Сделайте разметку примерно так:

<span class="toggleButton">+</span>
<div class="toggleContainer">
   blablabla...
<div>

Теперь ваш код для обработки этого становится таким простым:

$('.toggleButton').click(function() {
    $(this).next('.toggleContainer').slideToggle('slow');
});

Недавно я написал довольно содержательный сценарий для такого поведения.Я пошел немного другим путем: решил обернуть все элементы данного элемента скрытия/показа в содержащий его элемент div.Это позволяет вам иметь несколько «триггеров» для одного раздела, если вам это нужно, и вы можете добавлять произвольное количество элементов скрытия/отображения, не беспокоясь об их нумерации.Я бы структурировал это примерно так:

<div class="expSecWrapper">
    <div class="expSecTrigger">Insert Trigger Here</div>
    <div class="expSecBody">
        Content to hide/show
    </div>
</div>

И тогда код jQuery будет примерно таким:

$(document).ready(function(){
    var targets = $(".expSecWrapper")
    targets.find(".expSecTrigger").click(function(){
        targets.find(".expSecBody").hide()
        $(this).parents(".expSecWrapper").eq(0).children(".expSecBody").toggle();
    })
})

Вы можете добавить оставшийся JS, соответствующий вашему приложению.

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

И последнее: вам даже не нужно использовать итератор .each для назначения такого поведения.Что-то вроде .click() назначит поведение всей группе объектов jQuery.Пока вы используете селектор, который захватит все ваши цели.

Извините, пришлось пару раз редактировать.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top