<!DOCTYPE html>
<html ng-app="myapp">
<head>
<link rel="stylesheet" type="text/css" href="http://fonts.googleapis.com/css?family=Droid+Sans">
<link rel="stylesheet" href="style.css">
<script data-require="angular.js@1.1.5" data-semver="1.1.5" src="http://code.angularjs.org/1.1.5/angular.min.js"></script>
<link rel="stylesheet" href="http://nvd3.org/src/nv.d3.css">
<script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
<!--<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/d3/3.1.6/d3.min.js"></script>-->
<!--<script type="text/javascript" src="http://nvd3.org/lib/fisheye.js"></script>-->
<script type="text/javascript" src="http://nvd3.org/nv.d3.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/lodash.js/1.2.1/lodash.min.js"></script>
<script src="app.js"></script>
</head>
<body data-ng-controller='SummaryController'>
<h1>Hello NVD!</h1>
<ng-view></ng-view>
<div summary="visualizePie1"></div>
</body>
</html>
var app = angular.module('myapp', []);
app.directive('summary', function(){
return {
restrict: 'A',
replace: false,
scope: {
summary: '='
},
templateUrl: 'summary.html',
link: function(scope, elem, attrs){
// console.log('directive: call to load pie1');
scope.summary();
}
}
});
app.controller('SummaryController', function($scope){
var summary = {
'total_debit': '91.24',
'days_left': 22,
'month': 7,
'total_credit': '0.0',
'year': 2013,
'data': [
{
'category': {
'uri': '/categories/0b092e7c-4d2c-4eba-8c4e-80937c9e483d',
'parent': 'Food',
'name': 'Costco!!'
},
'amount': '55.0',
'debit': true
},
{
'category': {
'uri': '/categories/d6c10cd2-e285-4829-ad8d-c1dc1fdeea2e',
'parent': 'Food',
'name': 'India Bazaar'
},
'amount': '40.0',
'debit': true
},
{
'category': {
'uri': '/categories/d6c10cd2-e285-4829-ad8d-c1dc1fdeea2e',
'parent': 'Food',
'name': 'Sprouts'
},
'amount': '21.1',
'debit': true
},
{
'category': {
'uri': '/categories/7ea09d55-9c47-4e28-9d4d-f2cead708385',
'parent': 'Home',
'name': 'Rent'
},
'amount': '655.14',
'debit': true
},
{
'category': {
'uri': '/categories/0b092e7c-4d2c-4eba-8c4e-80937c9e483d',
'parent': 'Home',
'name': 'Repair'
},
'amount': '15.0',
'debit': true
},
{
'category': {
'uri': '/categories/d6c10cd2-e285-4829-ad8d-c1dc1fdeea2e',
'parent': 'Travel',
'name': 'Bart'
},
'amount': '200.0',
'debit': true
},
{
'category': {
'uri': '/categories/d6c10cd2-e285-4829-ad8d-c1dc1fdeea2e',
'parent': 'Travel',
'name': 'Air Tickets'
},
'amount': '110.1',
'debit': true
},
{
'category': {
'uri': '/categories/7ea09d55-9c47-4e28-9d4d-f2cead708385',
'parent': 'Travel',
'name': 'Disney'
},
'amount': '55.14',
'debit': true
}
]
};
/* Lodash Helper methods */
// group by with parent category
var dataGroupByParentCategory = function(data){
return _.groupBy(data, function(entry){
return entry.category.parent;
});
};
// object with {parentCategory: sum(parentCategory.amount)}
var parentCategorySum = function(data) {
var result = [];
var dataGroupByParent = dataGroupByParentCategory(data);
_.forEach(_.keys(dataGroupByParent), function(parentCategory){
var s = _.reduce(dataGroupByParent[parentCategory], function(s, entry){
return s + parseFloat(entry.amount);
}, 0);
result.push({'parent': parentCategory, 'amount': s})
});
return [{'values': result}];
};
/* end helper methods*/
var addGraph = function(where, summaryData){
nv.addGraph(function() {
var chart = nv.models.pieChart()
.x(function(d) {
if (where === '#pie1') {
return d.parent;
}
if (where === '#pie2') {
return d.category.name;
}
})
.y(function(d) { return d.amount; })
.showLabels(true);
d3.select(where + " svg")
.datum(summaryData)
.transition().duration(2200)
.call(chart);
if (where === '#pie1') {
d3.selectAll('.nv-slice')
.on('click', function(){
var parentCategory = this.getElementsByClassName("nv-label")[0].textContent;
console.log('visualize ', parentCategory);
$scope.visualizePie2(parentCategory);
});
}
var tp = function(key, y, e, graph) {
console.log(key, e, y);
return '<h3>' + key + '</h3>' +
'<p>$' + y + '</p>';
};
chart.tooltipContent(tp);
return chart;
});
};
$scope.visualizePie1 = function() {
var d = parentCategorySum(summary.data);
addGraph('#pie1', d);
}
$scope.visualizePie2 = function(parentCategory) {
var result = [{'values': dataGroupByParentCategory(summary.data)[parentCategory]}];
console.log('visualizing parentCategory ', result);
addGraph('#pie2', result);
}
});
body {
font-family: 'Droid Sans', serif;
}
#pie1 svg , #pie2 svg {
height: 400px;
}
#pie1 .nv-slice {
cursor: hand;
cursor: pointer;
}
<div id="summary">
<div id="pie1">
<svg></svg>
</div>
<div id="pie2">
<svg></svg>
</div>
</div>
var app = angular.module('myapp', []);
app.directive('summary', function(){
return {
restrict: 'A',
replace: false,
scope: {
summary: '='
},
templateUrl: 'summary.html',
link: function(scope, elem, attrs){
// console.log('directive: call to load pie1');
scope.summary();
}
}
});
app.controller('SummaryController', function($scope){
var summary = {
'total_debit': '91.24',
'days_left': 22,
'month': 7,
'total_credit': '0.0',
'year': 2013,
'data': [
{
'category': {
'uri': '/categories/0b092e7c-4d2c-4eba-8c4e-80937c9e483d',
'parent': 'Food',
'name': 'Costco!!'
},
'amount': '55.0',
'debit': true
},
{
'category': {
'uri': '/categories/d6c10cd2-e285-4829-ad8d-c1dc1fdeea2e',
'parent': 'Food',
'name': 'India Bazaar'
},
'amount': '40.0',
'debit': true
},
{
'category': {
'uri': '/categories/d6c10cd2-e285-4829-ad8d-c1dc1fdeea2e',
'parent': 'Food',
'name': 'Sprouts'
},
'amount': '21.1',
'debit': true
},
{
'category': {
'uri': '/categories/7ea09d55-9c47-4e28-9d4d-f2cead708385',
'parent': 'Home',
'name': 'Rent'
},
'amount': '655.14',
'debit': true
},
{
'category': {
'uri': '/categories/0b092e7c-4d2c-4eba-8c4e-80937c9e483d',
'parent': 'Home',
'name': 'Repair'
},
'amount': '15.0',
'debit': true
},
{
'category': {
'uri': '/categories/d6c10cd2-e285-4829-ad8d-c1dc1fdeea2e',
'parent': 'Travel',
'name': 'Bart'
},
'amount': '200.0',
'debit': true
},
{
'category': {
'uri': '/categories/d6c10cd2-e285-4829-ad8d-c1dc1fdeea2e',
'parent': 'Travel',
'name': 'Air Tickets'
},
'amount': '110.1',
'debit': true
},
{
'category': {
'uri': '/categories/7ea09d55-9c47-4e28-9d4d-f2cead708385',
'parent': 'Travel',
'name': 'Disney'
},
'amount': '55.14',
'debit': true
},
{
'category': {
'uri': '/categories/d6c10cd2-e285-4829-ad8d-c1dc1fdeea2e',
'parent': 'Taxes',
'name': 'Income'
},
'amount': '30.1',
'debit': true
},
{
'category': {
'uri': '/categories/7ea09d55-9c47-4e28-9d4d-f2cead708385',
'parent': 'Taxes',
'name': 'Sales'
},
'amount': '1.14',
'debit': true
},
{
'category': {
'uri': '/categories/d6c10cd2-e285-4829-ad8d-c1dc1fdeea2e',
'parent': 'Entertainment',
'name': 'comics'
},
'amount': '21.1',
'debit': true
},
{
'category': {
'uri': '/categories/7ea09d55-9c47-4e28-9d4d-f2cead708385',
'parent': 'Entertainment',
'name': 'music'
},
'amount': '111.14',
'debit': true
}
]
};
/* Lodash Helper methods */
// group by with parent category
var dataGroupByParentCategory = function(data){
return _.groupBy(data, function(entry){
return entry.category.parent;
});
};
// object with {parentCategory: sum(parentCategory.amount)}
var parentCategorySum = function(data) {
var result = [];
var dataGroupByParent = dataGroupByParentCategory(data);
_.forEach(_.keys(dataGroupByParent), function(parentCategory){
var s = _.reduce(dataGroupByParent[parentCategory], function(s, entry){
return s + parseFloat(entry.amount);
}, 0);
result.push({'parent': parentCategory, 'amount': s})
});
return [{'values': result}];
};
/* end helper methods*/
var addGraph = function(where, summaryData){
nv.addGraph(function() {
var chart = nv.models.pieChart()
.x(function(d) {
if (where === '#pie1') {
return d.parent;
}
if (where === '#pie2') {
return d.category.name;
}
})
.y(function(d) { return d.amount; })
.showLabels(true);
d3.select(where + " svg")
.datum(summaryData)
.transition().duration(2200)
.call(chart);
if (where === '#pie1') {
d3.selectAll('.nv-slice')
.on('click', function(){
var parentCategory = this.getElementsByClassName("nv-label")[0].textContent;
console.log('visualize ', parentCategory);
$scope.visualizePie2(parentCategory);
});
}
var tp = function(key, y, e, graph) {
console.log(key, e, y);
return '<h3>' + key + '</h3>' +
'<p>$' + y + '</p>';
};
chart.tooltipContent(tp);
return chart;
});
};
$scope.visualizePie1 = function() {
var d = parentCategorySum(summary.data);
addGraph('#pie1', d);
}
$scope.visualizePie2 = function(parentCategory) {
var result = [{'values': dataGroupByParentCategory(summary.data)[parentCategory]}];
console.log('visualizing parentCategory ', result);
addGraph('#pie2', result);
}
});