Свернуть поле, когда нажал элемент
У меня есть функция 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();
});
Ответы
Ответ 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();
}
});