How add crossfilter function filterRange. Dc.js on server side - dc.js

I moved calculations to the server side, because data is large.
I want to draw dc.seriesChart, but after specifying date range
.x(d3.scaleTime().domain([minDate, maxDate]))
an error appears on page load:
Uncaught TypeError: t.filterRange is not a function.
Please help implement filterRange in script.js, app.js and script.js code is attached.
I'm using the crossfilter express pattern from lastlegion/dc.js-server-side-crossfilter.
app.js
var express = require('express');
var path = require('path');
var anyToJSON = require('anytojson');
var crossfilter = require('crossfilter');
var d3 = require('d3');
var app = express();
app.listen(3000, () => console.log('Listening at Port 3000'));
app.use(express.static('public'));
var dimensions = {};
var groups = {};
app.get("/data", function(req, res, next) {
var results = {};
filter = req.param("filter") ? JSON.parse(req.param("filter")) : {}
console.log(filter);
for (dimension in dimensions) {
console.log("Dimension: " + dimension);
if (filter[dimension]) {
if ((filter[dimension]).length > 1) {
console.log(filter);
dimensions[dimension].filterFunction(function (d) {
var filters = (filter[dimension]);
for (var i = 1; i < filters.length; i++) {
var filter = filters[i];
if (filter.isFiltered && filter.isFiltered(d)) {
return true;
} else if (filter <= d && filter >= d) {
return true;
}
}
return false;
});
}
else {
console.log(filter[dimension]);
dimensions[dimension].filter(filter_value(filter[dimension]));
}
} else {
dimensions[dimension].filterAll()
}
}
for (dimension in groups) {
console.log("Group: " + dimension);
var group = groups[dimension];
results[dimension] = {
values: group.all(),
top: group.top(1)[0].value
};
}
res.writeHead(200, {
'content-type': 'application/json'
});
res.end((JSON.stringify(results)));
});
function filter_value(dir) {
console.log( "dfsk");
if ((dir).length === 1) {
return dir[0];
} else if ((dir).length === 0) {
return null
}
}
anyToJSON.csv({ path: "input/dataset.csv"}, function(records) {
var dateFormat = d3.timeFormat("%Y-%m-%d %H:%M:%S");
var dateFormatParser = d3.timeParse("%Y-%m-%d %H:%M:%S");
records.forEach(function(d) {
d.timestamp = dateFormat(dateFormatParser(d.timestamp));
});
var ndx = crossfilter(records);
var all = ndx.groupAll();
console.log("...");
var dateDim = ndx.dimension(function (d) { return d.timestamp; });
var datePriorityDim = ndx.dimension(function (d) { return [d.priority, d.timestamp];});
var numRecordsByDate = dateDim.group();
var datePriorityGroup = datePriorityDim.group().reduceCount();
dimensions.dateDim = dateDim;
dimensions.datePriorityDim = datePriorityDim;
groups.numRecordsByDate = numRecordsByDate;
groups.datePriorityGroup = datePriorityGroup;
});
module.exports = app;
public/js/script.js
var priorityTimeChart = new dc.seriesChart("#priority-timeline");
var filteredData = {};
var queryFilter = {};
window.filter = function(filters) {
filters.forEach(function(d, i) { charts[i].filter(d); });
renderAll();
};
window.reset = function(i) {
charts[i].filter(null);
renderAll();
};
var refresh = function(queryFilter){
d3.json("/data?filter="+JSON.stringify(queryFilter), function(d){
filteredData = d;
dc.redrawAll();
});
};
var dateDim = {
filter:function(f){
if(f){
queryFilter["dateDim"]=f;
refresh(queryFilter);
}
},
filterAll:function(){
},
filterRange:function(){
}
};
var numRecordsByDate = {
all:function(){
return filteredData["numRecordsByDate"].values;
},
order: function(){
},
top:function(){
}
};
var datePriorityDim = {
filter:function(f){
if(f){
queryFilter["datePriorityDim"]=f;
refresh(queryFilter);
}
},
filterAll:function(){
}
};
var datePriorityGroup = {
all:function(){
return filteredData["datePriorityGroup"].values;
},
order: function(){
},
top:function(){
}
};
var minDate = "Fri Mar 13 2020 11:49:35 GMT+0300";
var maxDate = "Tue Mar 17 2020 14:50:03 GMT+0300";
priorityTimeChart
.height(h_row2)
.chart(function(c) { return new dc.lineChart(c).curve(d3.curveCardinal).evadeDomainFilter(true); })
.x(d3.scaleTime().domain([minDate, maxDate]))
.brushOn(true)
.yAxisLabel("Events")
.xAxisLabel("Date")
.elasticY(true)
.dimension(dateDim)
.group(datePriorityGroup)
.mouseZoomable(true)
.colors(d3.scaleOrdinal().domain(['High','Middle','Low']).range(["red", "green", "yellow"]))
.seriesAccessor(function(d) {return "priority: " + d.key[0];})
.keyAccessor(function(d) {return +d.key[1];})
.valueAccessor(function(d) {return +d.value;})
.legend(dc.legend().x(350).y(350).itemHeight(13).gap(5).horizontal(1).legendWidth(140).itemWidth(70))
.yAxis().ticks(3);
priorityTimeChart.yAxis().tickFormat(function(d) {return d3.format(',d')(d);});
priorityTimeChart.margins().left += 10;
priorityTimeChart.filterHandler(function(dimension, filters){
if(filters)
dimension.filter(filters);
else
dimension.filter(null);
return filters;
});
function init(){
d3.json("/data?filter={}", function(d){
filteredData = d;
dc.renderAll();
});
};
init();

Related

Cemetery Mapping search with Leaflet

How can I do when I retrieve a person from the BD and create a link to direct to the grave on the map?
I do a search in the BD and when I find a person, I want to create a url that, when clicked, shows the map of the cemetery showing the location of the grave.
Here's the code I have so far. It shows me the map, but it doesn't show the grave marker.
<script >
$(document).ready(function(){
var prev_path = prev_marker = null;
$('.btn_search').on('click',function(){
var firstname = $('input[name="deceased_firstname"]').val();
var lastname = $('input[name="deceased_lastname"]').val();
/* var f_firstname = firstname.replace(/ /g, '%20');
var l_lastname = lastname.replace(/ /g, '%20');
*/
var url = '<?=base_url()?>/pages/search_burial/'+firstname+'/'+lastname;
console.log(url);
$.getJSON(url, function(data){
if (data == null) { alert("no results found!"); }
console.log(data);
var icon_grave = L.icon({
iconUrl: "<?=base_url()?>" +'user_template/icons/catholicgrave.png',
iconSize: [30,30] });
var latlngs = []
if(data != null || data != undefined) {
var route = JSON.parse(data.lot_coordinates);
for (var i = 0, len = route.length; i < len; i++) {
latlngs.push(new L.LatLng(route[i][0], route[i][1]));
}
} else {
latlngs = [];
}
var path = L.polyline(latlngs);
var marker = L.marker(latlngs[len - 1]).addTo(map).bindPopup("</br>"+"<strong>Fullname:</strong>"+" "+data.occupant_firstname+" "+data.occupant_middlename+" "+ data.occupant_lastname +"</br>" +
"<strong>Date of Birth:</strong>"+" " +data.occupant_dateofbirth + "</br>"+
"<strong>Date of Death:</strong>"+" " +data.occupant_dateofdeath + "</br>"+
"<strong>Garden:</strong>"+" " +data.garden_name + "</br>"+
"<strong>Block:</strong>"+" " +data.block_name + "</br>"+
"<strong>Lot:</strong>"+" " +data.lot_name + "</br>"+
"<strong>Longitude:</strong>"+" "+data.lot_long + "</br>"+
"<strong>Latitude:</strong>"+" "+data.lot_lat ).openPopup();
if (prev_path != null){
map.removeLayer(prev_path);
}
if(prev_marker != null){
map.removeLayer(prev_marker);
}
prev_path = path;
prev_marker = marker;
//map.removeLayer(path)
//map.addLayer(L.marker(latlngs[0]));
if(latlngs.length > 0) {
map.addLayer(marker);
}
map.addLayer(path);
setTimeout(function(){ path.snakeIn(); }, 3000);
//path.snakeIn();
});
});
});
</script>
<script>
// Creating a map object
var map = L.map('map').setView([-1.055588,2.109375],1);
var base_url = "<?=base_url()?>";
// Creating a Layer object
L.tileLayer('<?php echo base_url("user_template/map/{z}/{x}/{y}.png"); ?>',
{
minZoom: 2,
maxZoom: 4,
continousWorld: false,
noWrap: true,
}).addTo(map);
var bounds = new L.LatLngBounds(new L.LatLng(-70.020587,-132.242584), new L.LatLng(69.900118,140.680943));
map.fitBounds(bounds);
//add standard controls
L.control.coordinates().addTo(map);
//add configured controls
L.control.coordinates({
position:"bottomleft",
decimals:6,
decimalSeperator:".",
labelTemplateLat:"Latitude: {y}",
labelTemplateLng:"Longitude: {x}"
}).addTo(map); //mao ni siya bert naa diay sa taas ang code adto
/*Legend specific*/
var legend = L.control({ position: "bottomright" });
legend.onAdd = function(map) {
var div = L.DomUtil.create("div", "legend");
div.innerHTML += "<h5>Legend:</h5>";
div.innerHTML += '<i style="background: #e8851e"></i><span>Garden</span><br>';
div.innerHTML += '<i style="background: #448D40"></i><span>Block</span><br>';
div.innerHTML += '<i style="background: #ff0000"></i><span>Lot</span><br>';
return div;
};
legend.addTo(map);
var marker_1 = L.marker([-60.064840460104506,13.005095612485837]).addTo(map).bindPopup("Gate is here").openPopup();
map.addLayer(marker_1);
$.getJSON(base_url+"pages/map_gardens", function(data)
{
$.each(data, function(i, field)
{
var mapgarden_longitude_1 = parseFloat(data[0].garden_longitude1);
var mapgarden_latitude_1 = parseFloat(data[0].garden_latitude1);
var mapgarden_longitude_2 = parseFloat(data[0].garden_longitude2);
var mapgarden_latitude_2 = parseFloat(data[0].garden_latitude2);
var mapgarden_longitude_3 = parseFloat(data[0].garden_longitude3);
var mapgarden_latitude_3 = parseFloat(data[0].garden_latitude3);
var mapgarden_longitude_4 = parseFloat(data[0].garden_longitude4);
var mapgarden_latitude_4 = parseFloat(data[0].garden_latitude4);
var polylinePoints = [
[mapgarden_longitude_1, mapgarden_latitude_1],
[mapgarden_longitude_2, mapgarden_latitude_2],
[mapgarden_longitude_3, mapgarden_latitude_3],
[mapgarden_longitude_4, mapgarden_latitude_4],
[mapgarden_longitude_1, mapgarden_latitude_1]];
var polyline = L.polyline(polylinePoints).addTo(map);
});
});
$.getJSON(base_url+"pages/map_gardens", function(data)
{
$.each(data, function(i, field)
{
var mapgarden_longitude_1 = parseFloat(data[i].garden_long1);
var mapgarden_latitude_1 = parseFloat(data[i].garden_lat1);
var mapgarden_longitude_2 = parseFloat(data[i].garden_long2);
var mapgarden_latitude_2 = parseFloat(data[i].garden_lat2);
var mapgarden_longitude_3 = parseFloat(data[i].garden_long3);
var mapgarden_latitude_3 = parseFloat(data[i].garden_lat3);
var mapgarden_longitude_4 = parseFloat(data[i].garden_long4);
var mapgarden_latitude_4 = parseFloat(data[i].garden_lat4);
var mapgarden_longitude_5 = parseFloat(data[i].garden_long5);
var mapgarden_latitude_5 = parseFloat(data[i].garden_lat5);
var mapgarden_longitude_6 = parseFloat(data[i].garden_long6);
var mapgarden_latitude_6 = parseFloat(data[i].garden_lat6);
var mapgarden_longitude_7 = parseFloat(data[i].garden_long7);
var mapgarden_latitude_7 = parseFloat(data[i].garden_lat7);
var mapgarden_longitude_8 = parseFloat(data[i].garden_long8);
var mapgarden_latitude_8 = parseFloat(data[i].garden_lat8);
var mapgarden_longitude_9 = parseFloat(data[i].garden_long9);
var mapgarden_latitude_9 = parseFloat(data[i].garden_lat9);
var mapgarden_longitude_10 = parseFloat(data[i].garden_long10);
var mapgarden_latitude_10 = parseFloat(data[i].garden_lat10);
var mapgarden_longitude_11 = parseFloat(data[i].garden_long11);
var mapgarden_latitude_11 = parseFloat(data[i].garden_lat11);
var mapgarden_longitude_12 = parseFloat(data[i].garden_long12);
var mapgarden_latitude_12 = parseFloat(data[i].garden_lat12);
var mapgarden_longitude_13 = parseFloat(data[i].garden_long13);
var mapgarden_latitude_13 = parseFloat(data[i].garden_lat13);
var mapgarden_longitude_14 = parseFloat(data[i].garden_long14);
var mapgarden_latitude_14 = parseFloat(data[i].garden_lat14);
var mapgarden_longitude_15 = parseFloat(data[i].garden_long15);
var mapgarden_latitude_15 = parseFloat(data[i].garden_lat15);
var mapgarden_longitude_16 = parseFloat(data[i].garden_long16);
var mapgarden_latitude_16 = parseFloat(data[i].garden_lat16);
var polylinePoints_1 = [
[mapgarden_longitude_1, mapgarden_latitude_1],
[mapgarden_longitude_2, mapgarden_latitude_2],
[mapgarden_longitude_3, mapgarden_latitude_3],
[mapgarden_longitude_4, mapgarden_latitude_4],
[mapgarden_longitude_5, mapgarden_latitude_5],
[mapgarden_longitude_6, mapgarden_latitude_6],
[mapgarden_longitude_7, mapgarden_latitude_7],
[mapgarden_longitude_8, mapgarden_latitude_8],
[mapgarden_longitude_9, mapgarden_latitude_9],
[mapgarden_longitude_10, mapgarden_latitude_10],
[mapgarden_longitude_11, mapgarden_latitude_11],
[mapgarden_longitude_12, mapgarden_latitude_12],
[mapgarden_longitude_13, mapgarden_latitude_13],
[mapgarden_longitude_14, mapgarden_latitude_14],
[mapgarden_longitude_15, mapgarden_latitude_15],
[mapgarden_longitude_16, mapgarden_latitude_16],
[mapgarden_longitude_1, mapgarden_latitude_1]];
var polyline = L.polyline(polylinePoints_1, {
color: "#e8851e",
}).addTo(map);
});
});
$.getJSON(base_url+"pages/map_blocks", function(data)
{
$.each(data, function(i, field)
{
var mapblocks_longitude_1 = parseFloat(data[i].block_long1);
var mapblocks_latitude_1 = parseFloat(data[i].block_lat1);
var mapblocks_longitude_2 = parseFloat(data[i].block_long2);
var mapblocks_latitude_2 = parseFloat(data[i].block_lat2);
var mapblocks_longitude_3 = parseFloat(data[i].block_long3);
var mapblocks_latitude_3 = parseFloat(data[i].block_lat3);
var mapblocks_longitude_4 = parseFloat(data[i].block_long4);
var mapblocks_latitude_4 = parseFloat(data[i].block_lat4);
var polygonPoints = [
[mapblocks_longitude_1, mapblocks_latitude_1],
[mapblocks_longitude_2, mapblocks_latitude_2],
[mapblocks_longitude_3, mapblocks_latitude_3],
[mapblocks_longitude_4, mapblocks_latitude_4]];
var poly = L.polygon([polygonPoints],{
color: "green"
}).addTo(map);
});
});
$.getJSON(base_url+"pages/map_lots", function(data)
{
$.each(data, function(i, field)
{
var mapLots_longitude = parseFloat(data[i].lot_long);
var mapLots_latitude = parseFloat(data[i].lot_lat);
var circle = L.circle([mapLots_longitude, mapLots_latitude], {
color: "red",
fillColor: "#f03",
fillOpacity: 1.5,
radius: 50.0
}).addTo(map);
});
});
</script>

Vue - DOM is not updating when doing .sort() on array

I am trying to sort some JSON data using Vue. The data gets changed when checking via Vue console debugger, but the actual DOM doesn't get updated.
This is my Vue code:
Array.prototype.unique = function () {
return this.filter(function (value, index, self) {
return self.indexOf(value) === index;
});
};
if (!Array.prototype.last) {
Array.prototype.last = function () {
return this[this.length - 1];
};
};
var vm = new Vue({
el: "#streetleague-news",
data: {
allItems: [],
itemTypes: [],
itemTypesWithHeading: [],
selectedType: "All",
isActive: false,
sortDirection: "newFirst",
paginate: ['sortedItems']
},
created() {
axios.get("/umbraco/api/NewsLibraryApi/getall")
.then(response => {
// JSON responses are automatically parsed.
this.allItems = response.data;
this.itemTypes = this.allItems.filter(function (x) {
return x.Tag != null && x.Tag.length;
}).map(function (x) {
return x.Tag;
}).unique();
});
},
computed: {
isAllActive() {
return this.selectedType === "All";
},
filteredItems: function () {
var _this = this;
return _this.allItems.filter(function (x) {
return _this.selectedType === "All" || x.Tag === _this.selectedType;
});
},
sortedItems: function () {
var _this = this;
var news = _this.filteredItems;
if (_this.sortDirection === 'newFirst') {
news.sort(function (a, b) {
return new Date(b.PostDate) - new Date(a.PostDate);
});
} else {
news.sort(function (a, b) {
return new Date(a.PostDate) - new Date(b.PostDate);
});
}
return news;
}
},
methods: {
onChangePage(sortedItems) {
// update page of items
this.sortedItems = sortedItems;
}
}
});
This is an HTML part:
<paginate class="grid-3 flex" name="sortedItems" :list="sortedItems" :per="12" ref="paginator">
<li class="flex" v-for="item in paginated('sortedItems')">
The bit that seems not to be working is the sortedItems: function () {....
Can anyone see why the DOM is not updating?
The most probable is that sort() method doesn't recognize Date object precedence. Use js timestamp instead:
if (_this.sortDirection === 'newFirst') {
news.sort(function (a, b) {
var dateA = new Date(a.PostDate);
var dateB = new Date(b.PostDate);
return dateB.valueOf() - dateA.valueOf();
});
} else {
news.sort(function (a, b) {
var dateA = new Date(a.PostDate);
var dateB = new Date(b.PostDate);
return dateA.valueOf() - dateB.valueOf();
});
}
Got there eventually - thanks for your help
sortedItems: function () {
var _this = this;
var news = _this.allItems;
if (_this.sortDirection === 'newFirst') {
news.sort(function (a, b) {
var dateA = new Date(a.PostDate);
var dateB = new Date(b.PostDate);
return dateB.valueOf() - dateA.valueOf();
});
} else {
news.sort(function (a, b) {
var dateA = new Date(a.PostDate);
var dateB = new Date(b.PostDate);
return dateA.valueOf() - dateB.valueOf();
})
}
return news.filter(x => {
return _this.selectedType === "All" || x.Tag ===
_this.selectedType;
});
}

Ionic - How to create Image Blob from cordovaImagePicker.getPictures ImagePicker for S3

Using ionic,
I am trying to create an image blob from URI and have tried several codes but failed.
Here is where I implement the imagepicker in ionic:
$cordovaImagePicker.getPictures(options)
.then(function (results) {
console.log(results[0]);
var datablob = $scope.dataURItoBlob(results[0]);
technique 1 (create the blob):
$scope.dataURItoBlob = function(dataURI) {
var binary = atob(dataURI.split(',')[1]);
var array = [];
for (var i = 0; i < binary.length; i++) {
array.push(binary.charCodeAt(i));
}
var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0];
return new Blob([new Uint8Array(array)], {
type: mimeString
});
}
technique 2 (create the blob):
$scope.dataURItoBlob = function(dataURI) {
var arr = dataURI.split(','), mime = arr[0].match(/:(.*?);/)[1],
bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n);
while(n--){
u8arr[n] = bstr.charCodeAt(n);
}
return new Blob([u8arr], {type:mime});
}
Both techniques does not work. Please help! thank you very much.
$cordovaImagePicker.getPictures(options)
.then(function (results) {
console.log(results[0]);
dataURItoBlob(results[0], function(url){
var datablob = url;
}, function(error){
console.error(error);
})
})
function dataURItoBlob(path, cb, error) {
resolveLocalFileSystemURL(path, function (fileEntry) {
fileEntry.file(function (file) {
var reader = new FileReader();
reader.onloadend = function () {
if (typeof cb === 'function') {
cb(this.result)
}
};
reader.readAsDataURL(file);
}, function (err) {
if (typeof error === 'function') {
error(err)
}
});
});
}
Needs to cordova-plugin-file

d3js update with div and attributes

I am struggling with an update on d3js. The code below if uncommented does not update the values - actually, the initial layout disappears.
I cannot figure out yet. I just want the price to be updated.
Any help would be greatly appreciated.
updated
Someone (anonymous) updated http://jsfiddle.net/1qqdc0ns/11/ - so I am looking into this one.
I have cleaned my original version into http://jsfiddle.net/1qqdc0ns/12/ which still does not update properly.
function update(data) {
console.log("update " + data);
var quotes = d3.select("#quoteContainer")
.selectAll("div")
.data(data);
// ENTER
var q = quotes.enter()
.append("div")
.attr("class", "quotePanel");
var m = q.append("div").attr("class", "carmodel");
var p = q.append("div").attr("class", "price");
var f1 = p.append("span").attr("class", "bigFigure");
var f2 = p.append("span").attr("class", "smallFigure");
f1.text(function (d) {
var priceStr = d["price"].toString();
var bigFigure = priceStr.substr(0, 4);
console.log("bigFigure: " + bigFigure);
return bigFigure;
});
f2.text(function (d) {
return "00";
});
quotes.select("div").text(function (d) {
var modelname = d["symbol"];
console.log("Setting model name " + modelname);
return modelname;
});
//quotes.exit().remove();
}
function onclick() {
update([{
"symbol": "BMW",
"price": 9000
}, {
"symbol": "PIGEOT",
"price": 124
}]);
};
d3.select('#update')
.on("click", onclick);
update([{
"symbol": "ASTON",
"price": 3000
}, {
"symbol": "MARTIN",
"price": 6500
}]);
Thanks Igor.
The solution is:
http://jsfiddle.net/Ihorad/1qqdc0ns/14/
function update(data) {
var quotes = d3.select("#quoteContainer")
.selectAll(".quotePanel")
.data(data);
var q = quotes.enter()
.append("div")
.attr("class", "quotePanel");
var m = q.append("div").attr("class", "carmodel");
var p = q.append("div").attr("class", "price");
var f1 = p.append("span").attr("class", "bigFigure");
var f2 = p.append("span").attr("class", "smallFigure");
quotes.select(".carmodel").text(function (d) {
var modelname = d["symbol"];
return modelname;
});
quotes.select(".bigFigure").text(function (d) {
var priceStr = d["price"].toString();
var bigFigure = priceStr.substr(0, 4);
return bigFigure;
});
quotes.select(".smallFigure").text(function (d) {
return "00";
});
quotes.exit().remove();
}

Heatmap for multivalue variables

I am creating a heatmap using dc.js master API. My example is based on this. But the major difference is that the rows and columns have multivalues.
Below is the dataset in CSV format:
id,city,visitor,animals,food
1,NYC,854,"Lion,Tiger,Rabbit,Ape,Zebra,Monkey,Elephant,Horse","Apple,Banana,Chicken,Egg,Fish,Grape,Ham,Ice,Juice"
2,LAX,123,"Cat,Tiger,Rabbit,Ape,Whale,Bear,Zebra,Donkey,Goat,Turtle","Apple,Banana,Cake,Fish,Sugar,Bamboo,Leaf,Ham,Ice,Water"
3,LON,584,"Lion,Tiger,Ape,Shark,Panda,Zebra,Deer,Turtle,Bear,","Apple,Coke,Cake,Fish,Bamboo,Water,Grape,Orange"
4,TOR,704,"Cat,Rabbit,Ape,Whale,Bear,Panda,Donkey,Turtle,Cheetah","Banana,Cake,Orange,Kiwi,Sugar,Bamboo,Leaf,Goat,Ice,Juice"
5,SFO,855,"Lion,Tiger,Ape,Zebra,Monkey,Elephant,Donkey,Goat,Turtle,Cheetah","Apple,Cake,Grape,Ham,Juice,Hay"
6,DAL,654,"Salmon,Penguin,Rabbit,Ape,Whale,Goat,Tortoise","Apple,Banana,Cake,Ice,Water,Earthworm"
Animals and food each has multiple values. The rows are based on food and the columns are based on animals. I am able to create the heatmap but there is no interaction with other charts. For example, if I can click on a box, there is no action in the bar chart. The error message found at console is "Uncaught TypeError: Cannot read property 'all' of undefined." Here is the code.
parsecsv = function (string) {
var rows = d3.csv.parse(string);
var records = [];
rows.forEach(function (d, i) {
d.animals= d.animals.split(/,/);
d.food = d.food.split(/,/);
records.push(d)
});
return records
};
var chartGroup = "chartGroup";
var heatmapChart = dc.heatMap("#heatmap", chartGroup);
var pieChart1 = dc.pieChart("#piechart1", chartGroup);
var pieChart2 = dc.pieChart("#piechart2", chartGroup);
var barChart = dc.barChart("#barchart", chartGroup);
var ndx = crossfilter(parsecsv(csvtext));
console.log(ndx);
var animals_food_dim = ndx.dimension(function(d) { console.log (d.animals);return [d.animals, d.food]; });
var animals_food_group = animals_food_dim.groupAll().reduce(reduceAdd, reduceRemove, reduceInitial).value();
function reduceAdd(p, v) {
// skip empty values
if (v.animals[0] === "" || v.food[0]==="") return p;
v.animals.forEach (function(val1, idx1) {
v.food.forEach (function(val2, idx2) {
var temp_array=[val1,val2];
p[temp_array] = (p[temp_array] || 0) + 1; //increment counts
//console.log(val1+":"+val2, p[temp_array],temp_array);
});
});
return p;
}
function reduceRemove(p, v) {
if (v.animals[0] === "") return p; // skip empty values
v.animals.forEach (function(val1, idx1) {
v.food.forEach (function(val2, idx2) {
var temp_array=[val1,val2];
p[temp_array] = (p[temp_array] || 0) - 1; //increment counts
//console.log(val1+":"+val2,p[temp_array]);
});
});
return p;
}
function reduceInitial() {
return {};
}
animals_food_group.all = function() {
var newObject = [];
for (var key in this) {
if (this.hasOwnProperty(key) && key != "all" && key != "top") {
var temp_array=[key.substring(0,key.indexOf(",")),key.substring(key.indexOf(",")+1)];
//console.log(temp_array,this[temp_array]);
newObject.push({
key: temp_array,
value: this[temp_array]
});
}
}
return newObject;
};
animals_food_group.top = function(count) {
var newObject = this.all();
newObject.sort(function(a, b){return b.value - a.value});
return newObject.slice(0, count);
};
heatmapChart
.width(12 * 80 + 80)
.height(27 * 10 + 40)
.dimension(animals_food_dim)
.group(animals_food_group)
.keyAccessor(function(d) {return d.key[0];})
.valueAccessor(function(d) {return d.key[1];})
.colorAccessor(function(d) {return +d.value;})
.linearColors(["#FFEAEA", "#FF0000"])
.title(function(d) {
return "Animals: " + d.key[0] + "\n" +
"Food: " + d.key[1] + "\n" +
"Count: " + ( d.value) + " ";})
.calculateColorDomain();
heatmapChart.render();
var city_dim = ndx.dimension(function(d) {return d.city; });
var city_group = city_dim.group().reduceSum(function(d) {return +d.visitor;});
barChart
.dimension(city_dim)
.group(city_group)
.width(12 * 80 + 80)
.height(480)
.elasticY(true)
.x(d3.scale.ordinal().domain(["NYC","LAX","LON","TOR","SFO","DAL"]))
.xUnits(dc.units.ordinal)
.elasticY(true)
.centerBar(false)
.xAxisPadding(50);
barChart.render();
I bet I must did something wrong in reduceAdd, reduceRemove and/or animals_food_group.all. Would someone help me how to fix the interaction problem?
The JSFiddle is http://jsfiddle.net/chitester11/u33yb8k5/.

Resources