2

我会尽量保持简短。我正在尝试创建在用户单击展开按钮时隐藏或显示的文本框。我正在使用 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('+');
            }
        });
    });
});

除了切换部分外它都有效(我在无效的行上方添加了评论)。问题出在哪里?

4

8 回答 8

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
}

只需抛弃这些,并用它们替换切换选择器。

于 2009-07-16T17:00:00.413 回答
2

编辑

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

原始答案

正如其他人所说,不是您在引用它时所认为的上下文。这是 Remy Sharp 撰写的一篇很棒的文章,标题为“ 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('+');
        }

    });

});
于 2009-07-16T17:07:03.100 回答
2

我会遵循 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('+');
            }
        });
    });
});
于 2009-07-16T17:09:23.220 回答
1

我建议在您的切换按钮(跨度)上放置一个类,例如“toggler”和您的切换容器,例如“container”或其他东西,以简化您的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") ? "-" : "+");
    });
});

试一试。

于 2009-07-16T17:02:36.133 回答
1

正如mgroves 所说,您的范围通过使用each() 得到了提升。有关更多信息,请参阅

于 2009-07-16T17:03:58.363 回答
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>span') 之类的东西构造一个类似的选择器,以按标签名称选择它们,从它们的包含元素降序。

于 2009-07-16T17:08:45.373 回答
0

我最近为这样的行为写了一个相当丰富的脚本。我采取了稍微不同的路线,因为我选择将给定隐藏/显示元素的所有元素包装在包含 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 对象组。只要您使用一个可以抓取所有目标的选择器。

对不起,不得不编辑几次。

于 2009-07-16T17:26:35.213 回答
0

你应该给你的元素一个可以搜索的类,然后使用next.

让你的标记是这样的:

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

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

$('.toggleButton').click(function() {
    $(this).next('.toggleContainer').slideToggle('slow');
});
于 2009-07-16T17:27:12.917 回答