jquery - Efficient, concise way to find next matching sibling? -
sticking official jquery api, there more concise, not less efficient, way of finding next sibling of element matches given selector other using nextall
:first
pseudo-class?
when official api, mean not hacking internals, going straight sizzle, adding plug-in mix, etc. (if end having that, it, that's not question is.)
e.g, given structure:
<div>one</div> <div class='foo'>two</div> <div>three</div> <div class='foo'>four</div> <div>five</div> <div>six</div> <div>seven</div> <div class='foo'>eight</div>
if have div
in this
(perhaps in click
handler, whatever) , want find next sibling div matches selector "div.foo", can this:
var nextfoo = $(this).nextall("div.foo:first");
...and works (if start "five", instance, skips "six" , "seven" , finds "eight" me), it's clunky , if want match first of of several selectors, gets lot clunkier. (granted, it's lot more concise raw dom loop be...)
i want:
var nextfoo = $(this).nextmatching("div.foo");
...where nextmatching
can accept full range of selectors. i'm surprised next(selector)
doesn't this, doesn't, , docs clear does, so...
i can write , add it, although if , stick published api, things pretty inefficient. instance, naïve next
loop:
jquery.fn.nextmatching = function(selector) { var match; match = this.next(); while (match.length > 0 && !match.is(selector)) { match = match.next(); } return match; };
...is markedly slower nextall("selector:first")
. , that's not surprising, nextall
can hand whole thing off sizzle, , sizzle has been thoroughly optimized. naïve loop above creates , throws away sorts of temporary objects , has re-parse selector every time, no great surprise it's slow.
and of course, can't throw :first
on end:
jquery.fn.nextmatching = function(selector) { return this.nextall(selector + ":first"); // <== wrong };
...because while work simple selectors "div.foo", fail "any of several" option talked about, "div.foo, div.bar".
edit: sorry, should have said: finally, use .nextall()
, use .first()
on result, jquery have visit of siblings find first one. i'd stop when gets match rather going through full list can throw away results first. (although seems happen really fast; see last test case in speed comparison linked earlier.)
thanks in advance.
you can pass multiple selector .nextall()
, use .first()
on result, this:
var nextfoo = $(this).nextall("div.foo, div.something, div.else").first();
edit: comparison, here added test suite: http://jsperf.com/jquery-next-loop-vs-nextall-first/2 approach faster because it's simple combination of handing .nextall()
selector off native code when possible (every current browser) , taking first of result set....way faster looping can purely in javascript.
Comments
Post a Comment