March 29, 2012

How to develop a Jquery plugin to find the first child that match with a selector?

Question by Ivan

I’m trying to make a Jquery plugin (findFirst()) to find the first child with a given characteristics (something in the middle of the find() and children() functions. For instance, given this markup:

<div id="start">
    <div>
        <span>Hello world</span>
        <ul class="valid-result"> ... </ul>
        <ul class="valid-result">
            <li>
                <ul class="not-a-result"> ... </ul>
            </li>
        </ul>
        <div>
            <ul class="valid-result"> ... </ul>
        </div>
    </div>
</div>

If you ask for $("#start").findFirst('ul') it should return all ul lists that I have tagged with the valid-result class, but not the ul with class not-a-result. It is, this function has to find the first elements that matches with a given selector, but not the inner elements that match this selector.

This is the first time I try to code a Jquery function, and what I’ve already read doesn’t helps me too much with this. The function I have developed is this:

jQuery.fn.findFirst = function (sel) {
    return this.map(function() {
        return $(this).children().map(function() {
            if ($(this).is(sel)) {
                return $(this);
            } else {
                return $(this).findFirst(sel);
            }
        });
    });
} 

It works in the sense it tries to return the expected result, but the format it returns the result is very rare for me. I suppose the problem is something I don’t understand about Jquery. Here you have the JFiddle where I’m testing.

EDIT

The expected result after $("#start").findFirst('ul') is a set with all UL that have the class ‘valid-result’ BUT it’s not possible to use this class because it doesn’t exist in a real case (it’s just to try to explain the result).

This is not equivalent to first(), because first returns only one element!

Answer by charlietfl

You could do something like this:

var selector='ul';

var $results= $('#start '+selector).not( selector +' '+selector);

The not() method will exclude elements that match selector but are also descendents of the same selector

Answer by Starx

You don’t need to build a plugin. use jQuery inbuilt .first() and as suggested by Mark, you can also use first selector :first

$("#yourselector ul").first();

Here is the usages in your case

$("#start").find("ul").first().css("background", "red");
   //For Short $("#start ul").first()

To use class filter, use the attribute selector

$("#start").find("ul[class=valid-result]").first().css("background", "red");
   //For Short $("#start ul[class=valid-result]").first()

Demo


Update

If you want to highlight only the outer ul’s with class valid-result then first() is not needed at all

$("#start ul[class=valid-result]").css("background", "red");

But, since the inner ul will also share the background on my example, you might have to set different background for inner ul‘s. Here is an example


Update 2

If you want to select the first level of the <ul> then

$("#start div").chilrent("ul"); //this will return the first level of ul inside the div

Author: Nabin Nepal (Starx)

Hello, I am Nabin Nepal and you can call me Starx. This is my blog where write about my life and my involvements. I am a Software Developer, A Cyclist and a Realist. I hope you will find my blog interesting. Follow me on Google+

...

Please fill the form - I will response as fast as I can!