{"id":487,"date":"2014-05-29T17:08:18","date_gmt":"2014-05-29T21:08:18","guid":{"rendered":"http:\/\/digitallibraryworld.com\/?p=487"},"modified":"2014-05-29T17:09:17","modified_gmt":"2014-05-29T21:09:17","slug":"using-d3-with-external-data-source-through-http-rest-call","status":"publish","type":"post","link":"https:\/\/heisbudi.com\/?p=487","title":{"rendered":"Using D3 with external data source through HTTP  REST call"},"content":{"rendered":"<p><span style=\"line-height: 1.5em;\">I am new to D3, and struggled a bit trying to figure out how to use external data source obtained through HTTP REST call as my data source. If you don\u2019t know what I mean by HTTP REST call, it\u2019s basically calling a URL that would return JSON data.<\/span><\/p>\n<p><span style=\"line-height: 1.5em;\">If you are not familiar with D3,\u00a0 <a title=\"D3 Tutorial\" href=\"http:\/\/alignedleft.com\/tutorials\/d3\/fundamentals\">this tutorial<\/a> by Scott Murray is a required reading. <\/span><span style=\"line-height: 1.5em;\">After you are done reading that, read <a title=\"D3 Manual\" href=\"https:\/\/github.com\/mbostock\/d3\/wiki\/Requests\">this manual<\/a> by the author of d3 himself.\u00a0<\/span><\/p>\n<p>In a nutshell:<\/p>\n<ul>\n<li>No, you don&#8217;t need jquery library. D3 itself is enough.<\/li>\n<li>HTTP calls are asynchronous in d3.<\/li>\n<li>If you are pulling external data, you will need to provide a callback function. This callback function will be executed AFTER the HTTP call is done pulling data. The callback function can be a named or anonymous function<\/li>\n<li>Need to use d3.json(&#8220;some url&#8221;, function(error, response)). \u00a0The anonymous function is the callback that will be executed when HTTP call is finished.<\/li>\n<\/ul>\n<p>I will use a working example from nvd3 to accomplish this. You can download the source from <a href=\"https:\/\/github.com\/novus\/nvd3\">nvd3 site<\/a>. The file I will be using is\u00a0examples\/discreteBar.html<\/p>\n<p>The code below show that data is hardcoded in the original example file from nvd3. <\/p>\n<pre lang=\"html4strict\" line=\"1\">\r\n<script type=\"text\/javascript\">\r\nhistoricalBarChart = [ \r\n  {\r\n    key: \"Cumulative Return\",\r\n    values: [\r\n      { \r\n        \"label\" : \"A\" ,\r\n        \"value\" : 29.765957771107\r\n      } , \r\n      { \r\n        \"label\" : \"B\" , \r\n        \"value\" : 0\r\n      } , \r\n      { \r\n        \"label\" : \"C\" , \r\n        \"value\" : 32.807804682612\r\n      } , \r\n    ]\r\n  }\r\n];\r\n<\/pre>\n<p>The code below use the hardcoded data and pass it onto d3 to render. <\/p>\n<pre lang=\"javascript\" line=\"1\">\r\nnv.addGraph(function() {  \r\n  var chart = nv.models.discreteBarChart()\r\n      .x(function(d) { return d.label })\r\n      .y(function(d) { return d.value })\r\n      .staggerLabels(true)\r\n      \/\/.staggerLabels(historicalBarChart[0].values.length > 8)\r\n      .tooltips(false)\r\n      .showValues(true)\r\n      .transitionDuration(250)\r\n      ;\r\n\r\n  d3.select('#chart1 svg')\r\n      .datum(historicalBarChart)\r\n      .call(chart);\r\n\r\n  nv.utils.windowResize(chart.update);\r\n\r\n  return chart;\r\n});\r\n<\/pre>\n<p>What we want is to call d3.json function, and perform the following:<\/p>\n<ul>\n<li>process the HTTP call and transform the data it into format d3 requires<\/li>\n<li>render the graph<\/li>\n<\/ul>\n<p>The two process I mentioned above requires HTTP call to finish retrieving data before it can be passed to d3. To make http call using d3 library, use:<\/p>\n<pre lang=\"javascript\" line=\"1\">d3.json(\"http:\/\/something.that.returns.json\",function(error,response){\r\n\/\/TASK 1\r\n\/\/process http call here. \r\n\r\n\/\/TASK 2\r\n\/\/render the graph here\r\n});<\/pre>\n<p>This is the most important part:\u00a0the two task I mentioned previously need to be performed from within the anonymous function because this is the section that will be executed when d3 finishes making http call. The response variable will contain the json data resulting from http call. The error is empty when the http call is successful. It will contain error details otherwise. This is the complete code of calling currency exchange rate api. You need to provide your own api key.<\/p>\n<pre lang=\"html4strict\" line=\"1\">\r\n<!DOCTYPE html>\r\n<meta charset=\"utf-8\">\r\n\r\n<link href=\"..\/src\/nv.d3.css\" rel=\"stylesheet\" type=\"text\/css\">\r\n\r\n<style>\r\n\r\nbody {\r\n  overflow-y:scroll;\r\n  margin: 0;\r\n  padding: 0;\r\n}\r\n\r\nsvg {\r\n  overflow: hidden;\r\n}\r\n\r\ndiv {\r\n  border: 0;\r\n  margin: 0;\r\n}\r\n\r\n\r\n#test1 {\r\n  margin: 0;\r\n}\r\n\r\n#chart svg {\r\n  height: 800px;\r\n  width: 600px;\r\n}\r\n\r\n<\/style>\r\n\r\n<body>\r\n\r\n<div id=\"offsetDiv\">\r\n  <div id=\"chart\" class='with-3d-shadow with-transitions'>\r\n    <svg><\/svg>\r\n  <\/div>\r\n<\/div>\r\n\r\n<script src=\"..\/lib\/d3.v3.js\"><\/script>\r\n<script src=\"..\/nv.d3.js\"><\/script>\r\n<script src=\"..\/src\/tooltip.js\"><\/script>\r\n<script src=\"..\/src\/utils.js\"><\/script>\r\n<script src=\"..\/src\/models\/legend.js\"><\/script>\r\n<script src=\"..\/src\/models\/axis.js\"><\/script>\r\n<script src=\"..\/src\/models\/distribution.js\"><\/script>\r\n<script src=\"..\/src\/models\/scatter.js\"><\/script>\r\n<script src=\"..\/src\/models\/scatterChart.js\"><\/script>\r\n<script>\r\ngenerateChart();\r\nfunction generateChart() {\r\n    var chart;\r\n    var rate = [{key:\"Exchange Rate against USD\", values:[]}];\r\n    var test;\r\n    d3.json('http:\/\/openexchangerates.org\/api\/latest.json?app_id=YOUR_OWN_API', function(error,data){\r\n\r\n        for(var key in data.rates){\r\n            if(data.rates.hasOwnProperty(key)){\r\n                switch(key) {\r\n                    case \"CAD\":\r\n                        rate[0][\"values\"].push({\"label\":\"Canadian Dollar\",\"value\":data.rates[key]});\r\n                        break;\r\n                    case \"CNY\":\r\n                        rate[0][\"values\"].push({\"label\":\"Chinese Yuan\",\"value\":data.rates[key]});\r\n                        break;\r\n                    case \"CHF\":\r\n                        rate[0][\"values\"].push({\"label\":\"Swiss Franc\",\"value\":data.rates[key]});\r\n                        break;\r\n                    case \"EUR\":\r\n                        rate[0][\"values\"].push({\"label\":\"Euro\",\"value\":data.rates[key]});\r\n                        break;\r\n                    case \"JPY\":\r\n                        rate[0][\"values\"].push({\"label\":\"Japanese Yen\",\"value\":data.rates[key]});\r\n                        break;\r\n\r\n                }\r\n\r\n            }\r\n        }\r\n        nv.addGraph(function() {\r\n            chart = nv.models.discreteBarChart()\r\n                    .x(function(d) { return d.label })    \/\/Specify the data accessors.\r\n                    .y(function(d) { return d.value })\r\n                    .staggerLabels(true)    \/\/Too many bars and not enough room? Try staggering labels.\r\n                    .tooltips(false)        \/\/Don't show tooltips\r\n                    .showValues(true)       \/\/...instead, show the bar value right on top of each bar.\r\n                    .transitionDuration(350);\r\n\r\n            generateChart(chart);\r\n            d3.select('#chart svg')\r\n                    .datum(rate)\r\n                    .call(chart);\r\n\r\n            nv.utils.windowResize(chart.update);\r\n\r\n            return chart;\r\n        });\r\n    })\r\n\r\n}\r\n<\/script>\r\n\r\n<\/pre>\n<div data-counters='1' data-style='square' data-size='regular' data-url='https:\/\/heisbudi.com\/?p=487' data-title='Using D3 with external data source through HTTP  REST call' class='linksalpha_container linksalpha_app_3'><a href='\/\/www.linksalpha.com\/share?network='facebook' class='linksalpha_icon_facebook'><\/a><a href='\/\/www.linksalpha.com\/share?network='twitter' class='linksalpha_icon_twitter'><\/a><a href='\/\/www.linksalpha.com\/share?network='googleplus' class='linksalpha_icon_googleplus'><\/a><a href='\/\/www.linksalpha.com\/share?network='mail' class='linksalpha_icon_mail'><\/a><\/div><div data-position='' data-url='https:\/\/heisbudi.com\/?p=487' data-title='Using D3 with external data source through HTTP  REST call' class='linksalpha_container linksalpha_app_7'><a href='\/\/www.linksalpha.com\/share?network='facebook' class='linksalpha_icon_facebook'><\/a><a href='\/\/www.linksalpha.com\/share?network='twitter' class='linksalpha_icon_twitter'><\/a><a href='\/\/www.linksalpha.com\/share?network='googleplus' class='linksalpha_icon_googleplus'><\/a><a href='\/\/www.linksalpha.com\/share?network='mail' class='linksalpha_icon_mail'><\/a><\/div>","protected":false},"excerpt":{"rendered":"<p>I am new to D3, and struggled a bit trying to figure out how to use external data source obtained through HTTP REST call as my data source. If you don\u2019t know what I mean by HTTP REST call, it\u2019s basically calling a URL that would return JSON data. If you are not familiar with <a class=\"read-more\" href=\"https:\/\/heisbudi.com\/?p=487\">[&hellip;]<\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[31],"tags":[],"_links":{"self":[{"href":"https:\/\/heisbudi.com\/index.php?rest_route=\/wp\/v2\/posts\/487"}],"collection":[{"href":"https:\/\/heisbudi.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/heisbudi.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/heisbudi.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/heisbudi.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=487"}],"version-history":[{"count":16,"href":"https:\/\/heisbudi.com\/index.php?rest_route=\/wp\/v2\/posts\/487\/revisions"}],"predecessor-version":[{"id":503,"href":"https:\/\/heisbudi.com\/index.php?rest_route=\/wp\/v2\/posts\/487\/revisions\/503"}],"wp:attachment":[{"href":"https:\/\/heisbudi.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=487"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/heisbudi.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=487"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/heisbudi.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=487"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}