1

I have a simple HTML table and I want to insert new rows to the table with JQuery.

Each row has a custom val attribute with UNIX timestamp inside, for example:

<tr data-val="1356998400"><!-- Some row content --></tr>

I want to insert new rows with JQuery, and I want them to be sorted by val attribute after insertion.

The obviuos solution is to set id-s to rows and manually scan the rows array (performing time values comparison) before every single insertion to find the correct place to insert, but may be there is more JQuery-like solution? I guess a kind of one-line solution should exist for this case.

zavg
  • 10,351
  • 4
  • 44
  • 67
  • possible duplicate of [jQuery table sort](http://stackoverflow.com/questions/3160277/jquery-table-sort) – cfs Aug 07 '13 at 12:14
  • The val attribute is not valid. If your webpage is HTML 5 a valid attribute would be data-val – Ben Aug 07 '13 at 12:17

6 Answers6

4

Initially, you could sort the table with a basic sort function (if the rows haven't been sorted already):

Markup

(Note: Added your custom val attribute as a data attribute)

<table>
  <tbody>
    <tr data-val="1"><td>1st</td></tr>
    <tr data-val="4"><td>3rd</td></tr>
    <tr data-val="7"><td>4th</td></tr>
    <tr data-val="2"><td>2nd</td></tr>
  </tbody>
</table>

jQuery

$('table').html(function() {
  return $(this).find('tr').sort(function(a, b) {
    return $(a).data('val') > $(b).data('val');
  });
});

Once the rows have been sorted, you can easily find the position to insert the new row by grabbing the first row where its data-val is greater or equal to the data-val of the newRow:

var $newRow = $('<tr data-val="3"><td>Between 2nd and 3rd!</td></tr>');
var elementToInsertBefore = $('tr').filter(function() {
    return $(this).data('val') >= $newRow.data('val');
}).get(0);

if (typeof elementToInsertBefore === 'undefined') {
    $('table').append($newRow);  
} else {
    $newRow.insertBefore(elementToInsertBefore);
}

So, if the filter doesn't return an elementToInsertBefore (ie. there were no existing rows with a data-val greater, or equal to the $newRow's data-val, append it to the end of the table, otherwise insert it before the elementToInsertBefore.

Side Note: It'd probably be more efficient to use a for loop to get the elementToInsertBefore. That way, as soon as you find a row which meets the criteria, you can break out, which prevents further unecessary iterations (which could have a decent performance gain when dealing with a large number of rows).

If you want something more elaborate, have a look at the jQuery plugins mentioned.

Here's a fiddle

billyonecan
  • 20,090
  • 8
  • 42
  • 64
  • Awesome! this is what I was searching for! But it is not actually correct. New item should between first and second element, not between second and third. – zavg Aug 07 '13 at 12:59
  • @zavg `$newRow` has `data-val="3"`, 2nd and 3rd have `data-val's` of `2` and `4`, respectively, so it's inserting at the correct position, unless I misunderstood something? – billyonecan Aug 07 '13 at 13:04
  • The fiddle code was changed a little since the time I posted the comment, but now it is absolutely correct. The second JS-snippet in your answer is exactly what I was searching for! – zavg Aug 07 '13 at 15:13
0

Another solution: Fetch all tr elements with http://api.jquery.com/children/ (no Ids necessary) check the values and rearrange them. If they are in the right order, delete your table content and reinsert your rows.

(Isn't even necessary to clear your table and reinsert all rows. http://api.jquery.com/insertAfter/ enables you to insert a row between the correct two values if you code the right loop logic)

You can fetch all kind of attributes from your dom nodes by using http://api.jquery.com/attr/

XQDev
  • 366
  • 4
  • 15
0

i have a fork of tablesorter that allows you to write a parser that can extract data attributes from the table cell as well as assign specific textExtraction for each column.

Code :

$(function(){

  $.tablesorter.addParser({ 
    // set a unique id 
    id: 'myParser', 
    is: function(s) { 
      // return false so this parser is not auto detected 
      return false; 
    }, 
    format: function(s, table, cell, cellIndex) { 
      // get data attributes from $(cell).attr('data-something');
      // check specific column using cellIndex
      return $(cell).attr('data-something');
    }, 
    // set type, either numeric or text 
    type: 'text' 
  }); 

  $('table').tablesorter({ 
    headers : { 
      0 : { sorter: 'myParser' }
    }
  });

});
Butani Vijay
  • 4,181
  • 2
  • 29
  • 61
0

If you want to go with JQuery then there could be n no. of options Like

tablesorter, JQuery Datatable,etc.

Just see the following example.

http://tablesorter.com/docs/

Shaikh Farooque
  • 2,620
  • 1
  • 19
  • 33
0

If you want to sort based on val attribute value on each <tr>, you can use the following code.

Demo : http://jsfiddle.net/RvJ6e/

HTML Code

<table>
</table>

CSS Code

table td {
    border : 1px solid #ccc;
}

JavaScript Code

$(function() {
    //To add a new row after every 3 seconds.
    setInterval(function() {
        //I am generating a random number to demo table sorting properly.
        var val = parseInt(Math.random() * 10000);
        $('table').append('<tr val="' + val + '"><td>' + val + '</td></tr>');
        sortTable();
    }, 3000);
});

function compareRows (tr1, tr2) {
    var val1 = parseInt($(tr1).attr('val'));
    var val2 = parseInt($(tr2).attr('val'));
    return ((val1 > val2) ? 1 : ((val1 < val2) ? -1 : 0));
};

function sortTable() {
    $('table tr').sort(compareRows).appendTo('table');
}

I took many assumptions. Need to update as per your requirement.

If you want advanced level of sorting then as suggested by others, its better to depend on some jQuery plug-ins available.

Sasidhar Vanga
  • 3,384
  • 2
  • 26
  • 47
0

to sort an entire table according to the val attribute in the tr elements you may use the follwing code:

orig  = 
    $.map (
        $("tr[val]")
        , function( e, idx ) {
            return "<tr val='"+$(e).attr('val')+"'>" + $(e).html() + "</tr>";
          }
    );
sorted = orig.sort();
$("tbody").replaceWith(sorted);

this method is viable if your inserts are a bulk operation. if you need a sorted table immediately after insertion of individual elements you will need some bisection search on the array of tr elements.

have a look at the sample page.

collapsar
  • 17,010
  • 4
  • 35
  • 61