Add background color dynamically to even row groups

Viewed 73

I have code as follows:

$(document).ready(function() {
    $('#example').DataTable({
        "bLengthChange" : false,
      "paging": false,
      "bFilter": false,
      "columnDefs": [ {
        "targets"  : 'no-sort',
        "orderable": false,
      }],
      "order": []
    });
    
    $('#example th').click(function(e) {
      let clicked_col_class = $(this).attr('class');
        if(clicked_col_class.includes('office')){
          $('#example tbody tr.xbg-dark-grey').removeClass('xbg-dark-grey').addClass('bg-dark-grey');
        }else{
          $('#example tbody tr.bg-dark-grey').removeClass('bg-dark-grey').addClass('xbg-dark-grey');
        }
    });
} );
.bg-dark-grey{
  background-color: rgba(0,0,0,.05) !important;
}
.bg-white{
  background-color: #ffffff !important;
}
<link rel="stylesheet" href="https://cdn.datatables.net/1.10.22/css/jquery.dataTables.min.css">
<table id="example" class="xdisplay" style="width:100%">
        <thead>
            <tr>
                <th class="no-sort">Name</th>
                <th class="no-sort">Position</th>
                <th class="office">Office</th>
                <th>Age</th>
                <th class="no-sort">Start date</th>
                <th>Salary</th>
            </tr>
        </thead>
        <tbody>
            <tr class="bg-white">
              <td>Tiger Nixon</td>
              <td>System Architect</td>
              <td>Edinburgh</td>
              <td>61</td>
              <td>2011/04/25</td>
              <td>$320,800</td>
          </tr>
          <tr class="bg-white">
              <td>Quinn Flynn</td>
              <td>Support Lead</td>
              <td>Edinburgh</td>
              <td>22</td>
              <td>2013/03/03</td>
              <td>$342,000</td>
          </tr>
          <tr class="bg-white">
              <td>Cedric Kelly</td>
              <td>Senior Javascript Developer</td>
              <td>Edinburgh</td>
              <td>22</td>
              <td>2012/03/29</td>
              <td>$433,060</td>
          </tr>
          <tr class="bg-white">
              <td>Sonya Frost</td>
              <td>Software Engineer</td>
              <td>Edinburgh</td>
              <td>23</td>
              <td>2008/12/13</td>
              <td>$103,600</td>
          </tr>
          <tr class="bg-dark-grey">
              <td>Ashton Cox</td>
              <td>Junior Technical Author</td>
              <td>San Francisco</td>
              <td>66</td>
              <td>2009/01/12</td>
              <td>$86,000</td>
          </tr>
          <tr class="bg-dark-grey">
              <td>Herrod Chandler</td>
              <td>Sales Assistant</td>
              <td>San Francisco</td>
              <td>59</td>
              <td>2012/08/06</td>
              <td>$137,500</td>
          </tr>
          <tr class="bg-white">
              <td>Garrett Winters</td>
              <td>Accountant</td>
              <td>Tokyo</td>
              <td>63</td>
              <td>2011/07/25</td>
              <td>$170,750</td>
          </tr>
          <tr class="bg-white">
              <td>Airi Satou</td>
              <td>Accountant</td>
              <td>Tokyo</td>
              <td>33</td>
              <td>2008/11/28</td>
              <td>$162,700</td>
          </tr>
          <tr class="bg-white">
              <td>Rhona Davidson</td>
              <td>Integration Specialist</td>
              <td>Tokyo</td>
              <td>55</td>
              <td>2010/10/14</td>
              <td>$327,900</td>
          </tr>
          <tr class="bg-dark-grey">
              <td>Brielle Williamson</td>
              <td>Integration Specialist</td>
              <td>New York</td>
              <td>61</td>
              <td>2012/12/02</td>
              <td>$372,000</td>
          </tr>
          <tr class="bg-dark-grey">
              <td>Paul Byrd</td>
              <td>Chief Financial Officer (CFO)</td>
              <td>New York</td>
              <td>64</td>
              <td>2010/06/09</td>
              <td>$725,000</td>
          </tr>
          <tr class="bg-dark-grey">
              <td>Gloria Little</td>
              <td>Systems Administrator</td>
              <td>New York</td>
              <td>59</td>
              <td>2009/04/10</td>
              <td>$237,500</td>
          </tr>
          <tr class="bg-white">
              <td>Jena Gaines</td>
              <td>Office Manager</td>
              <td>London</td>
              <td>30</td>
              <td>2008/12/19</td>
              <td>$90,560</td>
          </tr>
          <tr class="bg-white">
              <td>Haley Kennedy</td>
              <td>Senior Marketing Designer</td>
              <td>London</td>
              <td>43</td>
              <td>2012/12/18</td>
              <td>$313,500</td>
          </tr>
          <tr class="bg-white">
              <td>Tatyana Fitzpatrick</td>
              <td>Regional Director</td>
              <td>London</td>
              <td>19</td>
              <td>2010/03/17</td>
              <td>$385,750</td>
          </tr>
          <tr class="bg-white">
              <td>Michael Silva</td>
              <td>Marketing Designer</td>
              <td>London</td>
              <td>66</td>
              <td>2012/11/27</td>
              <td>$198,500</td>
          </tr>
          <tr class="bg-white">
              <td>Bradley Greer</td>
              <td>Software Engineer</td>
              <td>London</td>
              <td>41</td>
              <td>2012/10/13</td>
              <td>$132,000</td>
          </tr>
        </tbody>
    </table>
    <script src="https://code.jquery.com/jquery-3.5.1.js"></script>
    <script src="https://cdn.datatables.net/1.10.22/js/jquery.dataTables.min.js"></script>

Here, I have used tr class bg-white and bg-dark-grey manually. However, in real case scenario there is a simple logic on php. It is something like

$bg_class = '';
foreach($data as $dv){
    if($old_office != $dv->office){
        if($bg_class == 'bg-white'){
            $bg_class = 'bg-dark-grey';
        }else{
            $bg_class = 'bg-white';
        }
        $old_office = $dv->office;
    }
}

However, you can ignore this php logic just remember that initially on even row group of office there will be background: dark-grey. On this initial scenario: San Francisco and New York will have a background as they are even row (office) group.

Edinburgh
San Francisco //even (bg-grey)
Tokyo
New York //even (bg-grey)
London

For ordering other than the office column none of the rows will the background and I have already implemented logic for that one. But, whenever I tried sorting with the office column. Let's consider sorting_asc condition:

Edinburgh
London
New York //(bg-grey)
San Francisco //(bg-grey)
Tokyo

In this case scenario, wrong row groups are having a background. As it is a client side datatable, php logic won't be executing again. So, I need some help so that I could add bacground to correct group whenever it is sorted based on office column. So my desired result are:

##For sorting_asc (office column)

Edinburgh
Edinburgh
Edinburgh
Edinburgh
London //desired-grey-row
London //desired-grey-row
London //desired-grey-row
London //desired-grey-row
London //desired-grey-row
New York 
New York 
New York 
San Francisco //desired-grey-row
San Francisco //desired-grey-row
Tokyo
Tokyo
Tokyo

##For sorting_desc (office column) (consider group not single row)

Tokyo
San Francisco //desired-grey-row
New York 
London //desired-grey-row
Edinburgh

i.e every even group row needs to have a grey background.

1 Answers

OK - this is a javascript way to highlight alternating office rows:

function highlightRows() {
  let t = document.getElementById("example");
  let tbody = t.getElementsByTagName("tbody")[0];
  let lastoffice = "";
  let lastclass = "bg-dark-grey";
  for (let r = 0; r < tbody.rows.length; r++) {
    let thisrow = tbody.rows[r];
    let thisoffice = thisrow.cells[2].innerHTML;
    if (thisoffice != lastoffice) {
      lastclass = (lastclass == "bg-dark-grey")? "bg-white": "bg-dark-grey";
      lastoffice = thisoffice;
      thisrow.className = lastclass;
    } else {
      thisrow.className = lastclass;
    }
  
  }
}

// for testing purposes only
window.onload = highlightRows;
.bg-dark-grey{
  background-color: rgba(0,0,0,.05) !important;
}
.bg-white{
  background-color: #ffffff !important;
}
<table id="example" class="xdisplay" style="width:100%">
  <thead>
      <tr>
          <th class="no-sort">Name</th>
          <th class="no-sort">Position</th>
          <th class="office">Office</th>
          <th>Age</th>
          <th class="no-sort">Start date</th>
          <th>Salary</th>
      </tr>
  </thead>
  <tbody>
      <tr class="bg-white">
        <td>Tiger Nixon</td>
        <td>System Architect</td>
        <td>Edinburgh</td>
        <td>61</td>
        <td>2011/04/25</td>
        <td>$320,800</td>
    </tr>
    <tr class="bg-white">
        <td>Quinn Flynn</td>
        <td>Support Lead</td>
        <td>Edinburgh</td>
        <td>22</td>
        <td>2013/03/03</td>
        <td>$342,000</td>
    </tr>
    <tr class="bg-white">
        <td>Cedric Kelly</td>
        <td>Senior Javascript Developer</td>
        <td>Edinburgh</td>
        <td>22</td>
        <td>2012/03/29</td>
        <td>$433,060</td>
    </tr>
    <tr class="bg-white">
        <td>Sonya Frost</td>
        <td>Software Engineer</td>
        <td>Edinburgh</td>
        <td>23</td>
        <td>2008/12/13</td>
        <td>$103,600</td>
    </tr>
    <tr class="bg-dark-grey">
        <td>Ashton Cox</td>
        <td>Junior Technical Author</td>
        <td>San Francisco</td>
        <td>66</td>
        <td>2009/01/12</td>
        <td>$86,000</td>
    </tr>
    <tr class="bg-dark-grey">
        <td>Herrod Chandler</td>
        <td>Sales Assistant</td>
        <td>San Francisco</td>
        <td>59</td>
        <td>2012/08/06</td>
        <td>$137,500</td>
    </tr>
    <tr class="bg-white">
        <td>Garrett Winters</td>
        <td>Accountant</td>
        <td>Tokyo</td>
        <td>63</td>
        <td>2011/07/25</td>
        <td>$170,750</td>
    </tr>
    <tr class="bg-white">
        <td>Airi Satou</td>
        <td>Accountant</td>
        <td>Tokyo</td>
        <td>33</td>
        <td>2008/11/28</td>
        <td>$162,700</td>
    </tr>
    <tr class="bg-white">
        <td>Rhona Davidson</td>
        <td>Integration Specialist</td>
        <td>Tokyo</td>
        <td>55</td>
        <td>2010/10/14</td>
        <td>$327,900</td>
    </tr>
    <tr class="bg-dark-grey">
        <td>Brielle Williamson</td>
        <td>Integration Specialist</td>
        <td>New York</td>
        <td>61</td>
        <td>2012/12/02</td>
        <td>$372,000</td>
    </tr>
    <tr class="bg-dark-grey">
        <td>Paul Byrd</td>
        <td>Chief Financial Officer (CFO)</td>
        <td>New York</td>
        <td>64</td>
        <td>2010/06/09</td>
        <td>$725,000</td>
    </tr>
    <tr class="bg-dark-grey">
        <td>Gloria Little</td>
        <td>Systems Administrator</td>
        <td>New York</td>
        <td>59</td>
        <td>2009/04/10</td>
        <td>$237,500</td>
    </tr>
    <tr class="bg-white">
        <td>Jena Gaines</td>
        <td>Office Manager</td>
        <td>London</td>
        <td>30</td>
        <td>2008/12/19</td>
        <td>$90,560</td>
    </tr>
    <tr class="bg-white">
        <td>Haley Kennedy</td>
        <td>Senior Marketing Designer</td>
        <td>London</td>
        <td>43</td>
        <td>2012/12/18</td>
        <td>$313,500</td>
    </tr>
    <tr class="bg-white">
        <td>Tatyana Fitzpatrick</td>
        <td>Regional Director</td>
        <td>London</td>
        <td>19</td>
        <td>2010/03/17</td>
        <td>$385,750</td>
    </tr>
    <tr class="bg-white">
        <td>Michael Silva</td>
        <td>Marketing Designer</td>
        <td>London</td>
        <td>66</td>
        <td>2012/11/27</td>
        <td>$198,500</td>
    </tr>
    <tr class="bg-white">
        <td>Bradley Greer</td>
        <td>Software Engineer</td>
        <td>London</td>
        <td>41</td>
        <td>2012/10/13</td>
        <td>$132,000</td>
    </tr>
  </tbody>
</table>

You can call this from "document ready" function directly (I've used window.onload to achieve the same thing, for testing purposes only though). Your existing code removes the grey backgrounds if you sort by age or salary so that part is ok, but you can then call this function again if you are sorting by office instead.

I'm sure that there's a php or jquery method as well, but I tend to use vanilla javascript.

Related