Dont want update charts dc.js - dc.js

I have chart when page load. I see normal charts with data:
Ids,Dates,Values
Бар,2018-12-21,224
Бар,2018-12-22,352
Бар,2018-12-23,61
Бар,2018-12-24,379
Бар,2018-12-25,78.2
Бар,2018-12-26,0
Бар,2018-12-27,0
Бар,2018-12-28,0
Бар,2018-12-29,0
Бар,2018-12-30,0
Бар,2018-12-31,0
Бар,2019-01-01,0
Бар,2019-01-02,0
Бар,2019-01-03,0
Бар,2019-01-04,0
Бар,2019-01-05,270
Бар,2019-01-06,0
Бар,2019-01-07,0
Бар,2019-01-08,0
Бар,2019-01-09,0
Бар,2019-01-10,0
Бар,2019-01-11,0
Бар,2019-01-12,0
Бар,2019-01-13,0
Бар,2019-01-14,0
Бар,2019-01-15,0
Бар,2019-01-16,0
Бар,2019-01-17,0
Бар,2019-01-18,0
Бар,2019-01-19,0
Бар,2019-01-20,0
But if I send ajax chart is empty, but have a data, and if I load page with this data all are correct, only ajax destroy chart:
Ids,Dates,Values
Бар,2018-11-21,178
Бар,2018-11-22,256
Бар,2018-11-23,226
Бар,2018-11-24,570
Бар,2018-11-25,266
Бар,2018-11-26,398
Бар,2018-11-27,0
Бар,2018-11-28,15
Бар,2018-11-29,80
Бар,2018-11-30,118
Бар,2018-12-01,41
Бар,2018-12-02,365
Бар,2018-12-03,180
Бар,2018-12-04,187
Бар,2018-12-05,38
Бар,2018-12-06,82
Бар,2018-12-07,390
Бар,2018-12-08,177
Бар,2018-12-09,359
Бар,2018-12-10,236
Бар,2018-12-11,7
Бар,2018-12-12,34
Бар,2018-12-13,478
Бар,2018-12-14,173
Бар,2018-12-15,290
Бар,2018-12-16,453
Бар,2018-12-17,52
Бар,2018-12-18,334
Бар,2018-12-19,0
Бар,2018-12-20,122
My js code:
$(document).ready(function() {
$('.js_dashboard').focus(function() {
allPostDataForOne($(this));
});
$('.js_dashboard').parents('.container').find('.js_dc_components').find('.js_data_graph').each(function(index, value) {
renderBar(dc.barChart("#js_graphic_" + index), d3.csv.parse(d3.select(value).text()));
});
});
function allPostDataForOne(elem) {
var table = elem.parents('.container').find('.js_main_dasboard');
$.ajax({
url: '/../index/total' + $('.js_suffix').val(),
type: 'POST',
data: 'date=' + elem.val(),
success: function(data) {
table.html($($(data)).find('.js_main_dasboard').html());
table.parents('.container').find('.js_dc_components').find('.js_data_graph').each(function(index, value) {
$($(data)).find('.container').find('.js_dc_components').find('.js_data_graph').each(function(index_res, value_res) {
if (index === index_res) {
value = value_res;
}
});
renderBar(dc.barChart("#js_graphic_" + index), d3.csv.parse(d3.select(value).text()));
});
},
})
}
function renderBar(chart, experiments) {
var start_date = new Date($('.js_start_date').val());
var end_date = new Date($('.js_end_date').val());
var format = d3.time.format("%Y-%m-%d");
experiments.forEach(function(x) {
x.Values = +x.Values;
});
var ndx = crossfilter(experiments);
var runDimension = ndx.dimension(function(d) {
return new Date(d.Dates);
});
var runGroup = runDimension.group().reduceSum(function(d) {
return d.Values;
});
chart
.width(750)
.height(300)
.x(d3.time.scale().domain([start_date, end_date]))
.brushOn(false)
.yAxisLabel(experiments[0]['Ids'])
.xAxisLabel("Date")
.dimension(runDimension)
.mouseZoomable(true)
.group(runGroup)
.title(function(d) {
return d.key.getFullYear() + '-' + parseInt(d.key.getMonth() + 1) + '-' + d.key.getDate() + ': ' + d.value;
})
chart.xUnits(function() {
return experiments.length;
});
chart.render();
}
I can't understand how to correctly update charts. I saw many quations but i cant understand how they update transform in my code.

Related

Execute multiple http request - Parse Cloud Code

i have an array of stores, where the address and some other things are stored.
Now I want to iterate through this array and geocode the lat / lng coords and save them to the database.
With the code below I get double or triple entries of the same store. Do I miss something with the scope here?
Thanks!
var promises = [];
data.forEach(function (element, index)
{
var addressString = element.plz + " " + element.stadt + "," + element.adresse;
var url = encodeURI("https://maps.googleapis.com/maps/api/geocode/json?address=" +
addressString);
var promise = Parse.Cloud.httpRequest({
method: "GET",
url:url
}).then(function (http) //SUCCESS
{
var geocodedObject = new Parse.Object("GeocodedStores");
geocodedObject.set("storeID", element.id);
geocodedObject.set("Latitude", http.data.results[0].geometry.location.lat);
geocodedObject.set("Longitude", http.data.results[0].geometry.location.lng);
return geocodedObject.save(null, {
useMasterKey: true
});
},
function (http, error)
{
response.error(error);
});
promises.push(promise);
});
return Parse.Promise.when(promises);
Finally found a working solution. It looked like it was a problem with the scope. I put the code in a seperate function and added this returned promise to an array.
var fn = function(element, geocodedObject)
{
var addressString = element.plz + " " + element.stadt + "," + element.adresse;
var url = encodeURI("https://maps.googleapis.com/maps/api/geocode/json?address=" +
addressString);
Parse.Cloud.httpRequest({
method: "GET",
url: url
}).then(function(http)
{
geocodedObject.set("storeID", element.id);
geocodedObject.set("Latitude", http.data.results[0].geometry.location.lat);
geocodedObject.set("Longitude", http.data.results[0].geometry.location.lng);
geocodedObject.set("address", addressString);
return geocodedObject.save(null, {
useMasterKey: true
});
});
}
var promises = [];
for (var k = 0;k<data.length;k++)
{
var geocodedObject = new Parse.Object("GeocodedStores");
promises.push(fn(data[k], geocodedObject));
}
Parse.Promise.when(promises).then(function () {
response.success("DONE");
});

D3-request retrieval of a google spreadsheet csv/json file fails

I have difficulties to make Google spreadsheet and D3js' D3-request / D3-request > header works together via xhr requests.
I use the following JS :
d3.request(url)
.header("X-Requested-With", "XMLHttpRequest")
.mimeType("text/csv")
.get(function(error, data) {
if (error) throw error;
console.log('request: '+ data);
});
I get the following error:
XMLHttpRequest cannot load https://docs.google.com/spreadsheets/d/e/2PACX-1vSZyV9olwK_hx0BRFgLtTz5hs_Z…mROYhax3VD9AFXTvmcataf8LuSIpxGT2/pub?gid=1023695213&single=true&output=csv. Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'https://fiddle.jshell.net' is therefore not allowed access.
Jsfiddle here
Any idea to bypass it ?
Using D3 only
d3.json(url, function (error, result) {
var data = [];
for (i = 0; i < result.feed.entry.length; i += 1) {
data.push({
"animal": result.feed.entry[i].gsx$animal.$t,
"population": result.feed.entry[i].gsx$population.$t
});
}
pie_chart(data, "#chart1");
});
Using jQuery
$.get(url, function (result) {
var data = [];
$(result.feed.entry).each(function () {
data.push({"animal": this.gsx$animal.$t, "population": this.gsx$population.$t});
});
pie_chart(data, "#chart2");
});
Using tabletop.
Tabletop.init({
key: key,
callback: function (data, tabletop) {
pie_chart(data, "#chart3");
},
simpleSheet: true
});
Below is just a simple example to get data from a Google spreadsheet and turn it into a D3 pie chart.
//draws a pie chart with D3
function pie_chart(data, id) {
var w = 400;
var h = 400;
var r = h / 2;
var color = d3.scale.category20c();
var vis = d3.select(id).append("svg:svg").data([data]).attr("width", w).attr("height", h).append("svg:g").attr("transform", "translate(" + r + "," + r + ")");
var pie = d3.layout.pie().value(function (d) {
return d.population;
});
var arc = d3.svg.arc().outerRadius(r);
var arcs = vis.selectAll("g.slice").data(pie).enter().append("svg:g").attr("class", "slice");
arcs.append("svg:path")
.attr("fill", function (d, i) {
return color(i);
})
.attr("d", function (d) {
return arc(d);
});
arcs.append("svg:text").attr("transform", function (d) {
d.innerRadius = 0;
d.outerRadius = r;
return "translate(" + arc.centroid(d) + ")";
}).attr("text-anchor", "middle").text(function (d, i) {
return data[i].animal;
});
}
//the key of google spreadsheet
var key = "1moczdbrfFwCp0L4Ube1a4GevuDcj2XQmCnpjArF_UEY";
//the url for jQuery and D3
var url = "https://spreadsheets.google.com/feeds/list/" + key + "/od6/public/values?alt=json";
var i = 0;
//D3 only
d3.json(url, function (error, result) {
var data = [];
for (i = 0; i < result.feed.entry.length; i += 1) {
data.push({
"animal": result.feed.entry[i].gsx$animal.$t,
"population": result.feed.entry[i].gsx$population.$t
});
}
pie_chart(data, "#chart1");
});
//Jquery
$.get(url, function (result) {
var data = [];
$(result.feed.entry).each(function () {
data.push({"animal": this.gsx$animal.$t, "population": this.gsx$population.$t});
});
pie_chart(data, "#chart2");
});
//tabletop
Tabletop.init({
key: key,
callback: function (data, tabletop) {
pie_chart(data, "#chart3");
},
simpleSheet: true
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/tabletop.js/1.4.3/tabletop.js"></script>
<div id="chart1" style="width: 480px; height: 400px;"><span>D3 only</span></div>
<hr>
<div id="chart2" style="width: 480px; height: 400px;"><span>Jquery</span></div>
<hr>
<div id="chart3" style="width: 480px; height: 400px;"><span>Tabletop</span></div>

show percentage in d3 pie chart

currently my pie chart in d3 shows the sum of numbers,i want percentage instead .
for eg: currently i have a pie chart for how many people submitted application who visited our site. our current pie chart shows like this : people submitted 17,000 and people didn't submitted-10,000
but i need this in percentage also. how can i get that.
please find the pie code below and let me know what changes do i need to make this work. I am new to JavaScript and D3.
ko.bindingHandlers.pieChart = {
init: function (element, valueAccessor) {
var _options = valueAccessor();
var _data = _options.transformer(_options.data);
$(element).css("marginLeft", "auto");
$(element).css("marginRight", "auto");
if (typeof _options.maxWidth != "undefined") {
var _max = _options.maxWidth * 1;
$(element).width(Math.min($(element).parent().width(), _max));
}
if ($(element).find("svg").length > 0 && _data.length == 0) {
$(element).find("svg").empty();
}
if (_data.length > 0 && isNaN(_data[0].value)) {
_data = [];
$(element).find("svg").empty();
}
if ($(element).is(":visible")) {
nv.addGraph(function () {
var _chart = nv.models.growingPieChart()
.x(function (d) {
return d.label
})
.y(function (d) {
return d.value
})
.height($(element).width())
.showLabels(true).showLegend(false)
.tooltipContent(function (key, y, e, graph) {
return '<h3>' + hueUtils.htmlEncode(key) + '</h3><p>' + y + '</p>'
});
var _d3 = ($(element).find("svg").length > 0) ? d3.select($(element).find("svg")[0]) : d3.select($(element)[0]).append("svg");
_d3.datum(_data)
.transition().duration(150)
.each("end", _options.onComplete != null ? _options.onComplete : void(0))
.call(_chart);
if (_options.fqs) {
$.each(_options.fqs(), function (cnt, item) {
if (item.id() == _options.data.widget_id && item.field() == _options.field()) {
_chart.selectSlices($.map(item.filter(), function (it) {
return it.value();
}));
}
});
}
$(element).data("chart", _chart);
var _resizeTimeout = -1;
nv.utils.windowResize(function () {
window.clearTimeout(_resizeTimeout);
_resizeTimeout = window.setTimeout(function () {
_chart.update();
}, 200);
});
$(element).on("forceUpdate", function () {
_chart.update();
});
$(element).height($(element).width());
var _parentSelector = typeof _options.parentSelector != "undefined" ? _options.parentSelector : ".card-widget";
$(element).parents(_parentSelector).on("resize", function () {
if (typeof _options.maxWidth != "undefined") {
var _max = _options.maxWidth * 1;
$(element).width(Math.min($(element).parent().width(), _max));
}
$(element).height($(element).width());
_chart.update();
});
return _chart;
}, function () {
var _d3 = ($(element).find("svg").length > 0) ? d3.select($(element).find("svg")[0]) : d3.select($(element)[0]).append("svg");
_d3.selectAll(".nv-slice").on("click",
function (d, i) {
if (typeof _options.onClick != "undefined") {
chartsUpdatingState();
_options.onClick(d);
}
});
});
}
},
update: function (element, valueAccessor) {
var _options = valueAccessor();
var _data = _options.transformer(_options.data);
var _chart = $(element).data("chart");
if (_chart) {
var _d3 = d3.select($(element).find("svg")[0]);
_d3.datum(_data)
.transition().duration(150)
.each("end", _options.onComplete != null ? _options.onComplete : void(0))
.call(_chart);
if (_options.fqs) {
$.each(_options.fqs(), function (cnt, item) {
if (item.id() == _options.data.widget_id && item.field() == _options.field()) {
_chart.selectSlices($.map(item.filter(), function (it) {
return it.value();
}));
}
});
}
chartsNormalState();
}
else if (_data.length > 0) {
ko.bindingHandlers.pieChart.init(element, valueAccessor);
}
}
};
A fiddle would be useful to test this against (hint hint), but I'm pretty sure you want to change this line:
.y(function (d) {
return d.value
})
to this
.y(function (d) {
return d.value/total
})
You may have to define total. Like I said, without a jsfiddle or at least some indication of the format of your data, it's hard to determine if this is actually what's wrong or how to fix it.
Note: a pie chart of relative percentages will look exactly the same as a pie chart of the original numbers. You might be able to change the label and only the label, as follows:
return '<h3>' + hueUtils.htmlEncode(key) + '</h3><p>' + y + '</p>'
to this
return '<h3>' + hueUtils.htmlEncode(key) + '</h3><p>' + (y/total) + '</p>'
Hopefully both of those should work. You will have to define total, if it isn't already defined elsewhere. If not:
var total = 0;
_data.forEach(function(d){total += d.value});
Good luck!
It would be even more helpful to include information such as the library you are using and a fully reproducible example using a gist, codepen, jsfiddle, etc. I am guessing you are using hue and more specifically growingPieChart. If my guesses are correct, then you can modify your tooltipContent function similar to #Vyross answer that posted while I was typing this.
.tooltipContent(function (key, y, e, graph) {
return '<h3>' + hueUtils.htmlEncode(key) + '</h3><p>' +
(+y) / d3.sum(
d3.select(graph.container).select('g').datum(),
function(d){return d.value}
) +
'</p>'
});

searchCallBack is not defined in Rotten Tomatoes API search

I am trying to do a search on the Rotten Tomatoes website for their movies and when I try to type in 'TOY' I got a searchCallBack that is not defined the search should return movies that have the word Toy in them. I am completely new to AJAX by the way. I found that error in the developers tools console.
here is the code:
$(function () {
// You will need this API key in order to call the Rotten Tomatoes API.
var apiKey = *removed for security purposes;
var baseUrl = "http://api.rottentomatoes.com/api/public/v1.0";
var moviesSearchUrl = baseUrl + '/lists/movies/box_office.json?apikey=' + apiKey
document.getElementById('searchBox').addEventListener('keydown', function (event) {
if (event.which === 13 || event.keyCode === 13) {
var searchText = this.value;
$(document).ready(function () {
$.ajax("http://api.rottentomatoes.com/api/public/v1.0/movies.json", {
q: 'TODO put in search text',
page_limit: 10,
page: 1,
success: seachCallBack(),
dataType: 'jsonp'
});
});
// callback for when we get back the results
function searchCallback(data) {
var movies = data.movies;
$.each(movies, function (index, movie) {
$(document.body).append('<h1>' + movie.title + '</h1>');
$(document.body).append('<img src="' + movie.posters.thumbnail + '" />');
});
}
}
});
});
In your Ajax request callback, you have misspelled the function "seachCallBack." If you spell it correctly it should work. It should be "searchCallback"
$(function () {
var apiKey = "removed for security purposes";
var baseUrl = "http://api.rottentomatoes.com/api/public/v1.0";
var moviesSearchUrl = baseUrl + '/lists/movies/box_office.json?apikey=' + apiKey
function keydownHandler(evt) {
if (event.which === 13 || event.keyCode === 13) {
var searchText = this.value;
$.ajax("http://api.rottentomatoes.com/api/public/v1.0/movies.json", {
q: search text,
page_limit: 10,
page: 1,
success: searchCallback,
dataType:"json"
});
}
}
// callback for when we get back the results
function searchCallback(data) {
var movies = data.movies;
$.each(movies, function (index, movie) {
$(document.body).append('<h1>' + movie.title + '</h1>');
$(document.body).append('<img src="' + movie.posters.thumbnail + '" />');
});
}
$('#searchBox').addEventListener('keydown', keydownHandler);
});

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