views:

217

answers:

2

This is related to my previous question about selecting visible elements. Now, here's the twist: Let's say I want to select the odd children only from the set of visible children of an element. What would be the best way to do this?

Edit: here is an example of my input and expected output.

<!-- A list with some visible and invisible children -->
<ul class="stripe">
    <li>Visible 1</li>
    <li style="display:none;">Visible 2</li>
    <li style="display:none;">Visible 3</li>
    <li>Visible 4</li>
    <li style="display:none;">Visible 5</li>
    <li>Visible 6</li>
    <li>Visible 7</li>
</ul>

<!-- Only the visible children. -->
<li>Visible 1</li>
<li>Visible 4</li>
<li>Visible 6</li>
<li>Visible 7</li>

<!-- The "odd" visible children. -->
<li>Visible 1</li>
<li>Visible 6</li>

I came up with two ways. One works, but the other doesn't.

// Method one: Returns the odd children whether they are visible or not. :(
var listChildren = $$("ul.stripe > li");
var oddChildren = allChildren
  .findAll(function(el) { return el.visible(); })
    .findAll(function(el) { return el.match("li:nth-child(odd)"); });
oddChildren.invoke("addClassName", "odd");

What I am currently doing now is the following:

// Method two: grouping!
var listChildren = $$("ul.stripe > li");
var oddChildren = listChildren
  .findAll(function(el) { return el.visible(); })
    .eachSlice(2, function(el) {
      el[0].addClassName("odd");    
    });

This code seems like it could be improved. Can anyone suggest a better way to accomplish this?

A: 

Can't you merge the two conditions like this?

var listChildren = $$("ul.stripe > li");
var oddChildren = allChildren
  .findAll(function(el) { return el.visible() && el.match("li:nth-child(odd)"); })
oddChildren.invoke("addClassName", "odd");
varzan
Yes. However, the problem is that I want to select the visible elements first, and then from *those* select the "odd" elements. The problem with this (any with my chained findAll version) is that the elements "oddness" is being tested outside of that "visible" subset of children.
Zack Mulgrew
+1  A: 

The CSS select won't work for the application you desire, it doesn't work correctly on an Array outside of the context of the DOM.

You can do this as follows:

var index = 0;
var myChildren = $$("ul.stripe > li")
    .select(function(e) { return e.visible(); })
    .select(function(e) {return ++index % 2 == 1; });
hobodave
This code made it to production!
Zack Mulgrew
Great to hear Zack :)
hobodave