354

I'm trying to pass "this" from a clicked span to a jQuery function that can then execute jQuery on that clicked element's first child. Can't seem to get it right...

<p onclick="toggleSection($(this));"><span class="redClass"></span></p>

Javascript:

function toggleSection(element) {
  element.toggleClass("redClass");
}

How do I reference the :first-child of element?

BoltClock
  • 700,868
  • 160
  • 1,392
  • 1,356
macca1
  • 9,541
  • 9
  • 32
  • 41
  • 4
    If you're using jQuery, why don't you bind event handlers using jQuery also? – Vivin Paliath Feb 16 '10 at 19:37
  • 2
    because bind event handlers have to be initialized in document.ready() which adds a performance hit (this is an app for IE6). or is there another way? – macca1 Feb 16 '10 at 19:43
  • Hm.. not sure. Binding using jQuery is the standard way (if you're already using jQuery). What kind of performance hit are you experiencing when you use `jQuery(document).ready(...)`? – Vivin Paliath Feb 16 '10 at 19:52
  • It's a large application with 7+ developers. It was originally 4+ seconds before I tried to clean it up a bit. So I'd rather avoid adding more to it when I don't have to :) – macca1 Feb 16 '10 at 20:30

11 Answers11

533

If you want to apply a selector to the context provided by an existing jQuery set, try the find() function:

element.find(">:first-child").toggleClass("redClass");

Jørn Schou-Rode noted that you probably only want to find the first direct descendant of the context element, hence the child selector (>). He also points out that you could just as well use the children() function, which is very similar to find() but only searches one level deep in the hierarchy (which is all you need...):

element.children(":first").toggleClass("redClass");
Community
  • 1
  • 1
Shog9
  • 156,901
  • 35
  • 231
  • 235
  • 1
    thanks! works perfectly. I imagine the other ways listed below will work as well. – macca1 Feb 16 '10 at 19:38
  • 6
    I believe `find()` searches through all descendants, and `:first-child` can match one element per parent. Hence, this query can is likely to return several elements. Or am I mistaken? – Jørn Schou-Rode Feb 16 '10 at 19:38
  • @Jørn: you're correct, I hadn't thought about this - if there is a hierarchy, then an unqualified :first-child selector will produce multiple results. – Shog9 Feb 16 '10 at 19:47
  • 21
    I know this is an old question/answer, but the useage of the ">" selector without a parent in that selector is depreciated (for example, ">:firstchild") as of jQuery 1.8. I suggest instead using `element.children(":first-child")` or `element.children().first();` – Kevin B Sep 06 '12 at 18:09
  • 3
    @KevinB apparently they decided not to deprecate it after all – Alnitak Feb 13 '13 at 15:58
  • 1
    the best approach would be NOT to iterate on all items and then pick the first one, as some suggested here. This would be BAD. – vsync May 08 '14 at 17:09
88

Use the children function with the :first selector to get the single first child of element:

element.children(":first").toggleClass("redClass");
Jørn Schou-Rode
  • 37,718
  • 15
  • 88
  • 122
61

I've added jsperf test to see the speed difference for different approaches to get the first child (total 1000+ children)

given, notif = $('#foo')

jQuery ways:

  1. $(":first-child", notif) - 4,304 ops/sec - fastest
  2. notif.children(":first") - 653 ops/sec - 85% slower
  3. notif.children()[0] - 1,416 ops/sec - 67% slower

Native ways:

  1. JavaScript native' ele.firstChild - 4,934,323 ops/sec (all the above approaches are 100% slower compared to firstChild)
  2. Native DOM ele from jQery: notif[0].firstChild - 4,913,658 ops/sec

So, first 3 jQuery approaches are not recommended, at least for first-child (I doubt that would be the case with many other too). If you have a jQuery object and need to get the first-child, then get the native DOM element from the jQuery object, using array reference [0] (recommended) or .get(0) and use the ele.firstChild. This gives the same identical results as regular JavaScript usage.

all tests are done in Chrome Canary build v15.0.854.0

Community
  • 1
  • 1
manikanta
  • 8,100
  • 5
  • 59
  • 66
  • 24
    Actually, `firstChild` won't give the same results as jQuery's `children()` or selector queries. `firstChild` will include text nodes which is rarely desired. jQuery's `contents()` function *will* include them, but `children()` won't. Newer browsers support `firstElementChild` which will give the first child element, but IE < 9 does not support it. So, if you use `firstChild` you have to manually find the first non-text node child. – Max Nov 28 '11 at 00:41
  • 3
    `$(":first-child", notif)` should be `$(":first", notif)` for expected behaviour. The former will return all first-child element descendants. – Drazen Bjelovuk Mar 06 '17 at 17:38
  • When there are no textnodes as direct children! You can choose to use `$(notif[0].firstChild)` for performance reasons when many children are involved. Then you end with a jQuery object again. On a JSBench.me I got 8,728 ops/s with `notif.children(":first")` and a whopping **12,440,220** ops/s for `$(notif[0].firstChild)`. I used 1000 child nodes to test with. – Piemol Sep 22 '22 at 13:16
32
element.children().first();

Find all children and get first of them.

Bishal Paudel
  • 1,896
  • 2
  • 21
  • 28
13

you can use DOM

$(this).children().first()
// is equivalent to
$(this.firstChild)
Yukulélé
  • 15,644
  • 10
  • 70
  • 94
10

Have you tried

$(":first-child", element).toggleClass("redClass");

I think you want to set your element as a context for your search. There might be a better way to do this which some other jQuery guru will hop in here and throw out at you :)

theIV
  • 25,434
  • 5
  • 54
  • 58
5

I've just written a plugin which uses .firstElementChild if possible, and falls back to iterating over each individual node if necessary:

(function ($) {
    var useElementChild = ('firstElementChild' in document.createElement('div'));

    $.fn.firstChild = function () {
        return this.map(function() {
            if (useElementChild) {
                return this.firstElementChild;
            } else {
                var node = this.firstChild;
                while (node) {
                    if (node.type === 1) {
                        break;
                    }
                    node = node.nextSibling;
                }
                return node;
            }
        });
    };
})(jQuery);

It's not as fast as a pure DOM solution, but in jsperf tests under Chrome 24 it was a couple of orders of magnitude faster than any other jQuery selector-based method.

Alnitak
  • 334,560
  • 70
  • 407
  • 495
  • 1
    I like this plugin - but there are 2 issues: 1) The plugin script cannot be included in the head because `document.body` is not initialized yet, 2) The performance is only much better than alternatives if the number of child nodes is very high. For only a few children (say less than 10) the `$('>:first-child',context)` is a little bit faster. Only the number of children affects the performance, not the depth. – codefactor Nov 15 '13 at 05:53
  • @codefactor good point about `document.body` - I'll look into that. – Alnitak Nov 15 '13 at 09:04
4

please use it like this first thing give a class name to tag p like "myp"

then on use the following code

$(document).ready(function() {
    $(".myp").click(function() {
        $(this).children(":first").toggleClass("classname"); // this will access the span.
    })
})
Flexo
  • 87,323
  • 22
  • 191
  • 272
2

This can be done with a simple magic like this:

$(":first-child", element).toggleClass("redClass");

Reference: http://www.snoopcode.com/jquery/jquery-first-child-selector

Prabhakar
  • 6,458
  • 2
  • 40
  • 51
-2

i am using

 $('.txt').first().css('display', 'none');
Fahimeh Ahmadi
  • 813
  • 8
  • 13
  • This is plain wrong? Apart from no definition of class `txt` in the script, `first()` wouldn't do the job: "Given a jQuery object that represents a set of DOM elements, the .first() method constructs a new jQuery object from the first element in that set." [link](https://api.jquery.com/first/) – fseydel Jan 26 '23 at 10:26
-5

If you want immediate first child you need

    $(element).first();

If you want particular first element in the dom from your element then use below

    var spanElement = $(elementId).find(".redClass :first");
    $(spanElement).addClass("yourClassHere");

try out : http://jsfiddle.net/vgGbc/2/

Amit Rathod
  • 271
  • 3
  • 3
  • 13
    this is just wrong - if `element` is a DOM node then `$(element).first()` is equivalent to `$(element)`, not its first child. – Alnitak Feb 13 '13 at 16:41
  • 1
    Agreed, if element is a DOM node $(element).first() is equivalent $(element) this caused me problem with knockoutJS binding – drgn May 06 '14 at 19:27