Подтвердить что ты не робот

Свернуть поле, когда нажал элемент

У меня есть функция 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(); 
}); 
4b9b3361

Ответ 1

Вы просто не можете удалить текст в HTML, JavaScript или CSS. Он должен содержаться в HTML-элементе, который будет иметь приложение display:none; или что-то подобное.

Следующий код превратит все в div и переместит вашу легенду на тот же уровень, что и div, и сделайте div show/hide, когда вы нажмете на легенду.

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

Ответ 2

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

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

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

Вы можете проверить это решение здесь.

Ответ 3

Используйте тег 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/

Ответ 4

Может быть, вы просто вложите свой текст в тег 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>

Ответ 5

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

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