JQuery: Как выбрать "отсюда до следующего H2"?
Я создаю очень простой раздел FAQ с jQuery. Например:
<h2>What happens when you click on this question?</h2>
<p>This answer will appear!</p>
Это все внутри очень специфического div, поэтому я буду выбирать заголовок с $('#faq h2')
. Простой, не так ли? Нажмите на H2 и используйте this.next()
, чтобы отобразить следующий абзац.
(Оговорка с этой страницей заключается в том, что не-программист будет ее поддерживать, поэтому я не использую классы: нет гарантии, что в каких-либо новых элементах будут иметься нужные классы.)
Итак! Проблема:
<h2>What happens when you click on the next question?</h2>
<p>That is an interesting conundrum.</p>
<p>Because the maintainer is kind of long-winded</p>
<p>and many answers will span a few paragraphs.</p>
Итак, как, не добавляя в div
и классы и еще что-нибудь, могу ли я, чтобы моя подпрограмма this.next()
выбирала все между вопросом, который был нажат, и следующим вопросом (заголовок H2)?
Ответы
Ответ 1
Интересная проблема. Прежде всего позвольте мне сказать, что я считаю, что лучшая стратегия состоит в том, чтобы заключить весь ответ в div, а затем проблема становится тривиальной:
<h2>Question here</h2>
<div>
<p>Answer here</p>
</div>
</h2>Next Question</h2>
...
с:
$(function() {
$("h2").click(function() {
$(this).next().toggleClass("highlighted");
});
});
Но, будучи сказанным, оно разрешимо без этого.
$(function() {
$("h2").click(function() {
$(this).nextAll().each(function() {
if (this.tagName == 'H2') {
return false; // stop execution
}
$(this).toggleClass("highlighted");
});
});
});
Не очень элегантный, но он будет работать.
Примечание.. Предполагается, что вопросы являются братьями и сестрами. Если они не становятся намного сложнее.
Ответ 2
Я понимаю, что это старый вопрос, но jQuery 1.4 теперь имеет nextUntil. Так что теперь должно работать что-то вроде этого:
$('h2').click(function(){
$(this).nextUntil('h2').show();
})
Ответ 3
не было бы смысла использовать CSS-стиль список DL?
<dl class="faq">
<dt>Question?</dt>
<dd>
<p>Answer</p>
<p>Answer</p>
<p>Answer</p>
</dd>
</dl>
И затем простой выбор с помощью:
$('+ dd', this);
это текущий dt.
Или просто оберните каждый ответ в div, так как он имеет смысл семантически. Тем не менее, я думаю, что список DL имеет смысл более семантически.
Ответ 4
Конечно! Просто сделайте цикл while.
$('h2').click(function() {
var next = $(this).next();
while (next.length != 0 && next[0].nodeName == 'P')
{
next.toggle();
next = next.next();
}
});
Это предполагает, что у вас есть только теги p после h2. Вы можете добавить дополнительные исключения в цикл while, если хотите добавить что-то вроде img.
Или, если вам все равно, что между тегами H2 вы можете проверить, что он не равен H2.
$('h2').click(function() {
var next = $(this).next();
while (next.length != 0 && next[0].nodeName != 'H2')
{
next.toggle();
next = next.next();
}
});
Это скроет все после нажатия на Н2, пока не будет обнаружен либо следующий H2, либо вы достигнете уровня в dom.
Ответ 5
Возможно, это не отвечает на ваш вопрос, но вы можете обернуть каждый элемент FAQ (т.е. каждую пару вопросов/ответов) в элементе DIV
. Это будет иметь смысл семантически, а не программисту, поддерживающему страницу, просто нужно будет скопировать полный DIV
(нет необходимости в классах).
HTML:
<div id="faq">
<!-- start FAQ item -->
<div>
<h2>Question goes here</h2>
<p>Answer goes here.</p>
<p>And here.</p>
<ul>
<li>Really, use any HTML element you want here.</li>
<li>It will work.</li>
</ul>
</div>
<!-- end FAQ item -->
<!-- start FAQ item -->
<div>
<h2>Second question goes here</h2>
<p>Answer to question two.</p>
</div>
<!-- end FAQ item -->
</div>
JavaScript (jQuery):
$('#faq div h2').click(function() {
$(this).parent().find(':not(h2)').show();
});
Ответ 6
На всякий случай есть люди, которым нужен ответ для этого...
Это также включает в себя строку h2 в группе.
Здесь, если образец html, для которого работает мое решение:
<h2> text1 </h2>
<p>asd</p>
<p>asd</p>
<p>asd</p>
<p>asd</p>
<h3>kjdf</h3>
<h2>asdk</h2>
<h3>kjdf</h3>
<p>asd</p>
<p>asd</p>
<p>asd</p>
<p>asd</p>
<h2>aqdsa</h2>
Решение:
jQuery( function ( $ ) {
//defining groups for wrapping them in custom divs
$('h2').each( function () {
var grpForDiv= [];
var next = $(this).next();
grpForDiv.push(this);
while ( next.length!==0 && next!== undefined && next[0].nodeName !== 'H2')
{
grpForDiv.push(next[0]);
next = next.next();
}
jQuery(grpForDiv).wrapAll('<div class="Group1" />');
} );
} );
Ответ 7
Обратите внимание, что выбранный ответ является хорошим, но я занимаюсь чем-то подобным, поэтому я работал сверхурочно:)
Я привел это в пример.
Учитывая HTML:
<h2>Question 1</h2>
<p>Answer 1</p>
<p>Answer 1</p>
<p>Answer 1</p>
<h2>Question 2</h2>
<p>Answer 2</p>
<p>Answer 2</p>
<p>Answer 2</p>
<h2>Question 3</h2>
<p>Answer 3</p>
<p>Answer 3</p>
<p>Answer 3</p>
Сделайте следующее, и вы получите ответ. Я думаю, что теперь это самый изящный из всех предоставленных решений, но я бы оценил другие вложения по этому поводу немного.
jQuery.fn.nextUntilMatch = function(selector) {
var result = [];
for(var n=this.next();(n.length && (n.filter(selector).length == 0));n=n.next())
result.push(n[0]);
return $(result);
}
$(function() {
$('h2~p').hide();
$('h2').click(function() {
$(this).nextUntilMatch(':not(p)').toggle();
})
});
Ответ 8
Вы также можете сделать это без редактирования HTML. Это плагин, который я только что написал для этой цели:
(function($){
$.fn.nextUntill = function(expr){
var helpFunction = function($obj, expr){
var $siblings = $obj.nextAll();
var end = $siblings.index( $siblings.filter(expr) );
if(end===-1) return $([]);
return $siblings.slice(0, end);
}
var retObject = new Array();
this.each(function(){
$.merge(retObject, helpFunction($(this), expr));
});
return $(retObject);
}
})(jQuery);
Вы можете использовать его следующим образом:
$('h2').click(function(){
$(this).nextUntill('h2').show(); //this will show all P tags between the clicked h2 and the next h2 assuiming the p and h2 tags are siblings
});
Ответ 9
Я не думаю, что ваша стратегия решения проблемы верна, у вас было 6 ответов, которые частично решают вашу проблему.....
Но ваша самая большая проблема заключается в том, что вы говорите, что не можете доверять сторонникам использовать divs/spans/classes и т.д.
То, что я думаю, вам нужно сделать, это упростить процесс для них и обучить их использованию вашего метода, или НЕ РАБОТАЕТ.
добавьте свою собственную простую метку и интерпретируйте для нее.
[Q] What happens when you click this link?[/Q]
[A] This marvellous answer appears [/A]
(jQuery не будет исправлять ошибку пользователя)