Link to home
Start Free TrialLog in
Avatar of trevor1940
trevor1940

asked on

jQuery Datatables paging

Hi
In code bellow clicking the button should move the random row to the top of the table
However it only works  if the random number is <= 10 or the paging is set to false any ideas how to fix it  

https://jsfiddle.net/493gpg5a/
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Ajax Table</title>
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
    
    <script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.3/jquery-ui.min.js"></script> 
    	<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/v/dt/dt-1.10.15/fc-3.2.2/fh-3.1.2/rr-1.2.0/sc-1.4.2/datatables.min.css"/>
 
<script type="text/javascript" src="https://cdn.datatables.net/v/dt/dt-1.10.15/fc-3.2.2/fh-3.1.2/rr-1.2.0/sc-1.4.2/datatables.min.js"></script>
	

<script type='text/javascript'>
	$(function() {
      // jQuery
      $('#example').DataTable({
            scrollY : '200px', 
            scrollCollapse: true,
            paging: true,  // set to false works
            searching: false,
            info: false
      });
       $('button').on('click', function (){
       $('tr').removeClass("highlight");        
        var ID = randomIntFromInterval(1,20);
         alert("Highlight row " + ID);
//         $("#row_" + ID).toggleClass("highlight");
      $("#row_" + ID).prependTo('#example').toggleClass('highlight');

     });
});

function randomIntFromInterval(min,max)
{
    return Math.floor(Math.random()*(max-min+1)+min);
}
</script>   
    <style>
      #MainDiv{
        width: 75%;
      }
  table.bordered {
  margin: 1em;
  border-collapse: collapse;
  border: 1px solid grey;
 width: 100%;
}

table.bordered td {
    border: 1px solid grey;
    text-align: center;
    font-size: 0.9em;
}
table.bordered th {
    border: 1px solid grey;
   background-color: lightgrey;
    text-align: center;
    font-size: 0.9em;
}

.highlight{
   background-color: yellow;

}
</style>  
</head>
  <body>

  <div id=wrap>
<button id="dummy" >Highlight Table Row</button>
   <div id=MainDiv>


<table id="example" class="bordered" width="100%" cellspacing="0">
  <thead>
    <tr>
    <th>id</th><th>city</th><th>long</th><th>lat</th><th>country_code</th><th>url</th><th>description</th>
    </tr>
  </thead>  
  <tbody>
      <tr id='row_1'><td>1</td><td>Tanjung Pandan</td><td>107.6529988</td><td>-2.7416678</td><td>ID</td><td><a href="#">Dummy Link</a></td><td>"Repair Left Lung, Via Natural or Artificial Opening Endoscopic"</td></tr>
      <tr id='row_2'><td>2</td><td>Alegria</td><td>121.0309165</td><td>14.5020933</td><td>PH</td><td><a href="#">Dummy Link</a></td><td>Fluoroscopy of Right Subclavian Vein</td></tr>
<tr id='row_3'><td>3</td><td>Dordrecht</td><td>4.6999899</td><td>51.792865</td><td>NL</td><td><a href="#">Dummy Link</a></td><td>"Revision of Internal Fixation Device in Left Scapula,External Approach"</td></tr>
<tr id='row_4'><td>4</td><td>Trinaterra</td><td>-8.5728738</td><td>41.2610181</td><td>PT</td><td><a href="#">Dummy Link</a></td><td>"Measurement of Cardiac Electrical Activity,External Approach"</td></tr>
<tr id='row_5'><td>5</td><td>Dakhla</td><td>-15.9347384</td><td>23.7221111</td><td>EH</td><td><a href="#">Dummy Link</a></td><td>"Bypass Coronary Artery,Four or More Arteries from Left Internal Mammary witd Zooplastic Tissue,Percutaneous Endoscopic Approach"</td></tr>
<tr id='row_6'><td>6</td><td>Huangzhai</td><td>119.996847</td><td>29.454189</td><td>CN</td><td><a href="#">Dummy Link</a></td><td>"Lower Joints,Fusion"</td></tr>
<tr id='row_7'><td>7</td><td>Zhufo</td><td>120.047429</td><td>30.379545</td><td>CN</td><td><a href="#">Dummy Link</a></td><td>"Revision of Infusion Device in Left Metatarsal-Tarsal Joint,Open Approach"</td></tr>
<tr id='row_8'><td>8</td><td>Rengo</td><td>-70.8674411</td><td>-34.4023791</td><td>CL</td><td><a href="#">Dummy Link</a></td><td>Beam Radiation of Lung using Neutron Capture</td></tr>
<tr id='row_9'><td>9</td><td>Ejido</td><td>-71.2428737</td><td>8.5493413</td><td>VE</td><td><a href="#">Dummy Link</a></td><td>"Removal of Infusion Device from Left Metacarpophalangeal Joint,Percutaneous Endoscopic Approach"</td></tr>
<tr id='row_10'><td>10</td><td>Xiaozhen</td><td>115.264971</td><td>24.690585</td><td>CN</td><td><a href="#">Dummy Link</a></td><td>"Restriction of Right Brachial Vein,Percutaneous Endoscopic Approach"</td></tr>
<tr id='row_11'><td>11</td><td>S�o Paio de Seide</td><td>-8.4737713</td><td>41.399671</td><td>PT</td><td><a href="#">Dummy Link</a></td><td>"Bypass Coronary Artery,tdree Arteries from Coronary Artery witd Syntdetic Substitute,Open Approach"</td></tr>
<tr id='row_12'><td>12</td><td>Huangshi</td><td>115.038835</td><td>30.20003</td><td>CN</td><td><a href="#">Dummy Link</a></td><td>"Restriction of Cecum,Percutaneous Endoscopic Approach"</td></tr>
<tr id='row_13'><td>13</td><td>Xilinji</td><td>122.539307</td><td>52.969667</td><td>CN</td><td><a href="#">Dummy Link</a></td><td>"Dilation of Left Renal Artery witd Two Drug-eluting Intraluminal Devices,Percutaneous Approach"</td></tr>
<tr id='row_14'><td>14</td><td>Wanghu</td><td>116.244678</td><td>30.661419</td><td>CN</td><td><a href="#">Dummy Link</a></td><td>"Removal of Syntdetic Substitute from Right Tibia, Percutaneous Approach"</td></tr>
<tr id='row_15'><td>15</td><td>Xufeng</td><td>113.8146974</td><td>23.0594685</td><td>CN</td><td><a href="#">Dummy Link</a></td><td>"Bypass Pancreatic Duct to Small Intestine witd Intraluminal Device,Open Approach"</td></tr>
<tr id='row_16'><td>16</td><td>La Asunci�n</td><td>-63.8581485</td><td>11.028458</td><td>VE</td><td><a href="#">Dummy Link</a></td><td>"Beam Radiation of Bladder using Heavy Particles (ProtonsIons)"</td></tr>
<tr id='row_17'><td>17</td><td>Mar del Plata</td><td>-57.5823273</td><td>-38.0667198</td><td>AR</td><td><a href="#">Dummy Link</a></td><td>Computerized Tomography (CT Scan) of Left Patella</td></tr>
<tr id='row_18'><td>18</td><td>Hongxingqiao</td><td>119.839212</td><td>34.007974</td><td>CN</td><td><a href="#">Dummy Link</a></td><td>"Release Splenic Artery, Percutaneous Approach"</td></tr>
<tr id='row_19'><td>19</td><td>Xinxing</td><td>112.225334</td><td>22.69569</td><td>CN</td><td><a href="#">Dummy Link</a></td><td>"Drainage of Right Inguinal Region,Percutaneous Approach"</td></tr>
<tr id='row_20'><td>20</td><td>Binawara</td><td>115.7782286</td><td>-3.4795532</td><td>ID</td><td><a href="#">Dummy Link</a></td><td>"Bypass Abdominal Aorta to Right Common Iliac Artery witd Autologous Venous Tissue,Open Approach"</td></tr>
</tbody>
<tfoot>
  
    <tr>
    <th>id</th><th>city</th><th>long</th><th>lat</th><th>country_code</th><th>url</th><th>description</th>
    </tr>
</tfoot>  

</table>

    </div>
    <div id=footer>
    </div>
   </div>
  </body>
</html>

Open in new window

Avatar of HainKurt
HainKurt
Flag of Canada image

it does not work this way, because your data is sorted initially...
removing one row and putting on top does not mean anything...
when it is sorted, it will go back to original location...

first you need to set

bSort = false
ok, I made a demo for you...

https://jsfiddle.net/bykf4zy7/

I used scroller plugin and added highlighing + scrolling

have a look at this demo...
you can find a nice solution using this and your initial code...
The row is not on the page, so attempting to target it using $("#row_" + ID) isn't going to work.  You need to use DataTables itself to find the row.  I believe you'll be able to do this using row().node().

Once you have the row, you can add or remove the class.
Avatar of trevor1940
trevor1940

ASKER

FYI.
This is just a simulation but the  user will be clicking on a map marker and the corresponding table row gets highlighted
There is too much info to be shown in a popup

It doesn't matter or small datasets like this but when your talking  large data sets  over many pages

@HainKurt
when it is sorted, it will go back to original location...

Do you mean when the user clicks a column heading? If so then it won't matter they will have already got what they need

The demo works but its on 1 page?

@zephyr_hex (Megan)

Is this what you mean?  it seems to work without the extra plugin

https://jsfiddle.net/493gpg5a/1/  the row moves to the top and the highlight class is added not sure why background-color doesn't turn  yellow;?

<script type='text/javascript'>
	$(function() {
      // jQuery
      var myTable = $('#example').DataTable({
            scrollY : '200px', 
            scrollCollapse: true,
//            bSort: false, 
            paging: true,  // set to false works
            searching: false,
            info: false
      });
       $('button').on('click', function (){
       $('tr').removeClass("highlight");        
        var ID = randomIntFromInterval(10,20);
         alert("Highlight row " + ID);
//         $("#row_" + ID).toggleClass("highlight");
//      $("#row_" + ID).prependTo('#example').toggleClass('highlight');
var row = myTable
    .row( "#row_" + ID)
    .node();
 
$(row).addClass( 'highlight' ).prependTo('#example');
     });
});

function randomIntFromInterval(min,max)
{
    return Math.floor(Math.random()*(max-min+1)+min);
}
</script>   

Open in new window

when the rows are sorted by default, you cannot remove/add rows and expect them non sorted!

you can remove, and after adding a new row, it will be sorted and you will see no change!

so, best thing you can do is add "scroller" plugin and use scrollTo method...
@HainKurt
so, best thing you can do is add "scroller" plugin and use scrollTo method...

Understood but your demo is displaying the whole table  on a single page I really need multiple pages
ok, without scrolling / adding or removing, you can use filtering!!!

https://jsfiddle.net/vpgeLzy8/

check this one...

and also no highlight required!
and here, I added another button to clear filter...

https://jsfiddle.net/3c4m3qbp/
There is no need for an extra plugin.  Just use the regular DataTables methods, like row().node(), as you've done here:

var row = myTable
    .row( "#row_" + ID)
    .node();

Open in new window


If the background color doesn't respond to the new class, my guess is that you need to redraw the datatable using draw()
If the background color doesn't respond to the new class, my guess is that you need to redraw the datatable using draw()

nope, no need to redraw

.highlight{
   background-color: yellow!important;
}

Open in new window


will do the job
There is no need for an extra plugin.

new row added to the top is not visible this way, unless we do manually scroll up...

that's why I suggested using filter or scrolling plugin...
if you want to jump the page to the top, you can do that with jquery.  as i said... a plugin isn't necessary.  and it doesn't answer the OP's original question, which is how to move the row (and add or remove a class) when there is more than 1 page in the datatable.
@Megan

if you are working with dataTable, it is better not to touch the elements directly like that, but use underlying data provided by API
like search, filter, scrollTo etc...

this way it ruins the purpose of dataTable
Hi I haven't managed to get this to  work because in this demo the click event is a button totally separate from creating the Datatable

Where as in the actual app the click event is a openlayers 2 marker object these are created during the  Datatable ajax function  something like bellow so this code or versions there of don't  as I'm already on the row

var row = myTable
    .row( "#row_" + ID)
    .node();

Open in new window


function GetPoints(Long, Lat) {
  console.log('3');
  //alert("long " + Long + " Lat " + Lat);
  
           var link = "Mock_data.json";
          //          $('#MainTable tbody').html(table);
          var arr=[];
          
         $('#dTable').DataTable({
//           $('#dTable').ajax.reload(),
    "columns": [{ "data": "id" }, { "data": "name" }, { "data": "Lat" }, { "data": "Long" }, {"data": "country_code"},{ "data": "url" }, { "data": "description" }],
    "ajax": {
        "url": link,
        "dataSrc" : function (json) {
            $.each(json, function(i, item) {
                item.id = item.id;// * 2;
                item.name = item.name.toUpperCase();
                item.url = '<a href="' + item.url + '" onclick="return false;">Dummy</a>';
                console.log(item.id + " Long Lat " + item.Long + ', ' + item.Lat);

    // make new marker obbject with BlueIcon else its red
                var mkr = new OpenLayers.Marker(new OpenLayers.LonLat(item.Long, item.Lat).transform(
                    new OpenLayers.Projection("EPSG:4326"),
                    map.getProjectionObject()
                ), BlueIcon.clone());
                console.log(fromProjection, toProjection);
                    mkr.custData = item;
                mkr.events.register("click", mkr, function(e, i) {
                  $(".olPopup").each(function(){
                    map.removePopup(map.popups[0]);
                  });
                  console.log("click");
                  $('#result').html(JSON.stringify(this.custData));
                  var  ID =   this.custData.id;
///////  this is where the code to highlight the row goes  
                  $("#row_" + ID).prependTo('#dTable').toggleClass('highlight');
                  popup = new OpenLayers.Popup.FramedCloud("chicken",
                    this.lonlat,
                    new OpenLayers.Size(200, 200),
                    "<h2>" + this.custData.name + "</h2><p>" + this.custData.url + "</p>",
                    null, true);
                  map.addPopup(popup);
                });  // end mkr click
                console.log(mkr); // 10 mkr objects in console
//                Add mkr to map
                searchLayer.addMarker(mkr);
            });

            return json;
        },
    },
     
    "fnRowCallback": function(nRow, aData, iDisplayIndex) {
        // aData is the JSON for each row, so you can access the properties, such as  aData.Long, aData.id
        var rowId = "row_" + aData.id; 
        nRow.setAttribute('id',rowId);
    },
    
    scrollY : '200px', 
    scrollCollapse: true,
    paging: false,
    searching: false,
    info: true,
    "bDestroy": true
        });
}// End gGetPoints
     

Open in new window

@Hain - my point is that scrolling has nothing to do with the OP's question.
@trevor1940:  I still see this in your code

 $("#row_" + ID).prependTo('#dTable').toggleClass('highlight');

Open in new window


I would expect to see this instead:

Line 9 of your code, do this:
 var dt = $('#dTable').DataTable({

Open in new window



then, line 36, do:
var row = dt.row( "#row_" + ID).node();
$(row).prependTo('table').toggleClass('highlight');

Open in new window


Here is a Demo:  https://jsfiddle.net/zephyr_hex/rhgL0294/18/

It shouldn't matter that the demo has a button, while your app uses a marker.  You have a click event bound to the marker, and the row ordering code is inside that click event function, so it should trigger when the marker is clicked.  To verify, you could use console.log() inside your click function, and check your browser's development console using F12.  So, for example, you could do:

var row = dt.row( "#row_" + ID).node();
console.log(row);
$(row).prependTo('table').toggleClass('highlight');

Open in new window


so, your modified code would be:

function GetPoints(Long, Lat) {
  console.log('3');
  //alert("long " + Long + " Lat " + Lat);
  
           var link = "Mock_data.json";
          //          $('#MainTable tbody').html(table);
          var arr=[];
          
         var dt = $('#dTable').DataTable({
//           $('#dTable').ajax.reload(),
    "columns": [{ "data": "id" }, { "data": "name" }, { "data": "Lat" }, { "data": "Long" }, {"data": "country_code"},{ "data": "url" }, { "data": "description" }],
    "ajax": {
        "url": link,
        "dataSrc" : function (json) {
            $.each(json, function(i, item) {
                item.id = item.id;// * 2;
                item.name = item.name.toUpperCase();
                item.url = '<a href="' + item.url + '" onclick="return false;">Dummy</a>';
                console.log(item.id + " Long Lat " + item.Long + ', ' + item.Lat);

    // make new marker obbject with BlueIcon else its red
                var mkr = new OpenLayers.Marker(new OpenLayers.LonLat(item.Long, item.Lat).transform(
                    new OpenLayers.Projection("EPSG:4326"),
                    map.getProjectionObject()
                ), BlueIcon.clone());
                console.log(fromProjection, toProjection);
                    mkr.custData = item;
                mkr.events.register("click", mkr, function(e, i) {
                  $(".olPopup").each(function(){
                    map.removePopup(map.popups[0]);
                  });
                  console.log("click");
                  $('#result').html(JSON.stringify(this.custData));
                  var  ID =   this.custData.id;
///////  this is where the code to highlight the row goes  
                  var row = dt.row( "#row_" + ID).node();
				  console.log(row); //you should see the row HTML in F12 console after clicking a marker
				  $(row).prependTo('table').toggleClass('highlight');
                  popup = new OpenLayers.Popup.FramedCloud("chicken",
                    this.lonlat,
                    new OpenLayers.Size(200, 200),
                    "<h2>" + this.custData.name + "</h2><p>" + this.custData.url + "</p>",
                    null, true);
                  map.addPopup(popup);
                });  // end mkr click
                console.log(mkr); // 10 mkr objects in console
//                Add mkr to map
                searchLayer.addMarker(mkr);
            });

            return json;
        },
    },
     
    "fnRowCallback": function(nRow, aData, iDisplayIndex) {
        // aData is the JSON for each row, so you can access the properties, such as  aData.Long, aData.id
        var rowId = "row_" + aData.id; 
        nRow.setAttribute('id',rowId);
    },
    
    scrollY : '200px', 
    scrollCollapse: true,
    paging: false,
    searching: false,
    info: true,
    "bDestroy": true
        });
}// End gGetPoints

Open in new window

@zephyr_hex (Megan)

That's basically what I've ended up doing  Why is
var dt = $('#dTable').DataTable({

Open in new window

 a good thing to do?

The filtering that @HainKurt sugested here ID: 42298897 https://jsfiddle.net/3c4m3qbp/ although the customer liked this option  bloke  the script
@zephyr_hex (Megan)

This breaks the script
var dt = $('#dTable').DataTable({

Open in new window


at line 36

I thing because dt hasn't finished before trying to access it

var dt = $('#dTable').DataTable({
// ... more code
// line 36, do:
var row = dt.row( "#row_" + ID).node();
$(row).prependTo('table').toggleClass('highlight');

});// end dt

Open in new window


Where as on your demo the dt is created / exists outside the click event

this Also fails with error "$('#dTable').row is not a function)" on clicking a marker

var row = $('#dTable').row( "#row_" + ID).node();
$(row).prependTo('table').toggleClass('highlight');
or

$(row).prependTo('#dTable').toggleClass('highlight');

Open in new window


This works
 $("#row_" + ID).prependTo('#dTable').toggleClass('highlight');

Open in new window

 $("#row_" + ID)

Open in new window


That will ONLY work for rows on the page.  If you want rows that are not showing on the page, you MUST use DataTables row().node() to get the row.

What I was attempting to do here was capture the instantiated datatable to a variable, so that you could refer to "dt" later on:
var dt = $('#dTable').DataTable({

Open in new window


If that doesn't work in your scenario, then reference the datatable directly, like so:

var row = $('#dTable').DataTable().row("#row_7").node();
$(row).prependTo('#dTable').toggleClass('highlight');

Open in new window


Here's an updated Fiddle: https://jsfiddle.net/zephyr_hex/rhgL0294/19/
Sorry @zephyr_hex (Megan) but I can't get your suggestion to work

Here's a https://jsfiddle.net/vzmq1jvL/

Am I missing something?

PS. It takes a while to load
I don't see where you're referencing DataTables in that demo.  Nor do I see a table ?
Deeply sorry @zephyr_hex (Megan) I attached the wrong fiddle

Here is the correct one https://jsfiddle.net/jwhkdy6r/1/

This has 30 points the 1 in South Africa has ID of 25
How do I get the datatable to show?
The reason why I'm asking is because it seems like you have a "chicken, egg" dilemma, where you're trying to move a row on a datatable that doesn't yet have rows.  But maybe I'm misunderstanding how / when the datatable is supposed to show.
How do I get the datatable to show?

Click anywhere on the map should place a red marker this grabs the Long and Lat and sends it to function GetPoints(Long, Lat) line 88 which performs an ajax call and builds the DataTable

In this I'm just using mock data so it doesn't matter where you click

if that dosn't work for you try  this https://jsfiddle.net/jwhkdy6r/2/ I've overridden the click so the datatables is loaded automatically

After the search is performed there will be 30 blue markers on the map and 30 rows in the table

click on one off those should move the connected  row to the top of the Datatable but doesn't

Hope that makes sense?
OK, I went with version 1 of your fiddle and added some console logs so I could see what's going on.

First, I added a console log to the row call back function:
    "fnRowCallback": function(nRow, aData, iDisplayIndex) {
        // aData is the JSON for each row, so you can access the properties, such as  aData.Long, aData.name, aData.url, aData.id
        var rowId = "row_" + aData.id; 
        nRow.setAttribute('id',rowId);
        console.log(nRow);
    },

Open in new window


What I saw is that only 10 rows are shown in the log:
User generated image
I also added a console log to verify there are 30 rows in your datatable (as you said).

That means that not all of the rows are getting an id.  Just the first 10.
So, you need to assign that id to your rows somewhere other than the row callback because that seems to only run on the rows being displayed.  I confirmed that assumption here.
For each row that is generated for display, the fnRowCallback() function is called

I believe you could use fnCreatedRow instead, but both fnCreatedRow and fnRowCallback are LEGACY functions. The current syntax is createdRow() : https://datatables.net/reference/option/createdRow
I changed the code to this
    "createdRow": function(nRow, aData, iDisplayIndex) {
        // aData is the JSON for each row, so you can access the properties, such as  aData.Long, aData.name, aData.url, aData.id
        var rowId = "row_" + aData.id; 
        nRow.setAttribute('id',rowId);
        console.log(nRow);
    },
    

Open in new window


Each row appears in the console log

So when I click a blue marker why doesn't the corresponding table row jump to the top?

https://jsfiddle.net/jwhkdy6r/5/
I say, either use scrollTo plugin or filter plugin of DataTable...

removing row from html and inserting it on top requires destroying and re initialize of datatable...
adding a row always add row to bottom... this may work if you do not use sort option
and after each operation you need to call "draw()" function...

or, dont play with table or datatble but clone that row and, display on top of your datatable in a separate table/div

this way, you can use sort/search of your datatable and you do not touch datatable at all..
on every click, get the row, and data of that row, then for each data, set to div for display purpose...
ASKER CERTIFIED SOLUTION
Avatar of zephyr_hex (Megan)
zephyr_hex (Megan)
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
for selected class, just use this

                    $('#dTable tr').removeClass('highlight');
                    $(row).prependTo('#dTable').addClass('highlight');

Open in new window


* based on solution proposed by Megan

https://jsfiddle.net/0mpckL4e/
@zephyr_hex (Megan) that was a silly typo on my behalf missing  referencing the row ID.

You should consider removing the highlight class from the previous row before applying  it to the new row

Yep in the actual script I'm doing that

In fear of taking the .........
How do  I remove the row these fail?

                    var row = $('#dTable').DataTable().row("#row_" + ID).node();
                    $('#dTable').DataTable().remove(row).draw( false );
//        fails    $(row).remove().draw( false );
                    $(row).prependTo('#dTable').toggleClass('highlight');

Open in new window

SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Not really sure who gets the points zephyr_hex (Megan) solution worked but HainKurt helped

Picked last 2

Hope this is OK

Thank you for your help I've learnt a lot