Reputation: 10852
I am trying to write a jQuery selector to select a range of table cells (minRow, minCol) to (maxRow, maxCol).
I have a selector that works for a horizontal range (col 1, row 2) to (col 3, row 2)
$('tr:lt(3):gt(1) td:lt(4):gt(0))')
But this fails for the corresponding vertical range (col 2, row 1) to (col 2, row 3)
$('tr:lt(4):gt(0) td:lt(3):gt(1)')
because the td selector won't loop over the row, it will just take the first one
This version using map and each works
$('tr:lt(4):gt(0)').map( function() { return $(this).find('td:lt(3):gt(1)') } ).each( function() { /* this.do_something */ } );
but is even uglier
Is there an elegant way to achieve this?
Bonus points for finding a more elegant range selector than :lt():gt()
Examples of the above horizontal and vertical ranges and a block range are at this fiddle http://jsfiddle.net/jghaines/qeLhgw4f/4/
Upvotes: 3
Views: 1757
Reputation: 240928
The selector tr:lt(3):gt(1) td:lt(4):gt(0)
only works because a single row is being selected. What's happening is tr:lt(3):gt(1)
will return a set of td
elements in row 3, and td:lt(4):gt(0)
will select the second, third, and fourth td
elements by their index in that specific set.
When you use a selector like tr:lt(4):gt(0) td:lt(3):gt(1)
, multiple rows are selected and the selectors are compounded relative to the set that is returned (rather than each individual td
element). The selector tr:lt(4):gt(0)
returns a set consisting of the second, third, and fourth rows. Based on this returned set, the selector td:lt(3):gt(1)
will select the third td
element by its index in that specific set.
In other words, the :gt()
/:lt()
selectors will select all elements at an index greater than or less than an index within the matched set. Your selectors weren't working as expected because the elements were being selected based on the matched set (rather than each individual td
element).
The solution would be to chain a .find()
method between tr:lt(4):gt(0)
/td:lt(3):gt(1)
.
In other words, replace:
$('table#2 tr:lt(4):gt(0) td:lt(3):gt(1)').addClass('red');
With:
$('table#2 tr:lt(4):gt(0)').find('td:lt(3):gt(1)').addClass('red');
Since you wanted an alternative to combining :lt():gt()
, it's worth pointing out that you can use the .slice()
method:
For instance, you could replace:
$('table#2 tr:lt(4):gt(0) td:lt(3):gt(1)').addClass('red');
With:
$('table#2 tr').slice(1, 4).find('td:lt(3):gt(1)').addClass('red');
Upvotes: 3