2

Is it possible, without greatly impacting on the original source code, to extend the jQuery .first() method so that it can accept a predicate parameter? Fundamentally what I want it to do is something similar to LINQ's .First(), C# method. In JavaScript it would look something like this:

function first(arr, predicate) {
    for (var i = 0; i < arr.length; i++) {
        // return the first item fulfilling the predicate
        if (predicate.call(arr[i])) {
            return arr[i];
        }
    }
}

var myArray = [1, 3, 5],
    myPredicate = function() {
        return this >= 2;
    };

var result = first(myArray, myPredicate); // should give '3'

I know it can easily be achieved with JavaScript; I'm just curious if it's possible to easily extend an existing method within jQuery.

Solution used:

$.fn.firstOne = function(predicate) {
    // validate the predicate is a function
    if ($.isFunction(predicate)) {
        // iterate through each item, finding the first match
        for (var i = 0; i < this.length; i++) {
            if (predicate.call(this.eq(i), i)) {
                return this.eq(i);
            }
        }
    }

    // maintain chainability
    return $();
};
Richard
  • 8,110
  • 3
  • 36
  • 59
  • Just use `.find` or `.filter`, then get the 1st element from that. – gen_Eric Sep 17 '12 at 14:26
  • yes its possible, but i dont think you should. the jquery methods are chained to their original single/array output. To hijack that function to iterate through separate arrays would be sortof misleading. – Kristian Sep 17 '12 at 14:26

2 Answers2

3

You can easily (and safely) create your own methods as needed,

$.fn.firstfn = function(fn) {
    return this.filter(fn).first()
}

$("#nav > li").firstfn(function() {
    return $(this).text() === "John Smith";
});

However I don't suggest you override existing methods. Just add your own methods.

Kevin B
  • 94,570
  • 16
  • 163
  • 180
  • Thanks @Kevin B, I'm reluctant to overwrite existing methods as well. I think I may resort to creating my own mini-plugin / utility as you recommended. I'm aware of the `filter` and `find` methods on jQuery, but ideally want to 'escape' the iteration as soon as possible. – Richard Sep 17 '12 at 14:58
  • 1
    In that case i would suggest using a basic for loop rather than `.filter`. – Kevin B Sep 17 '12 at 14:59
  • Yeah, I think I'll use a similar approach to the code I provided in the question, but within a plugin. – Richard Sep 17 '12 at 15:00
  • I'm not sure if you're aware, but `this` within a function defined on `$.fn` is a jQuery object, which is an array-like structure. you can loop over it in a for loop. http://jsfiddle.net/LHxNZ/ using `.eq()` keeps it as a jQuery object allowing for chaining. – Kevin B Sep 17 '12 at 15:03
  • Yeah that's fine Kevin B, I've written a handful of plugins before; but thank you for the heads up. :) – Richard Sep 18 '12 at 08:01
1

You can easily extend jQuery with your own functions, see this question for how to do this

But it already has built in selectors to do first() with predicates / selectors. Here are some examples

$("#mycontainer li.classYouWant").first();
$("#mycontainer").find("another selector").first();
$("#mycontainer li a:first");
Community
  • 1
  • 1
Chris
  • 26,744
  • 48
  • 193
  • 345