anychart not taking dynamically added data - javascript

I am using anychart to draw a chart in my page, My code is like this
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="https://cdn.anychart.com/js/7.12.0/anychart-bundle.min.js"></script>
<link rel="stylesheet" href="https://cdn.anychart.com/css/7.12.0/anychart-ui.min.css" />
<input id="chart-charitytomoney" value="[["Charity 4",10.00],["Charity 2",20.00],["Charity Donate",100.00],["Donate Your Humanity",5920.00],["Gift your Work",3155.00],["Celebrate Baby Shower",770.00],["Refer Friends",110.00],["Gift Your Friends",200.00],["Celebrate B\u0027day With Us",220.00],["Celebrate Weekend",50.00],["Piggy Bank",4100.00],["Give a Single Gift",4050.00]]">
<div id="chart-container" style="height:550px!important"></div>
<script type="text/javascript">
$(document).ready(function(){
anychart.onDocumentReady(function () {
var data = $("#chart-charitytomoney").val();
// create column chart
chart = anychart.column();
// turn on chart animation
chart.animation(true);
// set chart title text settings
chart.title('Charities by donation');
// create area series with passed data
alert(data);
var series = chart.column(data);
// set series tooltip settings
series.tooltip().titleFormatter(function () {
return this.x
});
series.tooltip().textFormatter(function () {
return '$' + parseInt(this.value).toLocaleString()
});
series.tooltip().position('top').anchor('bottom').offsetX(0).offsetY(5);
// set scale minimum
chart.yScale().minimum(0);
// set yAxis labels formatter
chart.yAxis().labels().textFormatter("${%Value}");
// tooltips position and interactivity settings
chart.tooltip().positionMode('point');
chart.interactivity().hoverMode('byX');
// axes titles
chart.xAxis().title('Product');
chart.yAxis().title('Revenue');
// set container id for the chart
chart.container('chart-container');
// initiate chart drawing
chart.draw();
});
});
</script>
Everything looks okay to me, But chart is not working.
but if I changed this line
var data = $("#chart-charitytomoney").val();
to
var data = [["Charity 4", 10.00], ["Charity 2", 20.00], ["Charity Donate", 100.00], ["Donate Your Humanity", 5920.00], ["Gift your Work", 3155.00], ["Celebrate Baby Shower", 770.00], ["Refer Friends", 110.00], ["Gift Your Friends", 200.00], ["Celebrate B\u0027day With Us", 220.00], ["Celebrate Weekend", 50.00], ["Piggy Bank", 4100.00], ["Give a Single Gift", 4050.00]]
Everything works. Can anyone point out what I am doing wrong here? And How I can overcome it?

It is a peculiar way to pass data but you can do that, just:
Option 1
You should use quotes in the input field:
<input id="chart-charitytomoney" value="[['Charity 4',10.00],['Charity 2',20.00],['Charity Donate',100.00],['Donate Your Humanity',5920.00],['Gift your Work',3155.00],['Celebrate Baby Shower',770.00],['Refer Friends',110.00],['Gift Your Friends',200.00],['Celebrate B\u0027day With Us',220.00],['Celebrate Weekend',50.00],['Piggy Bank',4100.00],['Give a Single Gift',4050.00]]">
And you need to eval() the result:
var data = eval($("#chart-charitytomoney").val());
Here is a sample: http://jsfiddle.net/yr35w6nu/8/
However, eval is no quite secure, if you want to store data in a string in a field like this consider using code like this:
Option 2
var data = JSON.parse($("#chart-charitytomoney").val().replace(/\'/g,'\"'));
shown in this sample: http://jsfiddle.net/yr35w6nu/9/
The same may be applied to your code with &quote;:
var data = JSON.parse($("#chart-charitytomoney").val().replace(/\"/g,'\"'));
Sample parsing quotes: http://jsfiddle.net/yr35w6nu/10/
Option 3
There is also a way to store CSV formatted string:
<input id="chart-charitytomoney" value="Charity 4,10.00;Charity 2,20.00;Charity Donate,100.00;Donate Your Humanity,5920.00;Gift your Work,3155.00;Celebrate Baby Shower,770.00\nRefer Friends,110.00;Gift Your Friends,200.00;Celebrate B\u0027day With Us,220.00;Celebrate Weekend,50.00\nPiggy Bank,4100.00\nGive a Single Gift,4050.00">
and then use it:
var data = anychart.data.set($("#chart-charitytomoney").val(),{rowsSeparator: ';'});
http://jsfiddle.net/yr35w6nu/13/

Related

Draw pie chart using spring boot, thymeleaf, js, highchart but can't

I'm new with js and spring, now i want to create a html dashboard and this page will have a small div with pie chart. But i can't create pie chart.
I try some tutorial in youtube but now i want to pass value to ajax or something like that to get the pie chart.
Here is my Code:
admin_homepage.html:
<div class="col-xl-4 col-lg-5">
<div class="card shadow mb-4">
<!-- Thay chart vào thẻ div này -->
<div class="card-body">
<div class="chart-pie pt-4 pb-2">
<div id="chartContainer" style="height: 370px; width: 100%;"></div>
</div>
</div>
</div>
</div>
<script type="text/javascript">
$.ajax({
/* for pie chart */
url: "admin_home",
success: function(result){
/* pie chart starts here */
var series = [];
var data = [];
for(var i = 0; i < result.length; i++){
var object = {};
object.name = result[i].catName.toUpperCase();
object.y = result[i].catCount;
data.push(object);
}
var seriesObject = {
name: 'Course By Category',
colorByPoint: true,
data: data
};
series.push(seriesObject);
drawPieChart(series);
/* pie chart ends here */
}
});
/* for pie chart */
function drawPieChart(series){
Highcharts.chart('chartContainer', {
chart: {
plotBackgroundColor: null,
plotBorderWidth: null,
plotShadow: false,
type: 'pie'
},
title: {
text: 'Browser market shares in January, 2018'
},
tooltip: {
formatter: function() {
return '<strong>'+this.key+': </strong>'+ this.y;
}
},
plotOptions: {
pie: {
allowPointSelect: true,
cursor: 'pointer',
dataLabels: {
enabled: true,
format: '<b>{point.name}</b>: {point.y}'
}
}
},
series: series
});
}
</script>
My Controller
#GetMapping("/admin_home")
public String viewHomePage(){
// Get list of course and count
List<CountCourse> pieChart = dashBoardRepository.countCourseByCategory();
model.addAttribute("pieChart",pieChart);
return "Admin_Homepage";
}
All i want is pass value of catName, catCount to pie chart but i can't
Any one help me. Many thanks.
Because you are using a Thymeleaf template, you are not required to use $.ajax({...}) to retrieve the pie chart data. Instead you can provide the data directly to the Thymeleaf template.
(Alternatively, you can continue to use an Ajax call - in which case, The Thymeleaf template will be rendered to HTML - and then as a separate step, the Ajax call will fetch the pie chart data.)
The following assumes the first approach (no Ajax needed):
No Ajax Needed
I took your Thymeleaf template in the question and made some changes to the script:
I removed the Ajax call.
I added a Thymeleaf variable to hold the chart data.
Here is the updated script:
<script th:inline="javascript">
// this simply wraps the code in a function
// that waits for the DOM to be ready:
(function () {
// this is populated by Thymeleaf:
var pieChartData = /*[[${pieChartData}]]*/ [];
var series = [];
var data = [];
for (var i = 0; i < pieChartData.length; i++) {
var object = {};
object.name = pieChartData[i].catName.toUpperCase();
object.y = pieChartData[i].catCount;
data.push(object);
}
var seriesObject = {
name: 'Course By Category',
colorByPoint: true,
data: data
};
series.push(seriesObject);
drawPieChart(series);
// draw the pie chart:
function drawPieChart(series) {
Highcharts.chart('chartContainer', {
chart: {
plotBackgroundColor: null,
plotBorderWidth: null,
plotShadow: false,
type: 'pie'
},
title: {
text: 'Your Heading Goes Here'
},
tooltip: {
formatter: function () {
return '<strong>' + this.key + ': </strong>' + this.y;
}
},
plotOptions: {
pie: {
allowPointSelect: true,
cursor: 'pointer',
dataLabels: {
enabled: true,
format: '<b>{point.name}</b>: {point.y}'
}
}
},
// use the series data defined earlier:
series: series
});
}
})();
</script>
The key points about this script are:
The script tag looks like this:
<script th:inline="javascript">
This tells Thymeleaf that the script will contain one or more Thymeleaf expressions.
In our case we have one expression - here it is:
var pieChartData = /*[[${pieChartData}]]*/ [];
This syntax will cause Thymeleaf to replace the pieChartData variable with the data structure provided by the Java controller.
Here is that piece from the controller:
List<CountCourse> pieChartData = dashBoardRepository.countCourseByCategory();
model.addAttribute("pieChartData", pieChartData);
return "admin_homepage";
This assumes you have a CountCourse object which contains String catName and int catCount.
Thymeleaf will take the List<CountCourse> pieChartData data and generate the following JavaScript for you (using my test data):
var pieChartData = [
{"catName":"Humanities","catCount":123},
{"catName":"Sciences","catCount":145},
{"catName":"Other","catCount":67}
];
After that, I use the same logic as you have in your Ajax success function to convert this raw data into HightCharts pie chart data.
The end result is the following HTML page:
With Ajax
If you want to use your Ajax approach instead of this, then you need to build a separate end point which will return the pie chart data directly to the Ajax handler in your JavaScript code.
When you take this approach, you no longer need to use the Thymeleaf attribute:
var pieChartData = /*[[${pieChartData}]]*/ []; // NO LONGER NEEDED
And you no longer need to pass this data to your model in the controller:
model.addAttribute("pieChartData", pieChartData); // NO LONGER NEEDED
Instead, you need to continue using your $.ajax code and you need to build a separate end-point which returns the pieChartData as JSON for that Ajax call:
$.ajax({
/* for pie chart */
url: "piechart_data_json", // some new URL for your JSON pie chart data
...
});
Given you are using Thymeleaf already, I think there is no need for this approach.
Update
Just to explain the following syntax a bit more:
var pieChartData = /*[[${pieChartData}]]*/ [];
It looks like an empty JavaScript array []. But in fact, there is more to it.
The Thymeleaf variable ${pieChartData} receives the data from the controller.
Because the variable is in a <script> tag, it's not sufficient just to use the standard Thymeleaf ${pieChartData} expression. You also have to surround that expression with [[ and ]]. This is because ${pieChartData} is actually valid JavaScript - for example, as used in string interpolation.
That gives us this:
var pieChartData = [[${pieChartData}]];
This is all you need. This will work.
The problem here is, it's not valid JavaScript, so your IDE may highlight it as having a syntax error.
To work around this, you can take one extra step. You can "hide" the expression in a JavaScript comment - and then provide a valid value (the empty array). This keeps the JavaScript syntax checker happy in your IDE.
Thymeleaf will locate the variable inside that comment and remove it - and also remove the placeholder [] value.
That is how Thymeleaf pushes the Java model data into the template in this case.

Search functionality to search for particular chart among multiple charts in dashboard

I am making a spring application with java and JSP. In the Dashboard, I am showing multiple stockcharts using Highstock chart. Now I have a search bar above the charts and I want to search for a particular chart.
I have tried using Js but unsuccessful so please help me with this and suggest me approaches.
All Highcharts charts are stored in the globally defined Highcharts.charts array which you can filter to find the wanted chart (for example by their container id).
Demo: https://jsfiddle.net/BlackLabel/w29pL0zg/
console.log(Highcharts.charts)
Check the console.
Run the below code in browser. use productId1, productId2 or productId3 for searching.
<!DOCTYPE html>
<html>
<head>
<script>
//create productid to chart containerid mappings (on server side itself)
const searchList = {
productId1: ["container11", "container13"],
productId2: ["container12", "container1"],
productId3: ["container2", "container3", "container13"]
}
// create list of all the chart container ids (on server side itself)
const chartList = ["container1","container2", "container3", "container11","container12","container13"];
// search function for searching productid (exact match)
function searchProduct() {
// take the user input value for the productid
const searchTerm = document.getElementById("searchBox").value;
console.log(searchTerm);
//get the list of all chart containerid list for productid user has searched
const chartListForProduct = searchList[searchTerm];
// hide all charts when user is searching
chartList.forEach((containerId) => {
const chartContainer = document.getElementById(containerId)
chartContainer.style.display = "none"
});
// mappings are available for given searched product id display only those charts
if(chartListForProduct){
chartListForProduct.forEach((containerId) => {
const chartContainer = document.getElementById(containerId)
chartContainer.style.display = "block"
});
}
}
</script>
</head>
<body>
<div>
<h1>
Search chart by productId
</h1>
<input type="text" id="searchBox" value="" />
<button name="search" onClick="searchProduct()"> Search</button>
</div>
<br/><br/><br/>
<div id="container11">Chart 11....</div>
<div id="container12">Chart 12....</div>
<div id="container13">Chart 13....</div>
<div id="container1">Chart 1....</div>
<div id="container2">Chart 2....</div>
<div id="container3">Chart 3....</div>
</body>
</html>

Zingchart doesn't plot correctly a CSV with more than 10 columns

Scenario:
I need to plot data in Zingchart from a CSV that will have a fixed number of columns (37). This CSV has a header that will define the legend of the graph.
Problem:
If the number of elements I define in the header is less than 10 (including the X - Axis name) then everything is good. The first nine columns get a proper legend, and the others are named using the default Series XX. Link to the gist
In the data I've tried messing around with quotes " and ' but it didn't change the behavior.
Sample graph
Times|Line_1|Line_2|Line_3|Line_4|Line_5|Line_6|Line_7|Line_8|Line_9|"Line_10" "Line_11" Line_12 Line_13 Line_14 Line_15 Line_16 Line_17 Line_18 Line_19 Line_20 Line_21 Line_22 Line_23 Line_24 Line_25 Line_26 Line_27 Line_28 Line_29 Line_30 Line_31 Line_32 Line_33 Line_34 Line_35 Line_36
1218604835|0.0756521739130562|-0.151304347825771|||||||0.122608695652389|||||||-0.130434782608745|0.0443478260868915|0.232173913043425|||||||-0.172173913043707|||||||||||
1218604836|-0.427826086956543|-0.253043478260679|||||||-0.279130434782701|||||||-0.130434782608745|-0.0573913043477887|0.232173913043425|||||||-0.27391304347816|||||||||||
1218604837|-0.229565217391325|0.0469565217390482|||||||-0.0808695652174265|||||||0.0678260869565293|0.242608695652279|-0.169565217391664|||||||0.0260869565217945|||||||||||
1218604838|0.370434782608697|0.34695652173923|||||||-0.482608695652061|||||||0.0678260869565293|-0.159130434782583|-0.169565217391664|||||||0.224347826086841|||||||||||
1218604839|-0.133043478260902|-0.156521739130767|||||||0.117391304347848|||||||0.266086956522031|0.039130434782578|0.4304347826087|||||||-0.279130434782701|||||||||||
However, as soon as I continue including elements in the header using the CSV | separator, things start to go wrong. Ideally, the file should be as this one:
Sample graph
Times|Line_1|Line_2|Line_3|Line_4|Line_5|Line_6|Line_7|Line_8|Line_9|Line_10|Line_11|Line_12|Line_13|Line_14|Line_15|Line_16|Line_17|Line_18|Line_19|Line_20|Line_21|Line_22|Line_23|Line_24|Line_25|Line_26|Line_27|Line_28|Line_29|Line_30|Line_31|Line_32|Line_33|Line_34|Line_35|Line_36
1218604835|0.0756521739130562|-0.151304347825771|||||||0.122608695652389|||||||-0.130434782608745|0.0443478260868915|0.232173913043425|||||||-0.172173913043707|||||||||||
1218604836|-0.427826086956543|-0.253043478260679|||||||-0.279130434782701|||||||-0.130434782608745|-0.0573913043477887|0.232173913043425|||||||-0.27391304347816|||||||||||
1218604837|-0.229565217391325|0.0469565217390482|||||||-0.0808695652174265|||||||0.0678260869565293|0.242608695652279|-0.169565217391664|||||||0.0260869565217945|||||||||||
1218604838|0.370434782608697|0.34695652173923|||||||-0.482608695652061|||||||0.0678260869565293|-0.159130434782583|-0.169565217391664|||||||0.224347826086841|||||||||||
1218604839|-0.133043478260902|-0.156521739130767|||||||0.117391304347848|||||||0.266086956522031|0.039130434782578|0.4304347826087|||||||-0.279130434782701|||||||||||
But then the output is completely messed up. Link to the gist
The HTML code for the graph I'm running in local with the same results:
<!DOCTYPE html>
<html>
<head>
<script src="zingchart_2.3.2/zingchart.min.js"></script>
<script>
zingchart.MODULESDIR = "zingchart_2.3.2/modules/";
</script>
<style></style>
</head>
<body>
<div id='myChart'></div>
<script>
var myConfig = {
"globals":{
"font-family":"Arial"
},
"legend":{
"layout":"4x",
"adjust-layout":true,
"align":"center",
"background-color":"none",
"shadow":0,
"border-width":0,
"vertical-align":"bottom"
},
"type": "line",
"utc":true,
"csv": {
"url": "zingchart_2.3.2/sample_5lines.dat",
"separator": "|",
"vertical-labels": true,
},
"plot":{
"line-width":2,
"active-area":true,
"shadow":0,
"exact":true,
"marker":{
"size":4
},
"hover-marker":{
"size":3
},
"preview":true,
"spline":false,
"text":"%v",
},
"plotarea":{
"adjust-layout":1,
"width":"100%",
"height":200,
"position":"0% 0%",
"margin-top":60,
"margin-right":60,
"margin-left":70,
"margin-bottom":105
},
"preview":{
"visible":true,
"height":40,
"position":"0 370",
"margin-top":10,
"margin-bottom":15
},
"scale-x":{
"format":"%v",
"zooming":true,
"label":{
"margin-top":100
},
"tick":{
"line-color":"black",
"line-width":"2px",
"size":8,
},
"transform":{
"type":"date",
"all":"%d/%M/%Y\n%H:%i:%s",
}
},
"scale-y":{
"zooming":true,
"decimals":0,
},
"tooltip":{
<!--"js-rule":"myfunc()",-->
"shadow":0,
"font-color":"#000",
"text":"%t - %k<br><br>%v<br>Hz",
"border-radius":"5px",
"sticky":true,
"timeout":500,
"decimals":6
}
};
zingchart.render({
id: 'myChart',
data: myConfig,
height: 500,
width: "100%"
});
</script>
</body>
</html>
Question:
What am I doing wrong?
There are a couple issues with the JSON that I found.
1.In the CSV object, you would need to add horizontal-labels:true to set allow ZingChart to pull the appropriate labels from your dataset. In your case, the second row contains the labels for each series.
The text "%v" is no longer necessary inside of the plot object. This essentially assigns a label to each series, but setting horizontal-labels:true fixes this.
I have increased your decimals in the scale-y object to 2 instead of 0 so the scale-y does not appear to have duplicate values. You could also use exponent notation as shown here: http://www.zingchart.com/docs/design-and-styling/formatting-numbers/?q=customizable%20number%20formats
I'm assuming the first column of values in your dat file are UNIX time stamps? These values are converted directly using the Javascript Date object, so `new Date(1218604835) would actually return a date of Wed Jan 14 1970. If they are indeed UNIX time stamps, the values would need to be multiplied by 1000 so that new Date(1218604835000) would return Tue Aug 12 2008.
Plnkr here: http://plnkr.co/edit/jQ0WuMsRBgEwV6s0fKlN?p=preview
Let me know if you need any further help! - ZingChart Member.

Google visualization table not allowing HTML

I am using the Google visualization tools to show a table, but all of my HTML is being shown as a string. Here is the code:
var data = new google.visualization.DataTable()
data.setTableProperty('allowHtml', true)
data.addColumn('string','Keyword')
data.addColumn('number','<img src="http://m8app.com/assets/google-icon-8556487cd6ff3508d7bf2c4f64a0e3ad.jpg">Rank')
data.addColumn('number','Rank Change')
data.addColumn('string','Page')
data.addColumn('string','Link')
var row = 1;
while(row < thing.length){
data.addRow([
thing[row][0],
parseInt(thing[row][1],10),
parseInt(thing[row][2],10),
thing[row][3],
"<a href='"+thing[row][4]+"' target='_blank'>Search</a>"]);
row++;
}
var table = new google.visualization.Table(document.getElementById('rankInner'));
table.draw(data, {
allowHtml:true,
showRowNumber: false,
page : 'enable',
pageSize:10,
sortColumn: 2,
sortAscending:false
});
I have set 'allowHtml' to true on both the DataTable and the Table, but the table still shows the full text of the HTML rather than rendering it as html. I'd be grateful for any recommendation to try, thank you.
I tried a sample like yours in the online visualization playground, and it seems good
The only line I see you got messed up is the below line, where the indentation is wrong [quotes, double quotes. Compare with the below working one]
"<a href='"+thing[row][4]+"' target='_blank'>Search</a>"]);
link : https://code.google.com/apis/ajax/playground/?type=visualization#table
Code I tried:
function drawVisualization() {
// Create and populate the data table.
var data = google.visualization.arrayToDataTable([
['Name', 'Height', 'Dance'],
['Kuttappan', 174, true],
['Raayappan', 523, false],
["<a href='abc.com' target='_blank'>Search</a>", 86, true]
]);
// Create and draw the visualization.
visualization = new google.visualization.Table(document.getElementById('table'));
visualization.draw(data, {allowHtml:true});
}
when you run it [click on RunCode in the tool], you see the search link, and not the HTML code.
The below code for image,
data.addColumn('number','<img src="http://m8app.com/assets/google-icon-8556487cd6ff3508d7bf2c4f64a0e3ad.jpg">Rank')
is indeed showing as image only, and not HTML

How to drill down MAKit Chart with clicked category?

In a SAPUI5 application I am using two XML views showing a Chart each with a model bound to an OData service.
On the first view I build the chart using the following code:
<ma:Chart id="idChart" height="90%" width="100%" type="Column"
rows="{/MySet}" tap="onTapEvt">
<ma:category>
<ma:Category column="category" displayName="Category" />
</ma:category>
<ma:series>
<ma:Series column="intervallSeries" displayName="Intervall"/>
</ma:series>
<ma:values>
<ma:Value expression="mValue" displayName="Anzahl" />
</ma:values>
<ma:columns>
<ma:Column name="category" value="{Category}" />
<ma:Column name="intervallSeries" value="{Intervall}" />
<ma:Column name="mValue" value="{Anzahl}" type="number" />
</ma:columns>
</ma:Chart>
Let's assume I have four categories in my example chart named 'A', 'B', 'C' and 'D'.
When I click on the category 'C' in the Chart I would like to show another Chart on the next page using the filtered data from my OData service by filtering on "Category eq 'C'".
Therefore I use the function
onTapEvt: function(oEvent) {
var selectedCategory = oEvent.oSource._selectedCatIdx; // 2 when I select 'C'
// --> How do I get Category value 'C' instead of selectedIndex 2 here <--
app.to("nextPage", "slide", selectedCategory);
}
The object oEvent.oSource has all the MAKit Chart data in it, e.g. the selected index of the category in which I have clicked.
Now I am searching for a way to read the bound value of Category with index 2 from the chart.
Any ideas? In the SAPUI5 SDK I could not find a useful method for this.
You can use the following code to get the selected category :
var myChart = this.getView().byId("idChart");
var cat = myChart.getSelectedCategory();

Categories

Resources