wesbos
wesbos

Reputation: 26317

jQuery Value greater than the 6th element?

I have some data in a table that looks like this:

Adam    $50
Evan    $20
Frank   $80
Harold  $90
Jeff    $20
Linus   $10
Sam     $87
Zach    $100

Results are sorted by name alphabetically and can have any amount of $ beside them.

I need to make the top five amounts bold and red as well as append a #1, #2, #3 etc beside the first five names.

Can jQuery do this without sorting by the $ column?

Upvotes: 0

Views: 225

Answers (3)

Yanick Rochon
Yanick Rochon

Reputation: 53576

Not directly, this is too concrete to be handled by an abstract framework layer. However, you can accomplish this fairly easily. For a table like :

<table id="table_id">
   <tr><th class="rank"></th><th class="name">Name</th><th class="amount">Amount</th></tr>

   <tr><td></td><td>Adam</td><td>$50</td></tr>
   <tr><td></td><td>Evan</td><td>$20</td></tr>
   <tr><td></td><td>Frank</td><td>$80</td></tr>
   <tr><td></td><td>Harold</td><td>$90</td></tr>
   <tr><td></td><td>Jeff</td><td>$20</td></tr>
   <tr><td></td><td>Linus</td><td>$10</td></tr>
   <tr><td></td><td>Sam</td><td>$87</td></tr>
   <tr><td></td><td>Zach</td><td>$100</td></tr>
</table>

You can do :

var top = 5;  // apply only transformation to the top n rows
var rankCol, nameCol, amountCol;

$('#table_id').find('tr')
   // get first row and find where are the name and amount columns...
   .slice(0, 1).each(function(i,row) {
      rankCol = $(row).find('.rank').index();
      nameCol = $(row).find('.name').index();
      amountCol = $(row).find('.amount').index();
   }).end()
   // remove first row
   .slice(1)
   // sort returned set by 'amount' in ascending order
   .sort(function(a,b) {
      return parseFloat($(a).find('td:eq('+amountCol+')').text().substr(1)) - parseFloat($(b).find('td:eq('+amountCol+')').text().substr(1));
   })
   // get the last 'top' rows
   .slice(-top)
   // apply bold + red to column 'amount'
   .find('td:eq('+amountCol+')').css({'font-weight':'bold', 'color':'red'}).end()
   // prepend #n to column 'rank'
   .find('td:eq('+rankCol+')').each(function(i,col) {
      $(col).text('#'+(top-i)+'. ');
   })
;

The code was organized for readability, but also so you can see how JQuery can apply a reusable pattern to chain up the calls on your results. If your table layout is different, for example you have 5 columns and "amount" is in the 5th, then the code will still work without modification, all you need is to set some class name to your "name" and "amount" columns and look for that class in the first row.

** EDIT ** I also added a reserved column to put the rank's text. This render nameCol obsolete, but I kept it in the code anyway. Having such a reserved column aligns everything beautifully. :) The number of top rows are now variable based. ... I could still play with the code to make it even more flexible / reusable, but I think you get the point.

** NOTE ** you could replace the css() call with addClass() instead that will define bold + red. You could even replace the prepend(string) call with a prepend(element) instead so you can actually style the "#n" before the name.

Upvotes: 1

Ken Redler
Ken Redler

Reputation: 23943

Here's another approach.

var arr = $('#mytable').find('td:last-child')
  .map( function(){
    var cleanval = parseInt( $(this).text().replace('$',''),10 );
    $(this).addClass('s_'+cleanval);
    return cleanval;
  })
  .get()
  .sort( function(a,b){ return (b-a); } )
  .slice(4);

for( var i=0,j=arr.length;i<j;i++ ) {
    $('td.s_'+arr[i]).addClass('colorize');
}

​ Here's a working fiddle.

Upvotes: 0

Matt Ball
Matt Ball

Reputation: 359956

$(function ()
{
    var i = 5,
        values = $('#myTable').find('td:odd').map(function (i, elt)
                 {
                     var $elt = $(elt);
                     return {$td: $elt,
                             value: parseFloat($elt.text().slice(1))};
                 }).get().sort(function (a,b)
                 {
                    return b.value-a.value;
                 });

    while(i--)
    {
        values[i].$td.css({fontWeight: 'bold', color: '#F00'})
                     .prev().append(' #' + (i+1));
    }
});

Functioning demo: http://jsbin.com/iseme3/7

Feel free to ask about anything in there you don't understand.

Upvotes: 4

Related Questions