简体   繁体   中英

Data sorting in table in D3

I am creating a table using d3 charts. The problem is on sorting it is not sorting in any order. It appears it is sorting randomly. Thank you in advance

<!DOCTYPE html>
  <html>
    <head>
     <meta charset='UTF-8'>
     <title>Weekly Gainer</title>
     <meta name="viewport" content="width=device-width, initial-scale=1.0">
     <link rel="stylesheet" href="style.css" type="text/css"> 
    </head>

    <body>
      <div id="page-wrap">
        <h1>Weekly Gainer</h1>
         <p>Click the table header to sort data according to that column</p>
      </div>
    <script type="text/javascript" src="https://d3js.org/d3.v3.min.js"></script>
    <script type="text/javascript" src="script.js"></script>
   </body>
  </html>

Javascript

 d3.csv("data.csv", function(error, data) {
      if (error) throw error;

      var sortAscending = true;
      var table = d3.select('#page-wrap').append('table');
      var titles = d3.keys(data[0]);
      var headers = table.append('thead').append('tr')
                       .selectAll('th')
                       .data(titles).enter()
                       .append('th')
                       .text(function (d) {
                            return d;
                        })
                       .on('click', function (d) {
                           headers.attr('class', 'header');

                           if (sortAscending) {
                             rows.sort(function(a, b) { return b[d] < a[d]; });
                             sortAscending = false;
                             this.className = 'aes';
                           } else {
                             rows.sort(function(a, b) { return b[d] > a[d]; });
                             sortAscending = true;
                             this.className = 'des';
                           }

                       });

      var rows = table.append('tbody').selectAll('tr')
                   .data(data).enter()
                   .append('tr');
      rows.selectAll('td')
        .data(function (d) {
            return titles.map(function (k) {
                return { 'value': d[k], 'name': k};
            });
        }).enter()
        .append('td')
        .attr('data-th', function (d) {
            return d.name;
        })
        .text(function (d) {
            return d.value;
        });
  });

Style.css

           * { 
        margin: 0; 
        padding: 0; 
      }
      body { 
         font: 14px/1.4 Georgia, Serif; 
      }
     #page-wrap {
        margin: 50px;
     }
     p {
       margin: 20px 0; 
     }

      /* 
      Generic Styling, for Desktops/Laptops 
      */
      table { 
           width: 100%; 
           border-collapse: collapse; 
      }
      /* Zebra striping */
      tr:nth-of-type(odd) { 
           background: #eee; 
      }
      th { 
           background: #333; 
           color: white; 
           font-weight: bold; 
           cursor: s-resize;
           background-repeat: no-repeat;
         background-position: 3% center;
      }
      td, th { 
           padding: 6px; 
           border: 1px solid #ccc; 
           text-align: left; 
      }

      th.des:after {
       content: "\21E9";
     }

     th.aes:after {
       content: "\21E7";
     }

      /* 
      Max width before this PARTICULAR table gets nasty
      This query will take effect for any screen smaller than 760px
      and also iPads specifically.
      */
      @media 
      only screen and (max-width: 760px),
      (min-device-width: 768px) and (max-device-width: 1024px)  {

           /* Force table to not be like tables anymore */
           table, thead, tbody, th, td, tr { 
                display: block; 
           }

           /* Hide table headers (but not display: none;, for accessibility) */
           thead tr { 
                position: absolute;
                top: -9999px;
                left: -9999px;
           }

           tr { border: 1px solid #ccc; }

           td { 
                /* Behave  like a "row" */
                border: none;
                border-bottom: 1px solid #eee; 
                position: relative;
                padding-left: 50%; 
           }

           td:before { 
                /* Now like a table header */
                position: absolute;
                /* Top/left values mimic padding */
                top: 6px;
                left: 6px;
                width: 45%; 
                padding-right: 10px; 
                white-space: nowrap;
           }

           /*
           Label the data
           */
           td:before {
             content: attr(data-th) ": ";
           font-weight: bold;
           width: 6.5em;
           display: inline-block;
           }
      }

      /* Smartphones (portrait and landscape) ----------- */
      @media only screen
      and (min-device-width : 320px)
      and (max-device-width : 480px) {
           body { 
                padding: 0; 
                margin: 0; 
                width: 320px; }
           }

      /* iPads (portrait and landscape) ----------- */
      @media only screen and (min-device-width: 768px) and (max-device-width: 1024px) {
           body { 
                width: 495px; 
           }
      }

Data.csv

 "Stock","Change"
           "GAIL India","24.80%"
           "Vedanta","7.62%"
           "ITC","5.62%"
           "Mahindra & Mahindra","5.49%"
           "Bajaj Auto","5.02%"
           "Ambuja Cement","4.96%"
           "Cairn India","4.86%"
           "Idea Cellular","4.27%"
           "Cipla","4.02%"
           "Indusind Bank","3.93%"
           "Tata Steel","3.89%"
           "Ultratech Cement","3.69%"

here is a working example

you are using d3 so use d3 ascending and descending it will fix. here is the code it will fix your issue.

if (sortAscending) {
    rows.sort(function(a, b) {return d3.ascending(b[d], a[d]);  });
    sortAscending = false;
    this.className = 'aes';
    } 
else {
    rows.sort(function(a, b) { return d3.descending(b[d], a[d]); });
    sortAscending = true;
    this.className = 'des';
    }

I would recommend you to use a jQuery plugin called TableSorter . It's available under both MIT and GPL licences.

First give your table an ID.

.append("table")
.attr("id", "myTable")

Now enable table sorter on mouseover of the TH .

.append("th")
.on("mouseover", function mouseover(p) {
    $("#myTable").tablesorter()   // where mytable is the id of your table
})

Hope this helps.

.sort() does not work as you are expecting it should be some thing like this

rows.sort(function (a, b) {
            return a - b;
        });  

or

rows.sort(function (a, b) {
    if (a > b) {
        return 1;
    }
    if (a < b) {
        return -1;
    }
    // a must be equal to b
    return 0;
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM