JSON error when calling chart.draw from Google GeoChart library - javascript

I'm trying to use Google GeoChart library to display a map, and if I do it on a local HTML file or somewhere like JSFiddle, it works perfectly.
However, when I embed it in a JSP on my project and deploy it (using JBoss), calling chart.draw results in a JSON error:
Invalid JSON string: {":",":",":{":[",","]},":",":{":true}}
My complete Javascript method is as follows:
var data2 = google.visualization.arrayToDataTable([
[{label: 'Country', type: 'string'},
{label: 'description', type: 'string'},
{label: 'consistency', type: 'number'},
{type: 'string', role: 'tooltip'}],
['Canada', "CANADA", 2, "OK"],
['France', "FRANCE", 0, "KO"],
['USA', "USA", 1, "Other"]
]);
var options = {
displayMode: 'region',
backgroundColor: '#81d4fa',
colorAxis: {
colors: ['red', 'orange', 'green']
},
legend: 'none',
tooltip: {
showColorCode: true
}
};
var chart = new google.visualization.GeoChart(document.getElementById('chart_div'));
chart.draw(data2, options);
So it's clearly picking up the "structure" of the JSON object (two simple objects, another object with an array inside, another simple object, another object with an array inside), but for some reason is not picking up the content, except for the 'true' value, so it looks like a problem with quotes...
In any case, I have tried simple and double quotes, removing the quotes from the identifiers, reducing the options object to a simple
var options = {
"legend": "none"
};
... but to no avail. Everything results in a Invalid JSON string error (in this last case, a Invalid JSON string: {":"} error, since there is only one object).
Last note: if I just use
var options = {};
it shows the map (but with the default options).
Any ideas as to why is this happening and/or how to solve it?
Thanks!

Related

Optional Obj not rendering hands on table

Currently I am using handsontably 6.2.2 and I am trying to load a data set I get from a database but it will not render if I have an included table in the query that may or may not be there. I have tried to use custom rendering but it errors out before those are called and the only function that will log anything before erroring out is the beforeGetCellMeta but I cannot successfully change the value in this function. I may be doing that part wrong.
Here is my obj I am passing into Handsontable
data: [
{id: 1, name: "Test Name", includedTable: null},
{id: 2, name: Test Name 2", includedTable: {
id: 1,
name: "IncludedTableRowName"
}},
];
Below is the handsontable I am calling.
hot1 = new Handsontable(container, {
data: data,
colHeaders: ['id', 'Name', 'Table Row Name'],
columns: [
{data: 'id'},
{data: 'name'},
{data: 'includedTable.name'}
]
});
All I get is TypeError: Cannot read property 'name' of null on the includedTable.name. I get that it is undefined in the first but shouldnt it just render null in that case? If not I need help getting this to work with a customer render function or something else because I have tried custom renders, custom types, all the function within handsontable before to get the values to work and nothing has let me do this.

How to make a Pie Chart Aggregate the Data Source?

Using Kendo UI Complete for ASP.NET MVC, version: 2013.3 1119 (Nov 20, 2013)...
If I have this bit of code:
$("#status-chart").kendoChart({
dataSource: {
data: [
{Status: 10},
{Status: 20},
{Status: 200},
{Status: 200}
]
},
series: [{
field: 'Status',
categoryField: "Status",
aggregate: 'count'
}]
});
I get this chart:
As you can see - Status 10 and 20 have got a value of 1 and Status 200 a value of 2.
Great, but what I actually want is exactly the same thing in a pie chart (so, a chart with 3 pie slices, 2 of which are exactly the same size and one that is 2 times as big as the rest).
I therefore thought to myself, all I need to do is just set type: "pie" like so:
$("#status-chart").kendoChart({
dataSource: {
data: [
{Status: 10},
{Status: 20},
{Status: 200},
{Status: 200}
]
},
series: [{
field: 'Status',
categoryField: "Status",
aggregate: 'count',
type: "pie"
}]
});
But that produced this chart:
You can see that Status 200 is repeated and the value is determining the size of the slices.
So, here is my question:
How can I create a pie chart that looks like the picture below but which is bound to the data source in the first code snippet above?
Incidentally, the reason I do not want to change the data source is that I wish to share it with a grid.
What you are trying to do here is to group a shared DataSource and have it only affect one widget. Furthermore, Kendo UI will return a grouped object when you group it. The Pie chart is not interested in these objects, but rather the count of the items that each of these group objects contains. We just need to get the data in the right format.
So you have your original DataSource (which I have extracted since it's shared with another widget). When that DataSource changes, you want to populate a second one - one that you can group without affecting the grid.
var ds = new kendo.data.DataSource({
data: [
{Status: 10},
{Status: 20},
{Status: 200},
{Status: 200}
],
change: function() {
chartData.data(this.data());
}
});
The second DataSource (chartData) is grouped, and when it changes, it populates an array, constructing objects that the pie chart can actually understand.
var groupedData = [];
// populate the grouped data array by grouping this datasource
// and then populating an plain array
var chartData = new kendo.data.DataSource({
group: { field: 'Status' },
change: function() {
groupedData = [];
$.each(this.view(), function() {
groupedData.push({ field: this.value, value: this.items.length });
});
}
});
And then just bind your pie chart to that array
$("#status-chart").kendoChart({
dataSource: groupedData,
series: [{
type: 'pie',
field: 'value',
categoryField: 'field'
}]
});
Working example: http://jsbin.com/EKuxORA/1/edit

Google Chart - GeoChart "Incompatible data table: Error: Unknown address type."

I'm trying to generate a GeoChart using a set of data retrieved from mysql and parsed in PHP. However, I'm pretty sure that the error lies in my JavaScript. I've simplified the data to make it easier to understand.
Here is my JavaScript:
// Load the Visualization API and the piechart package.
google.load('visualization', '1.0', {'packages':['geochart']});
// Set a callback to run when the Google Visualization API is loaded.
google.setOnLoadCallback(drawChart);
// Callback that creates and populates a data table,
// instantiates the geo chart, passes in the data and
// draws it.
function drawChart() {
// Create the data table.
var data = new google.visualization.DataTable(
{
cols: [
{id: '0', label: 'Country'},
{id: '1', label: 'Downloads'}
],
rows: [
{c:[{v: 'GB'}, {v: 166020}]}
]
}
);
// Set chart options
var options = {
title:'Downloads in Last 30 Days',
width:900,
height:700,
};
// Create and draw the visualization.
visualization = new google.visualization.GeoChart(document.getElementById('chart_div1'));
visualization.draw(data, options);
}
In the page I just get red text that says:
Incompatible data table: Error: Unknown address type.
I have other charts working fine using a datatable with the same format/layout.
Any help appreciated,
Cheers
I fixed it. I just needed to specify the type of column was a string or a number.
Example:
cols: [
{id: '0', label: 'Country', type: 'string'},
{id: '1', label: 'Downloads', type: 'number'}
],

Programmatically Set Constructor Parameters in Javascript

I am trying to interact with a javascript api (bare in mind I have never done this before). An example of what I am attempting to work with is here:
SearchSpring.Catalog.init({
leaveInitialResults : true,
facets : '.leftNav',
results : '#results',
result_layout: 'list',
results_per_page : 12,
layout: 'top',
loadCSS: false,
filters: {
color: ['Blue']
},
backgroundFilters: {
category: ['Shirt', 'Shoes'],
department: ['Mens']
},
maxFacets: 5,
maxFacetOptions: 10,
sortText: 'Sort By ',
sortType: 'dropdown',
filterText: 'Refine Search Results',
previousText: 'Previous',
scrollType: 'scroll',
scrollTo: 'body',
backgroundSortField: 'price',
backgroundSortDir: 'desc',
compareText: 'Compare Items',
summaryText: 'Current Filters',
showSummary: true,
subSearchText: 'Subsearch:',
showSubSearch: true,
forwardSingle: false,
afterResultsChange: function() { $('.pagination').hide(); },
filterData: function(data) { console.debug(data); }
});
In the example I want to add a "backgroundFilter" to this with a value:
var cat="MyNewCategory";
cat.value="ANewValue;
How would I add this category and value to the backgroundFilters: listed above?
This is a very common framework initialization pattern when working with frameworks.
Your example code is passing a JavaScript Object {} as a parameter into a function () that is called init.
Taking out all definitions the pattern looks like this:
SomeFramework.frameworkFunction({});
In the above code the {} is an empty object used for initialization. There are two ways that you can work with that object in practice.
Regarding your first code snippet, you can add code into that 'object literal'.
backgroundFilters: {
category: ['Shirt', 'Shoes'],
department: ['Mens'],
cat: ['My value']
},
Notice the added comma, this is an important tripping point. This may or may not fit your needs, depending on a few factors.
Regarding your second code snippet, you can apply members to JavaScript objects at runtime. What I mean is, your var cat can be added to the anonymous object-literal that is being passed in. Hard to say, but a simple concept. Here is how:
//Say this is initialized in some separate way. //There is a bug here I'll describe later.
var cat="MyNewCategory";
cat.value="ANewValue";
//Extract and name the initialization object. It is verbatim at this point.
var initObject = {
leaveInitialResults : true,
facets : '.leftNav',
results : '#results',
result_layout: 'list',
results_per_page : 12,
layout: 'top',
loadCSS: false,
filters: {
color: ['Blue']
},
backgroundFilters: {
category: ['Shirt', 'Shoes'],
department: ['Mens']
},
maxFacets: 5,
maxFacetOptions: 10,
sortText: 'Sort By ',
sortType: 'dropdown',
filterText: 'Refine Search Results',
previousText: 'Previous',
scrollType: 'scroll',
scrollTo: 'body',
backgroundSortField: 'price',
backgroundSortDir: 'desc',
compareText: 'Compare Items',
summaryText: 'Current Filters',
showSummary: true,
subSearchText: 'Subsearch:',
showSubSearch: true,
forwardSingle: false,
afterResultsChange: function() { $('.pagination').hide(); },
filterData: function(data) { console.debug(data); }
};
//Now we can add variables (and functions) dynamically at runtime.
initObject.cat = cat;
//And pass them into the framework initialization in a separated way.
SearchSpring.Catalog.init(initObject);
Now for the bug. I don't know the solution because I do not know what it is intended to do, but I can point out what is potentially incorrect.
var cat="MyNewCategory";
cat.value="ANewValue;
This code is: 1 creating a String Object called cat. 2 changing the value to a new string.
I do not think this is what you really want.
To add a new backgroundFilter, in the separated way above, it would be:
initObject.backgroundFilters.cat = ['A', 'B'];
//Line above would give you this type of definition within the initObject (at runtime):
backgroundFilters: {
category: ['Shirt', 'Shoes'],
department: ['Mens'],
cat: ['A','B']
},
For this to work it will depend on what the framework is expecting regarding backgroundFilters.
Hope that helps.
All the best!
Nash
I don't quite understand - do you want to have the backgroundFilters categories as structured objects rather than plain strings? If you are in control of the entire API, you can do something like
...
backgroundFilters: {
category: [
new SearchSpring.Catalog.Category("Shirt"),
new SearchSpring.Catalog.Category("Shoes"),
new SearchSpring.Catalog.Category("MyNewCategory", "ANewValue")
],
department: 'Mens'
}
...

jqGrid has no addJSONData method

I'm just playing around with jqGrid this afternoon, and have it working fairly well with a local array data source. However, now I'm trying to get it to load local JSON data.
My code is as follows:
jQuery("#list4").jqGrid({
datatype: "json", //<-- Also tried "local" here
height: 'auto',
autowidth: true,
forceFit: true,
colNames:['ID','Name'],
colModel:[
{name:'id',index:'id', width:60, sorttype:"int", jsonmap:"id"},
{name:'name',index:'name', width:90, jsonmap: "name"}
],
multiselect: false,
caption: "Test"
});
I then try to load JSON data using the following:
jQuery("#list4").jqGrid.addJSONData(json);
The issue is that jQuery("#list4").jqGrid.addJSONData is undefined. I've also tried:
jQuery("#list4").jqGrid('addJSONData', json);
Which throws an exception saying that the method addJSONData is not defined. I can see other documented methods on jQuery("#list4").jqGrid, just not this one. addXMLData is also missing. However, I can verify that these methods are in the jquery.jqGrid.min.js source code.
I just downloaded jqGrid today, so I know I have the latest versions of everything.
I must be doing something wrong, but I'm not sure what it could be. I've put the entire page here:
http://pastie.org/3825067
The addJSONData is very old method which uses still expandos to the DOM element of the grid (<table> element). So to use addJSONData correctly one should use
jQuery("#list4")[0].addJSONData(json);
See the documentation. More beter way will be to create jqGrid and fill the data directly. You can use
jQuery("#list4").jqGrid({
datatype: "local",
data: mydata,
height: 'auto',
autowidth: true,
colNames: ['ID', 'Name'],
colModel: [
{name: 'id', index: 'id', width: 60, sorttype: "int", key: true},
{name: 'name', index:'name', width: 90}
],
caption: "Test",
gridview: true // !!! improve the performance
});
The format of mydata can be like
var mydata = [
{id: 10, name: "Oleg"},
{id: 20, name: "Mike"}
];
It's allow to use local paging, filtering and sorting of data. The input data need not be sorted.
Alternatively you can use datatype: 'jsonstring' and datastr. The value of datastr can be either JSON string or already parsed object. The data from datastr have to be correctly sorted (if you use some sortname and sortorder parameters) and have the same format as for datatype: 'json' (see the documentation). One can use jsonReader and jsonmap to specify the data format:
var mydata = {
//total: 1, // will be ignored
//page: 1, // will be ignored
//records: 2 // will be ignored
rows: [
{id: 10, name: "Oleg"},
{id: 20, name: "Mike"}
]
];
What is the most strange for me is why you need to load "local JSON data"? Where is the difference to the "local array data source"? You can use $.parseJSON to convert the input data to object or use datatype: 'jsonstring' directly. In the most cases the usage of addJSONData is because of loading the data from the server manually per jQuery.ajax which is really bed idea (see one from my first posts on the stackoverflow here). jqGrid has a lot of customization options and callbackes like ajaxGridOptions, serializeGridData and beforeProcessing, you can use functions in jsonReader (see here) and jsonmap, which allows you to load practically any format of input data. Using prmNames, serializeGridData and postData (see here) you can make practically any customization of the parameters sent to the server. So the usage of low-level addJSONData are needed really in extremely very seldom scenarios.
For the most part, you are close. I don't think the addJSONData method is the way to go. Here's how we deal with local JSON data:
The grid:
$("#list4").jqGrid({
datatype: "local", //<-- "local" tells jqGrid not to try and get the data itself
height: 'auto',
autowidth: true,
forceFit: true,
colNames:['ID','Name'],
colModel:[
{name:'id',index:'id', width:60, sorttype:"int", jsonmap:"id"},
{name:'name',index:'name', width:90, jsonmap: "name"}
],
multiselect: false,
caption: "Test"
});
Give data to the grid:
// Clear the grid if you only want the new data
$('#list4').clearGridData(true);
// Set the data the tell the grid to refresh
$('#list4').setGridParam({ data: jsonData, rowNum: jsonData.length }).trigger('reloadGrid');
You should also change your jsonData to:
var jsonData = [
{id: 1, name: 'Apple'},
{id: 2, name: 'Banana'},
{id: 3, name: 'Pear'},
{id: 4, name: 'Orange'}
];
jqGrid is going to look to match up the columns specified to the objects passed into the array.
I'm working with version jqGrid 4.1.2
Having initialized the grid with a JSONReader and datatype:'jsonstring', when adding jsonstring data I've to include the datatype:'jsonstring' parameter.
$('#list4').setGridParam({ datastr: jsonData, datatype:'jsonstring', rowNum: jsonData.length }).trigger('reloadGrid');
As far as I know that is because after initialize the datatype:'jsonstring' is turned to datatype:'local', so when adding jsonstring it tries to load data from "data" param instead of "datastr" but because is empty no data is loaded.
I hope to contribute to this ...

Categories