Collectives™ on Stack Overflow
Find centralized, trusted content and collaborate around the technologies you use most.
Learn more about Collectives
Teams
Q&A for work
Connect and share knowledge within a single location that is structured and easy to search.
Learn more about Teams
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/
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');
Updated Example
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');
–
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.