Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
446 views
in Technique[技术] by (71.8m points)

d3.js - putting the country on drop down list using d3 via csv file

Good day,

I need help regarding this simple task. All i want is to insert data in drop down. when i select data in drop down the map will zoom based on the selected value. i already have the code regarding the zooming of each country. but it is in the table when the country click on country of specific tr the map will zoom and it's fine. the problem is that i want to put that value of the country inside the drop down using d3. is can any one can help me..

here is my code.

          <!DOCTYPE html>
          <meta charset="utf-8">

             <style>

         .legend {
         font-size: 10px;
           z-index:0;

         }
          rect {
           fill: none;
                pointer-events: all;
           }

            .feature {
         fill: #ccc;
        cursor: pointer;
         }

         .feature.active {
           fill: orange;
       }

      .mesh {
fill: none;
stroke: #fff;
stroke-width: .5px;
stroke-linejoin: round;
      }

.csvTable table {
    border-collapse: collapse;
    text-align: left;
    width: 100%;
}

.csvTable {
    font: normal 12px/150% Arial, Helvetica, sans-serif;
    background: #fff;
    overflow: hidden;
    border: 1px solid #069;
    -webkit-border-radius: 3px;
    -moz-border-radius: 3px;
    border-radius: 3px;
}

.csvTable table td, .csvTable table th {
    padding: 3px 10px;
}

.csvTable table thead th {
    background: 0;
    filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#006699',endColorstr='#00557F');
    background-color: #006D2C;
    color: #FFF;
    font-size: 15px;
    font-weight: 700;
    border-left: 1px solid #0070A8;
}

    .csvTable table thead th:first-child {
        border: none;
    }

.csvTable table tbody td {
    color: #00496B;
    border-left: 1px solid #E1EEF4;
    font-size: 12px;
    border-bottom: 1px solid #E1EEF4;
    font-weight: 400;
}

    .csvTable table tbody td:first-child {
        border-left: none;
    }

.csvTable table tbody tr:last-child td {
    border-bottom: none;
}

.csvTable tr:hover td {
    background-color: #069;
    color: white;
}
</style>

  <script src="Script/d3.v3.min.js" ></script>
   <script src="Script/topojson.v1.min.js"></script>

  <!--<script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>-->

       <body>
      <!-- Table to hold the Divs -->
           <table border="0" cellpadding="10" style="overflow-y: scroll;">
          <tr>
         <td><div id="country_select" class="csvTable"></div></td>
        <td><div id="table_container" class="csvTable"></div></td>
        <td><div id="map_container"></div></td>
    </tr>
     </table>

 <script>


var w = 900;
var h = 300;
var active;
var jsonOutside;

var projection = d3.geo.mercator()
     .center([0, 5])
     .rotate([0, 0])
     .scale(100)
     .translate([w / 2, h / 2])
     .precision(9);


var path = d3.geo.path()
                 .projection(projection);


var svg = d3.select("#map_container")
            .append("svg")
            .attr("width", w)
            .attr("height", h);

var color_domain = [1, 50000, 250000, 70000000, 150000000, 300000000];
var ext_color_domain = [100, 50000, 250000, 70000000, 150000000, 300000000];
var legend_labels = ["< 5000", "5000+", "100000+", "500000+", "7500000+", "> 15000000"];
// var legend_labels = ["< 5000", "5000+", "15000+", "35000+", "75000+", "> 150000"];
var color = d3.scale.log()
.domain(color_domain)

 .range(["#adfcad", "#ffcb40", "#ffba00", "#ff7d73", "#ff4e40", "#ff1300"]);
    // .range(["#adfcad", "#ccff66", "#ffff00", "#cc9933", "#0099ff", "#ff1300"])

      // from colorbrewer (http://colorbrewer2.org/)
         //var colours = ["#BAE4B3", "#74C476", "#31A354", "#006D2C"];


        //var colScale = d3.scale.ordinal()
         //                  .range(colours);

        svg.append("rect")
    .attr("width", w)
    .attr("height", h)
    .on("click", reset);

        var g = svg.append("g");

      d3.csv("data/TotalReputationBlocked.csv", function (data) {
    d3.json("data/world-population.geo.json", function (json) {

        json.features.forEach(function (d, i) {
            data.forEach(function (e, j) {
                if (d.properties.name === e.Country) {
                    d.properties.value = +e.Result;
                };
            })
        })

        jsonOutside = json; // pass json to a global so tableRowClicked has access


        var dispatch = d3.dispatch("load", "countrychange");
        d3.csv("data/ERSReputationBlocked.csv", type, function (error, country) {
            if (error) throw error;
            var countryById = d3.map();
            country.forEach(function (d) { countryById.set(d.id, d); });
            dispatch.load(countryById);
            dispatch.countrychange(countryById.get("Philippines"));

        });
        dispatch.on("load.menu", function (countryById) {
            var select = d3.select("body")

              .append("div")
              .append("select")
              //.on("change", function () { dispatch.countrychange(countryById.get(this.value)); });

                .on("click", click)
            // .on("change", function (d) { tableRowClicked(d); });

            select.selectAll("option")
              .data(countryById.values())
              .enter().append("option")
              .attr("value", function (d) { return d.id; })
              .text(function (d) { return d.Country; });

            dispatch.on("countrychange.map", function (d) {
                select.property("value", d)
                //.on("click",tableRowClicked)
               .on("click", click)
            //    //end of selection
            });
        });
        //end of selection
        //var columns = ["Country", "Result"];
        //var table = d3.select("#table_container").append("table"),
        //      thead = table.append("thead"),
        //      tbody = table.append("tbody");

        //// append the header row
        //thead.append("tr")
        //      .selectAll("th")
        //      .data(columns)
        //      .enter()
        //      .append("th")
        //      .text(function (column) { return column; });


        //// create a row for each object in the data
        //var rows = tbody.selectAll("tr")
        //     .data(data)
        //     .enter()
        //     .append("tr");


        //// create a cell in each row for each column
        //var cells = rows.selectAll("td")
        //     .data(function (row) {
        //         return columns.map(function (column) {
        //             return { column: column, value: row[column] };
        //         });
        //     })
        //     .enter()
        //     .append("td")
        //     .text(function (d) { return d.value; }
        //     )
        //     .on("click", function (d) { tableRowClicked(d); }); // added on click event to td         element NB you need to click on the cell with the conuty name 

        // add extents (max and min) from data results for choropleth
        //color.domain(d3.extent(data, function (d) { return d.Result; }));



                //Bind data and create one path per GeoJSON feature
                g.selectAll("path")
                   .data(json.features)
                   .enter()
                   .append("path")
                   .attr("d", path)
                   .attr("class", "feature")
                   .attr("id", function (d) { return d.properties.name; }) // added id so click could work on id which is common between the json and csv data

                    //.on("click",function (d) { tableRowClicked(d); })
                     .on("click", function (d) { click(d); })
                   .style("stroke", "white")
                   //.style("fill", function (d, i) { return colScale(d.properties.value); }); // fill based on colour scale
                 .style("fill", function (d) {
                     return color(d.properties.value);
                 });

                g.append("path")
                   .data(json.features)
                   .enter()
                   .append("path")
                   .attr("class", "mesh")
                   .attr("d", path);

            });
        });




        function type(d) {
            d.total = d3.sum(d.value, function (k) { return d[k] = +d[k]; });
            return d;
        }



var legend = svg.selectAll("g.legend")
.data(ext_color_domain)
.enter().append("g")
.attr("class", "legend");

var ls_w = 20, ls_h = 20;

legend.append("rect")
.attr("x", 20)
.attr("y", function (d, i) { return h - (i * ls_h) - 2 * ls_h; })
.attr("width", ls_w)
.attr("height", ls_h)
.style("fill", function (d, i) { return color(d); })
.style("opacity", 0.8);

legend.append("text")
.attr("x", 50)
.attr("y", function (d, i) { return h - (i * ls_h) - ls_h - 4; })
.text(function (d, i) { return legend_labels[i]; });









function click(d) {

    if (active === d) return reset();
    g.selectAll(".active").classed("active", false);
    d3.select("#" + d.properties.name).classed("active", active = d); // changed selection to id

    var b = path.bounds(d);

    g.transition().duration(1000).attr("transform",
        "translate(" + projection.translate() + ")"
        + "scale(" + .95 / Math.max((b[1][0] - b[0][0]) / w, (b[1][1] - b[0][1]) / h) + ")"
        + "translate(" + -(b[1][0] + b[0][0]) / 2 + "," + -(b[1][1] + b[0][1]) / 2 + ")");
}

function reset() {
    g.selectAll(".active").classed("active", active = false);
    g.transition().duration(750).attr("transform", "");
}

function tableRowClicked(x) {
    jsonOutside.features.forEach(function (d) { // loop through json data to match td entry
        if (x.value === d.properties.name) {
            alert(x.value)
            var country = d;
            click(d); // pass json element that matches td data to click 
        };
    })
}

      </script>
        </body>
      </html>

this code works fine the only problem is that i cant put that country on the drop down, I hope there's some one who can help me..

thanks coders

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

A drop-down menu in HTML is created by using a <select> element with <option> elements inside, like this:

<select name="country-list">
  <option value="Afghanistan">Afghanistan</option>
  <option value="Albania">Albania</option> 
  <option value="Algeria">Algeria</option>
  <!-- and so on... -->
</select>

To create this structure, you can just go through and adapt the part of the original code where it created the table. You start by creating a <select> element instead of a <table> element, like this:

var dropDown = d3.select("#table_container").append("select")
                    .attr("name", "country-list");

You can skip the thead and tbody parts, since the structure of the dropdown menu is so much simpler. Then, instead of joining data to create a selection of tr (table row) elements, we join it to create a selection of option elements:

var options = dropDown.selectAll("option")
               .data(data) // eg., data = [ {'value': 10}, {'value': 11}, {'value': 12} ]
               .enter()
               .append("option");

Then add the value attribute and the text content of the option element based on the data:

options.text(function (d) { return d.value; })
       .attr("value", function (d) { return d.value; });

I hope that's all straight-forward. It gets a little more complicated when you add the event handler.

Instead of responding to a "click" event on an individual country name, the event handler for a drop-down list is added to the list as a whole, and responds to a "change" event:

dropDown.on("change", menuChanged);

Because the event handler is attached to the entire list instead of to each individual option element, however, it can't get passed the d data object from the element that was selected. Instead, the value attribute of the selected element is stored within the global d3.event object, as d3.event.target.value. This is why I was careful to set the value attribute of each option element to match the value property of the data object.

So the final thing you need to do is to change your event handler method to use the event value instead of a passed-in data value:

/*  BEFORE
function tableRowClicked(x) {
      //x is the data object for that individual table row

    jsonOutside.features.forEach(function (d) { 
        // loop through json data to match td entry

        if (x.value === d.properties.name) {
        //for each data object in the features array (d), compare it's
        //name against the one in the table row data object

            alert(x.value)
            var country = d; //this does nothing...
            click(d); // pass json element that matches td data to click 
        };
    })
}
//*/
//* AFTER
function menuChanged() {
          //the name isn't important, but has to match the name
          //you added to the menu's "change" event listener.

    var selectedValue = d3.event.target.value;  
         //get the name of the selected option from the change event object

    jsonOutside.features.forEach(function (d) { 
        // loop through json data to match td entry

        if (selectedValue === d.properties.name) {
        //for each data object in the features array (d), compare it's
        //name against the one you got from the event object
        //if they match, then:

            alert(selectedValue)  //remove this line when things are working!

            click(d); // pass json element that matches selected value to click
             //which will respond the same way as if you clicked the country on
             //the map. 
        };
    })
}
//*/

I've got a slightly simpler example of an event on a drop-down menu here:
http://fiddle.jshell.net/7KJC7/2/
The option elements are pre-coded in the HTML instead of created from data, but I show how to access different types of data about the selection from the d3.event object, and compare with what happens (nothing) when you try to put the event handler on the individual <option> elements.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

1.4m articles

1.4m replys

5 comments

57.0k users

...