8

Basically what the title says - I'm wondering if there's a way to use .find() on the same jQuery selector multiple times. Or maybe using .find() more than once isn't the right way to do this?

Here's what I'm trying to accomplish:

HTML

<div id="foo">
    <h2>A Header</h2>
    <p>Some text</p>
</div>

JS

$("#foo").find("h2").html("New header");
$("#foo").find("p").html("New text");

Webstorm complains about the duplicated jQuery selector. Is there a different/better way to do this?

Mohammad
  • 21,175
  • 15
  • 55
  • 84
daviddorsey4
  • 122
  • 1
  • 10

6 Answers6

9

You can use next():

$("#foo").find("h2").html("New header")
         .next("p").html("New Text");
Sam Coles
  • 4,003
  • 24
  • 19
  • That's probably more internally concise than my answer. Presumably, jQuery doesn't have to walk the tree from the document level for each element, as it would in mine. – BobRodes Jul 22 '16 at 16:48
7

To go back to a previous collection in chaining, we can use end()

$("#foo")
    .find("h2")
        .html("New header")
        .end()
    .find("p")
        .html("New text");
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="foo">
    <h2>A Header</h2>
    <p>Some text</p>
</div>
sabithpocker
  • 15,274
  • 1
  • 42
  • 75
3

Use .addBack() to back to first selector after using .find() in chaining.

$("#foo").find("h2").html("New header").addBack().find("p").html("New text");
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="foo">
  <h2>A Header</h2>
  <p>Some text</p>
</div>
Mohammad
  • 21,175
  • 15
  • 55
  • 84
2

The "right way" (the simplest way at least) is to use basic CSS selector syntax:

$("#foo h2").html("New header");
$("#foo p").html("New text");

Or more specifically, this:

$("#foo>h2").html("New header");
$("#foo>p").html("New text");

The first example targets any h2 that is a descendant of foo at any level, whereas the second targets any h2 that is an immediate descendant.

As for trying to do something like this:

x = $("#foo").find("h2").find("p");

This is equivalent to this:

x = $("#foo h2 p");

(You can verify this by going into debug after executing the statement and looking at x.selector.) Which means that you are looking for a paragraph inside a header inside foo:

<div id="foo">
    <h2>A Header
        <p>**Selector would find this**</p>
    </h2>
</div>

And there isn't any such in your example.

BobRodes
  • 5,990
  • 2
  • 24
  • 26
1
<div id="foo">
  <h2>A Header</h2>
  <p>Some text</p>
</div>

var $foo = $("#foo");
$foo.find("h2").html("New header");
$foo.find("p").html("New text");

OR, if it's possible:

<div id="foo">
  <h2>A Header</h2>
  <p>Some text</p>
</div>

var htmlString = '<h2>New header</h2><p>New text</p>';
$("#foo").html( htmlString );
Mohit Bhardwaj
  • 9,650
  • 3
  • 37
  • 64
  • That's rather a roundabout way to solve the problem. Your `var $foo = $("#foo"); $foo.find("h2").html("New header");` is equivalent to `$("#foo h2").html("New header");`. – BobRodes Jul 22 '16 at 16:24
  • @BobRodes Using it like that caches the selected element. So, it does not need to find the element every time you select it using `$("#foo")`. It's considered a good practice to do so if you are going to use a selector multiple times. – Mohit Bhardwaj Jul 22 '16 at 16:26
  • Yes, I agree if you are going to reference a selected element multiple times (which the OP didn't mention), that you should store it in a variable. However, applying a `find` to the variable negates the advantage of caching, since you're appending a value to the existing selector and going and getting a new element all over again. You're incurring double overhead, once to cache the parent and once to get the descendant. If you're going to avail yourself of caching to reference multiple elements of the same type, `var $foo_h2 = $("#foo h2"); var $foo_b = $("#foo b")`, etc. makes more sense. – BobRodes Jul 22 '16 at 16:36
  • In any case, I think Sam Coles' answer is better than either of ours. :) – BobRodes Jul 22 '16 at 16:47
0

It says duplicated jQuery selector because you should ( when possible ) always cache your jQuery selectors, because it's wasteful calling $("#foo") each time you need that object.
So, your code should become like this

HTML

<div id="foo">
  <h2>A Header</h2>
  <p>Some text</p>
</div>

JS

var foo = $("#foo");
foo.find("h2").html("New header");
foo.find("p").html("New text");
CapitanFindus
  • 1,498
  • 15
  • 26