jQuery.each()麻烦

时间:2009-07-16 16:52:47

标签: jquery toggle slide

我会尽量保持这一点。我正在尝试创建用户单击展开按钮时隐藏或显示的文本框。我正在使用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

#togle0应该切换#togle0Container,#toggle1切换#topggle1Container,依此类推。这全部由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('+');
            }
        });
    });
});

除了切换部分之外它是有效的(我在不起作用的行上方添加了注释)。问题出在哪里?

8 个答案:

答案 0 :(得分:5)

这是因为“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
}

放弃那些每个人并用那些替换切换选择器。

答案 1 :(得分:2)

修改

我更喜欢针对您的特定用例的mgroves解决方案,但我会留下我的答案,这解释了如何接受索引和元素作为.each方法的参数

原始回答

正如其他人所说, this 的上下文并不是您所认为的那样。这是雷米夏普的一篇很棒的文章,标题为“jQuery's this: demystified”,我建议你阅读。

.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('+');
        }

    });

});

答案 2 :(得分:2)

我会遵循mgroves的方法但是如果你真的想做数组的事情,或者只是想弄清楚如何正确使用每个(),那么你应该如何使用它:

$(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('+');
            }
        });
    });
});

答案 3 :(得分:1)

我建议在您的切换按钮(span)上添加一个类,如“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") ? "-" : "+");
    });
});

试一试。

答案 4 :(得分:1)

正如mgroves所说,你的范围是通过使用每个()来解决所有问题。有关详细信息,请参阅this

答案 5 :(得分:1)

我准备发布Max对使用课程的确切意见。我只会通过这个更容易的选择器来改进他的建议来找到容器:

$(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&gt; span')之类的东西构建类似的选择器,以按标记名称选择它们,从其包含元素开始。

答案 6 :(得分:0)

我最近为这样的行为写了一个相当实质的脚本。我选择了一个稍微不同的路线,因为我选择将一个给定的hide / show元素的所有元素包含在一个包含的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对象组。只要你使用一个能够抓住你所有目标的选择器。

抱歉,不得不编辑几次。

答案 7 :(得分:0)

您应该为您的元素提供可以搜索的类,然后使用next

使你的标记像这样:

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

现在,处理此问题的代码变得如此简单:

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