How to display data from server in pie chart? - javascript

I want to display data in pie chart. Data is retrieved from server in JSON format i.e. single int value and I want to display it using pie chart. Suppose that data is 66, then i want to show that 66% full in pie chart.
I have retrieved data but not able to find the function in javascript to accept data
For Ex. :
$(function(){
$("#doughnutChart").drawDoughnutChart([
{ title: "Full", value: 66, color: "#FC4349" },
{ title: "Empty", value: 34, color: "#6DBCDB" },
]);
});`
Then instead of already defined values in above function i want to accept value from server and display in pie chart.
in index.html I added statement
<script>
$(document).ready(function(){
$("button").click(function(){
$.getJSON('http://api.thingspeak.com/channels/79448/feed/last.json?callback=?', function(data){
$("div").append(data.field1 + " ");
});
**var x=data.field1;**
});
});
</script>
This is my index.js file :
$("#doughnutChart").drawDoughnutChart( dataFromServer);
`$(function(){
`$("#doughnutChart").drawDoughnutChart([
{ title:"Full" value: dataFromServer.y1, color: "#FC4349" },
{ title: "Empty" value: dataFromServer.y2, color: "#6DBCDB" },
]);
});`
`var formattedData = [];`
// "dataFromServer" contains an array of differently-formatted objects
for ( var i = 0; i < dataFromServer.length; i++ ){
formattedData.push({
value: dataFromServer[i].y,
});
}
$("#doughnutChart").drawDoughnutChart( formattedData );
So please tell me is this way i should write in index.js file???
dataFromServer.y1=x; Please suggest me the correct way.

This depends upon the form of your data. A;; you're going to do is use variables instead of literals. For instance, if your data is an array of objects with a title, value, and color, you could just call:
// "dataFromServer" is an array of appropriately formatted objects
$("#doughnutChart").drawDoughnutChart( dataFromServer);
If, on the other hand, you have a complex object you need to map out, you could do it explicitly like so:
// "dataFromServer" contains all of the right data, but in different locations
$("#doughnutChart").drawDoughnutChart([
{ title: dataFromServer.x1, value: dataFromServer.y1, color: dataFromServer.z1 },
{ title: dataFromServer.x2, value: dataFromServer.y2, color: dataFromServer.z2 },
]);
Most likely you will have an array of differently formatted object, which you will want to turn into an array of objects formatted in this manner, in which case you would want to loop through the objects from the server and create a new variable from them:
// formattedData is the array that will be passed into the chart
var formattedData = [];
// "dataFromServer" contains an array of differently-formatted objects
for ( var i = 0; i < dataFromServer.length; i++ ){
formattedData.push({ title: dataFromServer[i].x,
value: dataFromServer[i].y,
color: dataFromServer[i].z });
}
$("#doughnutChart").drawDoughnutChart( formattedData );
Addendum:
Upon comment clarification, I am adding the following. Assuming the Title and Color values are static (i.e. not coming from the database), you may simply insert the integer "values" into the code directly, like so:
// "mySanFranciscoDataValue" is the single integer you're trying to insert
// into the chart. Simply reference it directly, whether it's a
// variable or a function. Presumably you will have two of them,
// one for each city, so I've included a "myNewYorkDataValue" too.
$("#doughnutChart").drawDoughnutChart([
{ title: "San Francisco", value: mySanFranciscoDataValue, color: "#FC4349" },
{ title: "New York", value: myNewYorkDataValue, color: "#6DBCDB" },
]);

Related

Pass python dictionary to javascript

I have a Python + JS application connected to a PostgreSQL database. The database contains data about users in different countries, which is queried by the server.py file. The result of this query is a dictionary that would look something like this:
{'US': 2,
'CA': 5}
This dictionary needs to be passed to my map.js file, which populates a world map according to the country code (key) and volume (value). This dictionary updates with user activity, so it needs to be passed every time someone loads the map.
How can I pass the data over? It seems like I need to create a JSON file. I'm not sure how to create that file within python or how to call it from javascript.
I want to replace the hardcoded 'var data' values from map.js with my query results from country_count on server.py.
my server.py:
#app.route("/map")
def show_mapjs():
country_count = {
"US": 0, "CA": 0,
}
country_code = session.get("country_code")
for country_code, _ in country_count.items():
records_count = User_Records.query.filter_by(country_code=country_code).count()
country_count[country_code] = records_count
print(f"=== {country_count}")
return country_count
(US & CA are initialized at 0 and the records_count query updates the count as user activity increases over time.)
my map.js:
fetch('/map')
anychart.onDocumentReady(function () {
var data = [
{'id': 'US', 'value': 5},
{'id': 'CA', 'value': 2}
]
var dataSet = anychart.data.set(data);
var mapData = dataSet.mapAs({ description: 'description' });
var map = anychart.map();
what a fun project!
Let's get the work under way.
On your server side,
import json
#app.route('/map')
def show_mapjs():
country_count = {
"US": 0, "CA": 0,
}
#place your own code here to get the data from the database#
country_list = []
for country, count in country_count.items():
country_list.append({"id": country, "value": count})
# Serializing json
json_object = json.dumps(country_list)
return json_object
On your client side,
First, include the below js libs in the HTML, so the next code can use it.
<script src="https://cdn.anychart.com/releases/8.11.0/js/anychart-core.min.js" type="text/javascript"></script>
<script src="https://cdn.anychart.com/releases/8.11.0/js/anychart-map.min.js" type="text/javascript"></script>
<script src="https://cdn.anychart.com/geodata/latest/custom/world/world.js"></script>
<script src="https://cdn.anychart.com/releases/v8/js/anychart-data-adapter.min.js"></script>
Use the map js function as below,
<script>
anychart.onDocumentReady(function () {
anychart.data.loadJsonFile("/map",
function (data) {
var map = anychart.map();
map.geoData(anychart.maps.world);
var dataSet = anychart.data.set(data);
// set the series
var series = map.choropleth(dataSet);
// disable labels
series.labels(false);
// set the container
map.container('container');
map.draw();
}
);
});
</script>
You should do this way to avoid out-of-sync data loading and map rendering. This will ensure that the json is downloaded and then processed by the map.
Let me know if you have issues getting this working.

How can I make this JSON.stringify work properly

I have a small issue to make my arrays into the json I want to. I have made this code:
var arrData = [{label:Test,value:199.12}, {label:Test2,value:1024}]
var data = [];
for (var i = 0; i < arrData.length; i++) {
data.push(JSON.stringify({
label: arrData[i][2],
value: arrData[i][3]
}).replace(/\"/g, "").replace("\\r", ""))
}
It also does the job properly. But I do want it to be in this format:
{ label: 'Food', value: 90 },
I want to have the ' ' on the label data and I want to remove the double "" punctuation mark outside the json. Since my current json looks like this:
"{label:Test,value:199.12}", "{label:Test2,value:1024}",
{ label: 'Food', value: 90 } isn't valid JSON so you cannot create it using JSON.stringify.
It isn't any standard serialisation format (although it is a valid JavaScript literal) so if you want to serialise data to it, you'll need to write a custom serialiser.
You could loop over the properties of the object and append them, the associated values, and whatever quotes and commas your format demands, to a string.

Jquery: Autocomplete with label

I am trying to learn website development.
While learning autocomplete feature of jquery, I tried to put in the labels.
function autocomplete (data) {
var data = data.toString();
var availableTags = data.split(',');
var autocompleteData = [];
for (var i = 0; i < availableTags.length; i++){
autocompleteData[i] = {};
autocompleteData[i].label = i.toString();
autocompleteData[i].value = availableTags[i];
}
$("#tags").autocomplete({
source: autocompleteData,
select: function (event, ui) {
printautocomplete(event, ui)
}
});
};
The autocomplete[i].value is a valid string.
autocompleteData[0]
Object {label: 0, value: "Peter"}
However, I do not see any suggestions.
What is wrong with the way I am using the API?
The API says:
"Array: An array can be used for local data. There are two supported formats:
An array of strings: [ "Choice1", "Choice2" ]
OR An array of objects with label and value properties: [ { label: "Choice1", value: "value1" }, ... ]
The label property is displayed in the suggestion menu. The value will be inserted into the input element when a user selects an item. If just one property is specified, it will be used for both, e.g., if you provide only value properties, the value will also be used as the label. "
Thank you.
$('#sidebarSearch').autocomplete(
{
source: function(query, result)
{
var query = $('#sidebarSearch').val ();
$.ajax(
{
url:"sidebarSearchFetch.php",
method:"POST",
data:{query:query},
dataType:"json",
success:function(data)
{
result($.map(data, function(item)
{
return {
label: item.name,
value: item.usrId
};
}));
}
})
},
appendTo: "#sidebar-form"
});
I am skeptical of line 2 in your code (var data = String()data;) I would use: var data = data.toString();
But if you are sure that the autocompleteData elements do indeed have valid strings, then my best guess would be that perhaps you forgot to give the '#tags' id to your html entry field element.
Finally, if this is not it, to troubleshoot, I would try removing the select: option from the object you are passing to autocomplete() in the line that begins: $("#tags").autocomplete(... so that only the source options is passed.
Another thing to check out is when the code is being run. It is possible that a document.ready() function is needed to ensure that that when the autocomplete feature is added to the DOM element with the id '#tags', that the element has already been created.
The autocomplete works fine. Instead of completing "value", it completes "label".
So when I type in "1", it suggests "1", "10", "11", etc.
Autocomplete applying value not label to textbox answers how to change to to by-value.

Iteration through ajax data is working time to time

I wrote small calculator on python, using flask framework. I created forms in template, in which I gather specific data with Javascript and using .getJSON, I achieve working ajax. Here's code. (Using jQuery as well)
$(document).ready(function() {
$(function() {
$('.btn#population').bind('click', function() {//Only one button.
$( ".faction" ).each(function(x) {//Loops through many forms, which all are class .faction
var totals = [];//For late r use. Store gathered data.
$.getJSON('/_population', {//Parse data to python.
faction: $(this).attr('id'),
houses: $(this).find('input[name="houses"]').val(),
level: $(this).find(':radio:checked').val(),
space: $(this).find('.space').prop( "checked" ),
senate: $(this).find('.senate').prop( "checked" )
},
function(data) {//Receive data. give it to next functions.
$.merge(totals, data.result);
/*$.each(data, function(i, item){
item.forEach(function(number){
//console.log(number);
totals.push(number);
});
}); This is commented, due experiments.*/
});
console.log(totals);
$(this).find('input[name="total"]').each(function(i,val) {//Search for fields in forms, wich will store resoults. (Doesn't used for data gathering in this global function.)
$(this).val();//Here I'll itter througt totals and change values of inputs.
});
});
return false;
});
});
});
Forms are consisted of various inputs, but it's not important. /_population route has python script, which returns basic json array, consisting only numbers, usually, 3 or 4, like [0,0,0,0] or [120,140,300].
My aim is to put each of item of an returned array and put it in input fields in template. As you can see in code, it loops through many forms, and returned array items will goes to some of them. For now, I'm stuck at point, where console shows me very weird behaviour, sometimes it makes proper arrays, sometimes not.
Here's the example of Firefox console output.
Array [ ] functions.js:23
Array [ ] functions.js:23
Array [ ] functions.js:23
Array [ 40, 120, 300, 0 ] functions.js:23
Array [ 72, 540, 0, 0 ] functions.js:23
Array [ 30, 210, 100 ] functions.js:23
Array [ ] functions.js:23
Array [ ] functions.js:23
Array [ ] functions.js:23
Array [ 40, 120, 300, 0 ] functions.js:23
Array [ 72, 540, 0, 0 ] functions.js:23
Array [ 30, 210, 100 ] functions.js:23
(It's irregular at random manner.)
What would be a problem, why it's so and how to fix it?
You could store all the ajax calls in an array and use $.when to get a callback when everything is done and then iterate over the elements and set the value.
It's hard to test this, but something close to this should work.
$(function() {
$('#population').on('click', function(e) {
e.preventDefault();
var xhr = [];
$( ".faction" ).each(function(i, el) {
xhr.push(
$.getJSON('/_population', {
faction : el.id,
houses : $(el).find('input[name="houses"]').val(),
level : $(el).find(':radio:checked').val(),
space : $(el).find('.space').is( ":checked" ),
senate : $(el).find('.senate').is( ":checked" )
})
);
});
$.when.apply(undefined, xhr).done(function() {
var arg = [].slice.call(arguments);
$(this).find('input[name="total"]').val(function(i,val) {
return arg[i].responseText;
});
});
});
});
I'm sorry, but as it always happens to me, I thought pretty simple fix to problem. As #lan mentioned, getJSON is asynchronus, I thought, that then I should do all fucntions, while I have response, not after I get it. Here's my modified script. Commentaries included.
$(document).ready(function() {
$(function() {
$('.btn#population').bind('click', function() {
$( ".faction" ).each(function(x) {
//Here will answers be shown.
var answers = $(this).find('input[name="total"]');
$.getJSON('/_population', {
faction: $(this).attr('id'),
houses: $(this).find('input[name="houses"]').val(),
level: $(this).find(':radio:checked').val(),
space: $(this).find('.space').prop( "checked" ),
senate: $(this).find('.senate').prop( "checked" )
},
function(data) {
//Gathered data is stored directly in response function.
var totals = [];
//I guess ,can be done by merge too, but for now, I'll leave it like that.
$.each(data, function(i, item){
item.forEach(function(number){
totals.push(number);
});
});
//Here previously gathered answer input fields are used for purpose.
answers.each(function(y,val) {
$(this).val(totals[y]);
});
});
});
return false;
});
});
});

Updating D3.js (NVD3.js) Data by Merge

I'm working on some realtime graphs built with NVD3.js. I currently refresh each chart with the following:
function reDraw(c) {
d3.json(c.qs, function(data) {
d3.select(c.svg)
.datum(data)
.transition().duration(500)
.call(c.chart);
});
}
c looks like:
function Chart(svg, qs, chart) {
this.qs = qs;
this.svg = svg;
this.ylabel;
this.chart;
}
This works fairly well, but with each refresh I am fetching the whole time series again. It would be more efficient to only grab recent elements and update each graph. There are examples of doing this by appending elements (This answer NVD3 line chart with realtime data and this tutorial for example) , but this isn't ideal for me since some recent elements might be updated that are not the most recent element.
So what I'm looking to do is grab say the most recent minute (by setting query string (.qs) to only get the most recent minute, then take that result and do the following:
Overwrite any existing elements that have the same x value for each series with the most recent data
Append and elements when there are new x values from the update in each series
Expire elements past a certain age
Update the NVD3.js script with the new data. Maybe still use datum with the new merged object?
Can anyone suggest an elegant way to perform the above Merge operation? The existing data object looks like the following:
> d3.select(perf.svg).data()[0]
[
Object
key: "TrAvg"
values: Array[181]
__proto__: Object
,
Object
key: "RedisDurationMsAvg"
values: Array[181]
__proto__: Object
,
Object
key: "SqlDurationMsAvg"
values: Array[181]
__proto__: Object
]
> d3.select(perf.svg).data()[0][0]['values'][0]
Object {x: 1373979220000, y: 22, series: 0}
> d3.select(perf.svg).data()[0][1]['values'][0]
Object {x: 1373979650000, y: 2, series: 1}
The object returned would look something like the following (Except will only be maybe 6 elements or so for each object):
> d3.json(perf.qs, function(data) { foo = data })
Object {header: function, mimeType: function, response: function, get: function, post: function…}
> foo
[
Object
,
Object
,
Object
]
> foo[0]
Object {key: "TrAvg", values: Array[181]}
> foo[0]['values'][0]
Object {x: 1373980220000, y: 49}
In this newer object the series value is missing - maybe that needs to get added or perhaps D3 can do it?
For the time being I used linq.js to perform this operation, and then use .datum() to bind a new dataset each time. The solution isn't very elegant but it does seem to function:
function reDraw2(c, partial) {
if (partial) {
qs = c.qs.replace(/minago=[0-9]+/, "minago=1")
} else {
qs = c.qs
}
d3.json(qs, function(new_data) {
chart = d3.select(c.svg)
if (c.ctype == "ts" && partial) {
thirtyminago = new Date().getTime() - (60*30*1000);
old_data = chart.data()[0]
var union = new Array();
for (var i = 0; i < old_data.length; i++) {
var existing = Enumerable.From(old_data[i]['values']);
var update = Enumerable.From(new_data[i]['values']);
oldfoo = existing
newfoo = update
var temp = {}
temp['key'] = old_data[i]['key']
temp['values'] = update.Union(existing, "$.x").Where("$.x >" + thirtyminago).OrderBy("$.x").Select().ToArray();
union[i] = temp
}
chart.datum(union)
} else {
chart.datum(new_data)
}
chart.call(c.chart)
});

Categories

Resources