JQPlot: Plot series and labels from an external source - ajax

I am working with JQPlot to generate a chart pulling data from a database, like in the example here http://www.jqplot.com/tests/data-renderers.php.
The chart is working fine, but at the moment the series labels are hard coded. How can I make this chart to display the series labels from the database too, just like the series? I assume I need to make a new call, to a second file containing the label names, but I am not really sure how to do that. Any ideas?
Here is the code I am using:
$(document).ready(function(){
var ajaxDataRenderer = function(url, plot) {
var ret = null;
$.ajax({
async: false,
url: url,
dataType:'json',
success: function(data) {
ret = data;
}
});
return ret;
};
var jsonurl = "./index.php";
$.jqplot.config.enablePlugins = true;
plot1 = $.jqplot('chart1', jsonurl,{
dataRenderer: ajaxDataRenderer,
title: 'Annual Balance Summary',
legend: {show:true, renderer:$.jqplot.EnhancedLegendRenderer},
seriesDefaults: {lineWidth:4},
**series:[{label:'Tilikausi 01/2009 - 12/2009'}, {label:'Tilikausi 01/2010 - 12/2010'}, {label:'Tilikausi 01/2011 - 12/2011'}]**, // THIS ARE THE VALUES I WANT TO BRING FROM THE DATABASE
showMarker:true,
pointLabels: { show:true },
axes: {
xaxis: {pad:1, numberTicks:12, tickInterval: 1, autoscale:true, tickOptions:{formatString:'%d', fontSize:'10pt', fontFamily:'Tahoma', angle:-40, fontWeight:'normal'}}},
highlighter: {bringSeriesToFront: true}
});
});
The outcoming json array of the index.php, look like this:
[[[0,413010.71],[1,431586.96],[2,418659.56],[3,418776.76],[4,409203.91],[5,392167.56],[6,547296.04],[7,529292.86],[8,523009.35],[9,541452.97],[10,535397.58],[11,555497.48],[12,465849.17]],[[0,465849.17],[1,464569.69],[2,468339.1],[3,471005.39],[4,470786.79],[5,472315.46],[6,492847.16],[7,495973.32],[8,520188.21],[9,550497.27],[10,544294.18],[11,559081.4],[12,479558.69]],[[0,479558.69],[1,467694.94],[2,459592.48],[3,476012.25],[4,463623.8],[5,487588.68],[6,445992.44],[7,457935.72],[8,481076.75],[9,498464.53],[10,508681.42],[11,523928.66],[12,548180.15]]]
The array for the series labels should be something like this:
[["Tilikausi 01\/2009 - 12\/2009"],["Tilikausi 01\/2010 - 12\/2010"],["Tilikausi 01\/2011 - 12\/2011"]] // Array of series labels
Thanks in advance for your answers!

I think the key to this one is getting the JSON structured correctly that is retrieved by index.php.
Currently you are returning this:
[[[0,413010.71],[1,431586.96],[2,418659.56],[3,418776.76],[4,409203.91],[5,392167.56],[6,547296.04],[7,529292.86],[8,523009.35],[9,541452.97],[10,535397.58],[11,555497.48],[12,465849.17]],[[0,465849.17],[1,464569.69],[2,468339.1],[3,471005.39],[4,470786.79],[5,472315.46],[6,492847.16],[7,495973.32],[8,520188.21],[9,550497.27],[10,544294.18],[11,559081.4],[12,479558.69]],[[0,479558.69],[1,467694.94],[2,459592.48],[3,476012.25],[4,463623.8],[5,487588.68],[6,445992.44],[7,457935.72],[8,481076.75],[9,498464.53],[10,508681.42],[11,523928.66],[12,548180.15]]]
But what you really need is something like this (some elements of values omitted for brevity):
{
values: [[[0,413010.71],[1,431586.96],[2,418659.56],[3,418776.76], ... [12,548180.15]]],
labels: [["Tilikausi2 01\/2009 - 12\/2009"],["Tilikausi2 01\/2010 - 12\/2010"],["Tilikausi2 01\/2011 - 12\/2011"]]
}
The tricky thing is that labels are assigned to a series when the graph is created. This causes a problem because it really means that the Ajax call must happen prior to creating the graph.
Given the Json as structured above, something like this should do the trick:
$.jqplot.config.enablePlugins = true;
var jsonurl = "./index.php";
//Get the data prior to creating the graph.
var plotData = ajaxDataRenderer(jsonurl);
//plotData.values is now passed in to be the actual data the plot is created from.
plot1 = $.jqplot('chart1', plotData.values, {
title: 'Annual Balance Summary',
legend: {show:true, renderer:$.jqplot.EnhancedLegendRenderer},
seriesDefaults: {lineWidth:4},
//The series labels can now be supplied.
series: plotData.labels,
showMarker:true,
pointLabels: { show:true },
axes: {
xaxis: {pad:1, numberTicks:12, tickInterval: 1, autoscale:true, tickOptions:{formatString:'%d', fontSize:'10pt', fontFamily:'Tahoma', angle:-40, fontWeight:'normal'}}},
highlighter: {bringSeriesToFront: true}
});
Edit:
The other thing you will need to do is modify the labels array that comes back. We are still using the ajaxDataRenderer function, so just after you have received the data you will need to do this:
for(var i = 0; i < data.labels.length; i++) {
data.labels[i] = { label: data.labels[i][0] };
}
All this does is create the kind of object literal that jqplot is expecting when you are specifying labels.
Edit 2:
If your JSON looks like:
[[["Tilikausi 01\/2009 - 12\/2009"],["Tilikausi 01\/2010 - 12\/2010"],
["Tilikausi 01\/2011 - 12\/2011"]],[[[1,-4308.6],[2,-11725.18],[3,-23253.57],
...,[10,-85437.15],[11,-10‌​5465.7],[12,-129859.38]]]]
Then it should still work, but you would need to refer to things differently. Instead of plotData.values you would have plotData[1], and instead of plotData.labels you would have plotData[0].
Also, the label rearrangement code would instead look like:
for(var i = 0; i < data[0].length; i++) {
data[0][i] = { label: data[0][i][0] };
}

Read your values in a javascript array and use it to display values in the legend using the following code-snippet:
legend:{
show: true,
location: 'ne',
placement: "outside",
labels: companies
}

Related

Slick grid values not populating in the grid

I am trying to populate slick grid it is showing the values while debugging but not showing in the web page.
I have added all the required references. Here is the js function.
function LoadMonthStatus(dropdownYear, buttonId) {
try {
$(".screen").css({ opacity: 0.5 });
$(".slick-cell").css({ opacity: 0.5 });
dirtyFlag = false;
var drpYear = document.getElementById(dropdownYear);
year = drpYear.options[drpYear.selectedIndex].value;
data = [];
var dropdownoptions = ""; // "hard,soft,closed";
var columns = {};
var options = {
editable: true,
enableCellNavigation: true,
asyncEditorLoading: false,
autoEdit: true,
autoHeight: true
};
columns = [
{ id: "month", name: "Month", field: "Month", width: 250 },
{ id: "status", name: "Close Status", field: "Status", options: columnOptions, editor: Slick.Editors.Select, width: 150 }
];
$.ajax({
type: "GET",
url: "http://localhost:51072/PULSE.Service/api/MonthCloseStatus/LoadMonths",
data: { year: $("#drpYear").val() },
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (msg) {
data = msg;
monthStatusGrid = new Slick.Grid("#slkgrdMonths", data, columns, options);
//grid.setSelectionModel(new Slick.CellSelectionModel());
monthStatusGrid.onCellChange.subscribe(function (e, args) {
var cell = monthStatusGrid.getCellNode(args.row, args.cell);
cell.className += cell.className ? ' slick-cell-modified' : 'slick-cell-modified';
dirtyFlag = true;
});
if (msg == null || msg == "")
document.getElementById(buttonId).disabled = true;
else
document.getElementById(buttonId).disabled = false;
//Enable the button
$(".screen").css({ opacity: 1 });
$(".slick-cell").css({ opacity: 1 });
},
error: function (xhr, textStatus, errorThrown) {
try {
var err = JSON.parse(xhr.responseText);
jAlert(err.Message, 'PULSE');
}
catch (e) {
jAlert(clientErrMessage, 'PULSE');
}
$(".screen").css({ opacity: 1 });
$(".slick-cell").css({ opacity: 1 });
}
});
}
catch (e) {
jAlert(clientErrMessage, 'PULSE');
}
}
Slick grid should be populated with months like Jan, Feb, March and its status respectively in 2 columns.
There are too many variables to give an answer. However I would recommend that you create the grid on page load and just populate it with data on ajax load, rather than creating the grid possibly each time.
In my experience, data not being visible is often CSS related.
Have a look at the samples in the SlickGrid repo, they are pretty comprehensive. Make sure you are using https://github.com/6pac/SlickGrid rather than the old MLeibman repo.
If you want assistance, the best idea is to create a stand alone test page that works with local files (apart from the ajax call) in the example folder of the slickgrid repo.
If you can share that, we can easily reproduce the behaviour. As a bonus, about 90% of the time you'll work out the problem while you are creating the example page.
Check to see
-if the property of data after ajax call is matching with the property provided in columns Field and vice versa.
- if the container u are passing is correct.

c3.js scatterplot example and tsv file

New to C3 here. I am trying to make a simple scatter plot. I thought this would work (c3_test.csv is the same data set from samples.)
var chart = c3.generate({
data: {
url: 'c3_test.csv',
x: 'data1',
columns: ['data2']
type: 'scatter'
}
});
but looks like this is not the way to go. This works,
var chart = c3.generate({
data: {
url: 'c3_test.csv',
filter: function (d) {
return d.id !== 'data1';
},
x:'data2',
type: 'scatter'
},
however, it would be helpful to know how to make the first method also give the desired output.
Also, I am trying to load a tsv file; based on this, I thought I could just use the url interface, however, that doesn't seem to work. Again, I would appreciate any help on this as well. I am using https://cdnjs.cloudflare.com/ajax/libs/c3/0.4.10/c3.js. My csv(tsv) file is below.
TIA,
C.S.N
data1,data2,data3
20,180,400
40,150,310
70,120,470
50,170,400
80 200 380
You can load from TSV files now. In order to do so you need to add the mimetype property to the data object as tsv.
Here's an example:
function glucoseInit() {
var chart = bb.generate({
bindto: '#divGlucoseScores',
data: {
url: 'glucoseScores.tsv',
mimeType: 'tsv',
x: 'date',
xFormat: '%Y-%m-%d %H:%M:%S', // how the date is parsed
y: 'score',
names: {
date: 'Date',
score: 'Blood glucose (mg/dL)'
}
},
axis: {
x: {
type: 'timeseries',
tick: {
format: '%m/%d/%Y'
}
}
}
});
}
See this post on github. It looks like this was added in September of 2014.
If you are looking to use data1 for the x axis, data2 for y, and ignore data3, you can use this:
var chart = c3.generate({
data: {
url: 'c3_test.csv',
x: 'data1',
type: 'scatter',
hide: ['data3']
},
legend: {
hide: ['data3']
}
});
After a little playing around I wasn't able to get a TSV file to load using the url option either, but you could use base D3 to parse the TSV and feed it to the chart object.

jqplot replot using dateaxisrenderer goes blank

I am trying to use JQPlot for plotting a live time based data .
As it is live data, I am doing an ajax call every 10 seconds to get new data and appending it to the existing dataset before replotting.
The initial plotting of the JQPlot chart is fine but subsequently from the first replot onwards the chart becomes blank for ever.
Here is my javascript code.
$.jqplot.config.enablePlugins = false;
var Graph;
var GraphUpdate;
var GraphData = [];
var interval = 10000;
var npoints = 25;
var maxIterations = 200;
var niters = 0;
var fetchInProgress = false;
var lastSuccessCDR = 0;
function BuildDataArray() {
GraphData = [];
lastSuccessCDR = 0;
if(fetchInProgress == false)
{
postdata = 'successCDR='+lastSuccessCDR;
fetchInProgress = true;
$.ajax({url:'/CDR-Analyser/php/livedata_fetch.php',
type:'POST',
data:postdata,
async:true,
dataType:"json",
success: function(data,status){
if(lastSuccessCDR == 0)
{
//GraphData = [data[0]['data']];
GraphData = [[["2013-07-17 21:11:20",2],["2013-07-17 21:12:20",5],["2013-07-17 21:14:20",7]]];
//GraphData = [[[1,2],[2,5],[3,7]]];
lastSuccessCDR = data[1]['lastCDR'];
Graph = $.jqplot('livechart', GraphData, {
stackseries : true,
seriesDefaults: {
showMarker: false,
fill: true,
fillAndStroke: true
},
axes: {
xaxis: {
//numberTicks:2,
//renderer:$.jqplot.DateAxisRenderer,
//pad:0,
renderer:$.jqplot.DateAxisRenderer,
tickOptions: {
angle: -30
}
},
yaxis: {
label: 'Call Count',
//min:0,
//max:30,
tickInterval:2,
labelRenderer: $.jqplot.CanvasAxisLabelRenderer
}
},
cursor:{
zoom:true,
looseZoom: true
}
});
}
fetchInProgress = false;
}
});
}
}
function UpdateDataArray() {
var set = 0;
if(fetchInProgress == false)
{
postdata = 'successCDR='+lastSuccessCDR;
fetchInProgress = true;
$.ajax({url:'/CDR-Analyser/php/livedata_fetch.php',
type:'POST',
data:postdata,
async:true,
dataType:"json",
success: function(data,status){
set = [data[0]['data']];
lastSuccessCDR = data[1]['lastCDR'];
var newData = new Array();
newData = GraphData;
newData[0].shift();
newData[0].push(set[0][0]);
GraphData = [["2013-07-17 21:11:20",2],["2013-07-17 21:12:20",5]];
//Graph.series[0].data = newData[0];
Graph.series[0].data = [["2013-07-17 21:11:20",2],["2013-07-17 21:12:20",5]];
//Graph.data[0] = [["2013-07-17 21:12:20",5],["2013-07-17 21:14:20",7]] ;
Graph.replot({resetAxes:true});
fetchInProgress = false;
}
});
}
return set;
}
function StartGraphLoop() {
BuildDataArray();
GraphUpdate = setInterval(UpdateGraph, interval);
}
function UpdateGraph() {
UpdateDataArray();
}
function StopGraphLoop() {
clearInterval(GraphUpdate);
}
I have two functions above , BuildDataArray() and updateDataArray() for building the initial data set and for getting the subsequent data elements.
As you can see I have replaced the actual data received from ajax ( it is commented) with sample data to test the behavour of JQPlot. Unfortunately with this sample data also the chart goes blank at the call of first replot. I had earlier tested this with sample data without the dates ( something like [[1,2] , [2,5] , [3,4]] ) by commenting out the dateaxisrenderer option in xaxis property.
So now I am left with no option so either I am missing something or it is a bug in JQPlot while rendering dateaxis.
Please advise
I had the same problem using the dateAxisRenderer where the series were being updated and the plot redrawn but there was no data in my graph. After a lot of head scratching I found this stackoverflow answer
Instead of updating the series data via
chartObj.series[i].data = // your data
You can create a variable and pass it as an argument to the replot() function. To use the snippet from C5H8NNaO4 as an example
var series = [[1,2],[2,3]];
chartObj.replot({data:series});
I haven't tested it with your code but it looks like we had the same problem and this solved the issue for me. If this works I suggest you up-vote the initial answer too :)

Sencha Touch refresh list after data in store has been changed

i want to do the following:
I have a store which gets JSON data from the server. The JSON looks like this:
{"id":"1","name":"Name1","address":"exampleaddress1","lat":"48.366268","lng":"10.892320","distance":"0"},{...}]
My model and store:
Ext.regModel('Filiale', {
fields: ['id', 'name', 'address', 'distance', 'lat', 'lng'],
});
var ListStore = new Ext.data.Store({
model: 'Filiale',
id: 'ListStore',
autoLoad: false,
fields:['name', 'address', 'distance'],
proxy: {
type: 'ajax',
url : 'http://example.com/getSomeJson.php',
reader: {
type: 'json'
}
},
listeners: {
load: function(){
ListStore.each(function(store){
var newData = getDistance(store.data); // this function calculates the distance from currentLocation to the received address
console.log(newData); // i see a object in the console, with the correct calculated distance
console.log(newData.distance); // this shows the old distance which is set to '0' in the databse
//at this point i want to update the received records with the new distance, but the list always shows the old distance
});
}
}
});
I don't understand, why the two console.logs show different values for the distance. Can anyone explain that to me ?
My List:
var listPanel = new Ext.List({
title: 'ListStore',
store: ListStore,
id: 'addresslist',
itemTpl: '<div class="contact">{name}, {address}, {distance}</div>',
rendered: false,
listeners: {
beforerender: function(){
ListStore.load();
}
}
});
my function to calculate the distance:
var getDistance = function(dataset){
navigator.geolocation.getCurrentPosition(function(position){
var start = new google.maps.LatLng(position.coords.latitude, position.coords.longitude);
//add current position marker to map
var marker = new google.maps.Marker({
map: mapPanel.map,
position: start
});
var end = new google.maps.LatLng(dataset.lat, dataset.lng);
var service = new google.maps.DirectionsService();
var request = {
origin: start,
destination: end,
travelMode: google.maps.DirectionsTravelMode.DRIVING
};
service.route(request, function(result, status){
if (status == google.maps.DirectionsStatus.OK) {
dataset.distance = result.routes[0].legs[0].distance.value / 1000;
}
});
});
return dataset;
};
And as i said, the distance is correctly calculated and the objects gets returned... but i'm unable to update the records in the store or the list...
I don't understand, why the two console.logs show different values for the distance. Can anyone explain that to me ?
Are You using Chrome? Chrome console sometimes has problems with up-to-date console data
And as i said, the distance is correctly calculated and the objects gets returned... but i'm unable to update the records in the store or the list...
Records in the store in Your script are always up-to-date - in JS obejcts are passed by reference, so You don't even have to return newData - store object will be updated automatically
Just after adding some values to store type:
listpanel.refresh()
to load current store to list

Needing example to load jqplot with multiple series, date-based data from json file

Been searching and cannot find exactly what I am looking for. Need to load multiple series into one jqplot, with each series coming from its own data file.
The example here http://www.jqplot.com/tests/data-renderers.php does show how to load a series from a file, but when I convert file to have date data, then it stops working, probably just a formatting issue, but cannot solve. What am I doing wrong?
Here is the data in the txt file:
[["7/11/2011 04:00:00am",85.0],["7/12/2011 04:00:00AM",87.4],["7/13/2011 04:00:00AM",90.0]]
Here is the code:
<script class="code" type="text/javascript">$(document).ready(function(){
var line = [ ];
var ajaxDataRenderer = function(url, plot) {
var ret = null;
$.ajax({
// have to use synchronous here, else returns before data is fetched
async: false,
url: url,
dataType:'json',
success: function(data) {
ret = data;
}
});
return ret;
};
var jsonurl = "./jsondata1.txt";
plo12 = $.jqplot('chart2', jsonurl,{
title: 'AJAX JSON Data Renderer',
dataRenderer: ajaxDataRenderer,
axes: {
xaxis: {
renderer:$.jqplot.DateAxisRenderer,
tickInterval: '1 day',
tickOptions:{formatString:'%y/%m/%d'}
}
}
});
});</script>
You could use the dataRendererOptions parameter to declare possible files, like this:
plo12 = $.jqplot('chart2', jsonurl,{
title: 'AJAX JSON Data Renderer',
dataRenderer: ajaxDataRenderer,
dataRendererOptions: {file1:'name_of_file_1', file2:'name_of_file2'}
axes: {
xaxis: {
Next use for-each to iterate trough the dataRendererOptions - Object:
var ajaxDataRenderer = function(url, plot,op) {
var ret = null;
$.each(op,function(i,n) {
$.ajax({
// have to use synchronous here, else returns before data is fetched
async: false,
url: url+'/'+i,
dataType:'json',
success: function(data) {
ret[]= data;
}
}); //end ajax
});//end each
return ret;
}
This code is not testet, but the idea behind could fit your needs.

Resources