单击图例元素时折叠字段集

时间:2011-01-11 14:10:51

标签: jquery toggle

我有一个jQuery函数,当点击它的图例时,它会切换字段集内容的可见性,只留下字段集边框(如果有的话)和图例显示:

$('legend.togvis').click(function() {
    $(this).siblings().toggle();
    return false;
});

除非字段集包含文本节点,否则它很有效。

<fieldset><legend class='togvis'>Click Me</legend>
  <p>I toggle when the legend is clicked.</p>
  But I'm a recalcitrant text node and refuse to toggle.
</fieldset>

为了切换文本节点,我尝试了这个:

$('legend.togvis').click(function() {
    $(this).parent().contents().not('legend').toggle();
    return false;
});

与第一个函数的作用相同。这个:

$('legend.togvis').click(function() {
    $(this).parent().contents(":not(legend)").toggle();
    return false;
});

抛出错误

Message: 'style.display' is null or not an object
Line: 5557
Char: 3
Code: 0
URI: http://code.jquery.com/jquery-1.4.4.js

有关如何获取字段集的整个内容(减去图例)以在单击图例时切换的任何想法?

ETA解决方案,非常感谢Eibx

$('legend.togvis').click(function() { 
    $(this).parent().contents().filter(
        function() {  return this.nodeType == 3; }).wrap('<span></span>');//wrap any stray text nodes
    $(this).siblings().toggle(); 
}); 

6 个答案:

答案 0 :(得分:14)

你根本无法使文字在HTML,JavaScript或CSS中消失。它需要包含在应用display:none;或类似内容的HTML元素中。

以下代码将所有内容包装到div中,并将您的图例移动到与div相同的级别,并在单击图例时使div显示/隐藏。

$("fieldset legend").click(function() {
  if ($(this).parent().children().length == 2)
    $(this).parent().find("div").toggle();
  else
  {
    $(this).parent().wrapInner("<div>");
    $(this).appendTo($(this).parent().parent());
    $(this).parent().find("div").toggle();
  }
});

答案 1 :(得分:11)

由于文本节点不是元素,因此无法切换它们。

作为最后的手段,如果你不能用元素包装它们,你可以删除除图例之外的所有内容并稍后添加元素和文本节点:

$(document).ready(function() {
    $('legend.togvis').click(function() {
        var $this = $(this);
        var parent = $this.parent();
        var contents = parent.contents().not(this);
        if (contents.length > 0) {
            $this.data("contents", contents.remove());
        } else {
            $this.data("contents").appendTo(parent);
        }
        return false;
    });
});

您可以测试该解决方案here

答案 2 :(得分:5)

使用div标签分隔内容,例如:

<fieldset>
  <legend class='togvis'>Click Me</legend>
  <div class="contents">
  <p>I toggle when the legend is clicked.</p>
  But I'm a recalcitrant text node and refuse to toggle.
  </div>
</fieldset>

然后你只需要切换div。

$('legend.togvis').click(function() {
    $(this).closest("contents").toggle();
    return false;
});

<强>更新 只有在您无法编辑HTML的情况下,您才能执行以下,但只有当所有文本都在至少一个标记内时才会有效

$('legend.togvis').click(function() {
    $(this).parents("fieldset").find("*:not('legend')").toggle();
    return false;
});

在线演示: http://jsfiddle.net/yv6zB/1/

答案 3 :(得分:0)

可能只是将文本放入sibilig标签:

<fieldset><legend class='togvis'>Click Me</legend>
  <div><p>I toggle when the legend is clicked.</p>
  But I'm a recalcitrant text node and refuse to toggle.</div>
</fieldset>

答案 4 :(得分:0)

我喜欢接受的答案,但没有找到足够强大的用于我的目的。只检查子元素数量的长度不支持很多场景。因此,我会考虑使用类似于:

的实现
$("fieldset legend").click(function () {
    var fieldset = $(this).parent();
    var isWrappedInDiv = $(fieldset.children()[0]).is('div');

    if (isWrappedInDiv) {
        fieldset.find("div").slideToggle();
    } else {
        fieldset.wrapInner("<div>");
        $(this).appendTo($(this).parent().parent());
        fieldset.find("div").slideToggle();
    }
});

答案 5 :(得分:0)

光彩纯HTML / CSS解决方案

这可以完全通过HTML和CSS来完成,现在是2019年。

#toggle + #content {
    display: none;
}

#toggle:checked + #content {
    display:block;
}

legend {
    width: 85%;
    border: 1px solid black;
    padding: 3px 6px;
    cursor: pointer;
}

legend label {
    width: 100%;
    display: inline-block;
    cursor: inherit;
}

legend label::after {
    content: "▼";
    float: right;
}
<body>
<form>
<fieldset>
    <legend><label for="toggle">Test</label></legend>
    <!-- This input has no name, so it's not submitted with the form -->
    <input type="checkbox" id="toggle" checked="" hidden=""/>
    <div id="content">
        <label>Some text field<input type="text" name="some-text-field"/></label><br/>
        <label>Some color input<input type="color" name="some-color-field"/></label>
    </div>
</fieldset>
</form>
</body>

Javascript版本

尽管Pure HTML / CSS解决方案显然很出色,但是使用Javascript编程页面上的交互性并没有错。但是我注意到所有其他答案都使用JQuery,这在2019年完全没有必要。

window.addEventListener('load', () => {
    const collapser = document.getElementById('collapser');
    const collapsable = document.getElementById('collapsable');

    function collapse(event) {
        if (event) {
            event.stopPropagation();
        }

        collapsable.hidden = !collapsable.hidden;
    }

    collapser.addEventListener('click', collapse);
});
legend {
    width: 85%;
    border: 1px solid black;
    padding: 3px 6px;
    cursor: pointer;
    display: inline-block;
}

legend::after {
    content: "▼";
    float: right;
}
<body>
<form>
<fieldset>
    <legend id="collapser">Test</legend>
    <div id="collapsable">
        <label>Some text field<input type="text" name="some-text-field"/></label><br/>
        <label>Some color input<input type="color" name="some-color-field"/></label>
    </div>
</fieldset>
</form>
</body>