views:

63

answers:

3

I have the following JQuery snippet:

(someVar.next().length == 0)?someVar.fadeOut().end().find("ul").first().fadeIn():someVar.fadeOut().next().fadeIn();

There is a fair amount of code duplication between the two results of the conditional - i.e. someVar.fadeOut() and .fadeIn() on both.

I would ideally like something like this:

someVar.fadeOut().((someVar.next().length == 0)?end().find("ul").first():next()).fadeIn();

But that doesn't work :) Safari developer tools reports a syntax error but I'm not skilled enough to work out how to do it properly.

If it can't be shortened, then just saying that is fine :)

A: 
T.J. Crowder
+1  A: 

I removed the .end() because I don't see a use for it.

Otherwise, I just moved .fadeOut() into the conditional test.

(someVar.fadeOut().next().length == 0) 
?  someVar.end().find("ul:first").fadeIn()
:  someVar.next().fadeIn();

Or maybe this?

var $in = (someVar.fadeOut().next().length == 0) 
           ? someVar.end().find("ul:first")
           : someVar.next();
$in.fadeIn();

EDIT: As noted by @T.J. Crowder, I was not correct in removing .end(). I didn't realize that it continues to work if you start a new chain with the previous result. Makes sense though. Fixed.

Also, I had somehow reversed the second example. Fixed.


Another EDIT:

The second example could be further simplified like this:

((someVar.fadeOut().next().length == 0) 
           ? someVar.end().find("ul:first")
           : someVar.next()).fadeIn();

One more EDIT:

Another possibility is to simply .fadeIn() the .next() either way, which will have no effect if its length is 0:

if(someVar.fadeOut().next().fadeIn().length == 0)
     someVar.end().find("ul:first").fadeIn();
patrick dw
Re the `end`, we don't know what filtering he's ending, it could be from before the code he's quoted... Good switch of `.find("ul").first()` to `.find("ul:first")`, though, that should be a bit more efficient.
T.J. Crowder
@T.J. - Yes, you're right. I thought `.end()` would only work in the current chain, but it seems to work for the result of a previous chain stored in a variable. I'll update.
patrick dw
Yep, I had done a previous find() call so the end() is needed :) Thanks for the help
Richard
@Richard - You're welcome. :o)
patrick dw
@Richard - I added one more possible solution. It removes the need for an `else` because it does a `fadeIn()` on the `.next()` in the conditional test. This should be harmless, because if the `length` is `0`, there's nothing to fade.
patrick dw
I moved the fadeOut() and next() calls to the previous line (where the elements are selected), changed (someVar.length == 0) to (!someVar.length), moved fadeIn() to outside the brackets at the end and changed .end.find() to just selecting from scratch and so ended up with:((!someVar.length)?$("#someID ul:first"):someVar).fadeIn();
Richard
@Richard - Looks good. :o)
patrick dw
A: 

Perhaps somewhat off-topic and so I'm making it a CW, but: When things get long like this, can I just put in my bid for good old-fashioned if/else statements?

someVar.fadeOut();
if (someVar.next().length === 0) {
    someVar.end().find("ul").first().fadeIn();
}
else {
    someVar.next().fadeIn();
}

About eight times easier to read and maintain, IMHO.

T.J. Crowder