How to select all content between two tags in jQuery
Asked Answered
M

7

61

I have a document with headings and unordered lists.

How can I use JQuery to select a given heading (by its unique class name) AND all content between that heading and the next heading?

Update:

Your suggestions are great, but aren't what I'm looking for. In the below code, for example, I would like to access only the "h1" with id of "heading2" and everything up to, but not including the "h1" with id of "heading3".

The jQuery examples provided above will access everyting after the first "h" tag that is not an "h" tag.

... or, correct me if I'm wrong :)

    <h1 id="heading1">...</h1>
        <ul>...</ul>
        <p>...</p>
        <ul>...</ul>
        <p>...</p>
    <h1 id="heading2" >...</h1>
        <ul>...</ul>
        <p>...</p>
        <ul>...</ul>
        <p>...</p>
    <h1 id="heading3" >...</h1>
        <ul>...</ul>
        <p>...</p>
        <ul>...</ul>
        <p>...</p>
Malevolent answered 26/1, 2009 at 19:47 Comment(0)
M
74

Two methods in particular would be very useful solving this problem: .nextUntil, and .andSelf. The first will grab all of the siblings following your selector, and the latter will lump in whatever is matched by your selector as well, giving you one jQuery object that includes them all:

$("#heading2")
    .nextUntil("#heading3").andSelf()
        .css("background", "red");

This results in the following:

enter image description here

Monafo answered 26/1, 2009 at 21:50 Comment(4)
Thanks for the JQuery lesson! Worked like a charm.Malevolent
Thanks. This helped solve a nightmare problem with Firefox 3.6.4 and nextUntil()Mckellar
any idea how to do this in cheerio?Preteritive
Looks like .andSelf is deprecated and we need to use .addBack() from jQuery 1.8 onwards api.jquery.com/addBackSiu
S
7

Here is the solution I use for my projects:

jQuery selector

(function ($) {
    $.fn.between = function (elm0, elm1) {
        var index0 = $(this).index(elm0);
        var index1 = $(this).index(elm1);

        if (index0 <= index1)
            return this.slice(index0, index1 + 1);
        else
            return this.slice(index1, index0 + 1);
    }
})(jQuery);

Usage

$('body').between($('#someid'), $('#someid2')).each(function () {
    // Do what you want.
});
Spun answered 18/11, 2011 at 7:41 Comment(0)
T
4
$('#secondSelector').prevAll('#firstSelector ~ *')
Tress answered 5/4, 2010 at 17:30 Comment(1)
smart. exactly what I needed.Bently
S
2

Yeah, you're right. This will only avoid the desired selector. Maybe it needs to be more detailed:

$(firstSelector).nextAll().not(secondSelector).not($(secondSelector).nextAll()).text()
Salazar answered 27/1, 2009 at 0:3 Comment(0)
S
2

I feel as if the accepted answer needs a bit of an update since the release of jQuery 1.8 and later. .andSelf() has been deprecated. In its place, we have .addBack(). The documentation explains everything you need to know.

Selfexistent answered 27/10, 2016 at 14:14 Comment(0)
S
1

Maybe, with

$(selectorForFirstHeading).nextAll().not(selectorForLastHeading).text()

Why do I use text()? Because html() will only return the inner HTML of the first result element.

Salazar answered 26/1, 2009 at 20:22 Comment(0)
G
0

If your elements are at the same level, something like this:

<h1 id="heading1">...</h1>
<ul>...</ul>
<p>...</p>
<ul>...</ul>
<p>...</p>
<h1 id="heading2" >...</h1>

That is, your next heading element is not a child of an element at the same level as the first heading element. You can try this code:

// This will get all the following siblings of <h1 id="heading1"> except those that are headings themselves
var elements = $('#heading1').nextAll().not("h1");
Gulden answered 26/1, 2009 at 20:30 Comment(1)
Hi, good answer, we have the same idea but you missed to serve the content :)Salazar

© 2022 - 2024 — McMap. All rights reserved.