How to deal with Ajax data not arrive yet? - javascript

I have a chart that contain
<script type="text/javascript">
console.log('{{ $cpe_mac }}');
var ajax = $.ajax({url: '/api/timebase/'+'{{ $cpe_mac }}'});
ajax.done(function (data) {
console.log(data)
var array_hour_g_down = [];
var array_hour_g_up = [];
var array_hour_p_down = [];
var array_hour_p_up = [];
for (var i = 0; i < data.hour_g_up.length; i++) {
array_hour_g_down[i] = {"value":data.hour_g_down[i]};
array_hour_g_up[i] = {"value":data.hour_g_up[i]};
array_hour_p_down[i] = {"value":data.hour_p_down[i]};
array_hour_p_up[i] = {"value":data.hour_p_up[i]};
}
var granular_time_network_day = new FusionCharts({
"type": "msstackedcolumn2d",
"renderAt": "granular-time-network",
"width": "100%",
"dataFormat": "json",
"dataSource": {
"chart": {
"caption": "Time-Based Bandwidth Usage",
"subcaption": "Daily View",
"xaxisname": data.month + ' ' + data.dth + ',' + ' '+ data.year,
"yaxisname": "Bandwidth (in Megabytes)",
"paletteColors": color_home_down+','+color_home_up+','+color_guest_down+','+color_guest_up,
// "numbersuffix": "MB",
"showvalues": "0",
"bgColor": "#ffffff",
"borderAlpha": "20",
"showCanvasBorder": "0",
"usePlotGradientColor": "0",
"plotBorderAlpha": "10",
"legendBorderAlpha": "0",
"legendShadow": "0",
"valueFontColor": "#ffffff",
"showXAxisLine": "1",
"xAxisLineColor": "#999999",
"divlineColor": "#999999",
"divLineDashed": "1",
"showAlternateHGridColor": "0",
"subcaptionFontBold": "0",
"subcaptionFontSize": "14"
},
"categories": [{
"category": [{
"label": "12am-2am"
}, {
"label": "2am-4am"
}, {
"label": "4am-6am"
}, {
"label": "6am-8am"
}, {
"label": "8am-10am"
}, {
"label": "10am-12pm"
}, {
"label": "12pm-2pm"
}, {
"label": "2pm-4pm"
}, {
"label": "4pm-6pm"
}, {
"label": "6pm-8pm"
}, {
"label": "8pm-10pm"
}, {
"label": "10pm-12am"
}]
}],
"dataset": [{
"dataset": [{
"seriesname": "Home Network - Downlink",
"data": array_hour_p_down
}, {
"seriesname": "Home Network - Uplink",
"data": array_hour_p_up
}]
}, {
"dataset": [{
"seriesname": "Guest Network - Downlink",
"data": array_hour_g_down
}, {
"seriesname": "Guest Network - Uplink",
"data": array_hour_g_up
}]
}]
}
});
});
</script>
I wrap my code around ajax.done() because I don't want my page load to wait for that data and rendering the chart as soon as the data arrive. But now I face another issue.
Uncaught ReferenceError: granular_time_network_day is not defined
Error
$('#granular-time').on('click', function() {
$('#granular-total-view').hide();
$('#granular-time-view').fadeIn('slow');
granular_time_network_day.render();
granular_time_device_day.render();
$('#btn-interval').prop('disabled', false);
});
How do I prevent this from happening?
Did I do anything wrong on my Ajax?
Should I look into promise or something like that?

You need to defined granular_time_network_day outside of your ajax.done function

define the function outside of your .done() callback so the click is aware of it even if the call hasn't completed yet.
EDIT
You don't need to check to see if a function is available, you need to check and see if you have the data yet from the $.ajax call:
var data = null;
$.ajax().done(function(data) {
// assign data
data = data;
});
$('#granular-time'.on('click', function() {
// check to see if you have data
if (data) {
// do your stuff
var granular_time_network_day = new FusionCharts({
"type": "msstackedcolumn2d",
"renderAt": "granular-time-network",
"width": "100%",
"dataFormat": "json",
....
})
}
});
});

I would suggest checking to see if granular_time_network_day exists before calling render.
Example:
$('#interval-day').on('click',function(){
if (granular_time_network_day) {
granular_time_network_day.render();
} else {
//tell user that the data is still being retrieved or handle another way
}
});
I did notice a potential other problem related to the variable being declared in the done call - granular_time_network_day will be in scope only for the done function. It would work out to declare it outside the done function, so that the click handler will be able to access it when the ajax call is complete.

window.
Turn out that window. save my life, and the answer that I am looking for.
Here is my final script
<script type="text/javascript">
var ajax = $.ajax({url: '/api/timebase/'+'{{ $cpe_mac }}'});
ajax.done(function (data) {
console.log(data)
var array_hour_g_down = [];
var array_hour_g_up = [];
var array_hour_p_down = [];
var array_hour_p_up = [];
for (var i = 0; i < data.hour_g_up.length; i++) {
array_hour_g_down[i] = {"value":data.hour_g_down[i]};
array_hour_g_up[i] = {"value":data.hour_g_up[i]};
array_hour_p_down[i] = {"value":data.hour_p_down[i]};
array_hour_p_up[i] = {"value":data.hour_p_up[i]};
}
window.granular_time_network_day = new FusionCharts({
"type": "msstackedcolumn2d",
"renderAt": "granular-time-network",
"width": "100%",
"dataFormat": "json",
"dataSource": {
"chart": {
"caption": "Time-Based Bandwidth Usage",
"subcaption": "Daily View",
"xaxisname": data.month + ' ' + data.dth + ',' + ' '+ data.year,
"yaxisname": "Bandwidth (in Megabytes)",
"paletteColors": color_home_down+','+color_home_up+','+color_guest_down+','+color_guest_up,
// "numbersuffix": "MB",
"showvalues": "0",
"bgColor": "#ffffff",
"borderAlpha": "20",
"showCanvasBorder": "0",
"usePlotGradientColor": "0",
"plotBorderAlpha": "10",
"legendBorderAlpha": "0",
"legendShadow": "0",
"valueFontColor": "#ffffff",
"showXAxisLine": "1",
"xAxisLineColor": "#999999",
"divlineColor": "#999999",
"divLineDashed": "1",
"showAlternateHGridColor": "0",
"subcaptionFontBold": "0",
"subcaptionFontSize": "14"
},
"categories": [{
"category": [{
"label": "12am-2am"
}, {
"label": "2am-4am"
}, {
"label": "4am-6am"
}, {
"label": "6am-8am"
}, {
"label": "8am-10am"
}, {
"label": "10am-12pm"
}, {
"label": "12pm-2pm"
}, {
"label": "2pm-4pm"
}, {
"label": "4pm-6pm"
}, {
"label": "6pm-8pm"
}, {
"label": "8pm-10pm"
}, {
"label": "10pm-12am"
}]
}],
"dataset": [{
"dataset": [{
"seriesname": "Home Network - Downlink",
"data": array_hour_p_down
}, {
"seriesname": "Home Network - Uplink",
"data": array_hour_p_up
}]
}, {
"dataset": [{
"seriesname": "Guest Network - Downlink",
"data": array_hour_g_down
}, {
"seriesname": "Guest Network - Uplink",
"data": array_hour_g_up
}]
}]
}
});
});
</script>
I'm no longer getting the error.

Related

How to show localstorage data in HTML form using jquery or javascript?

I am saving data in localstorage temporary, because of user have to go to another page before submit the form, But i have problem to display data in form again.
Here is my code
$('#ip_range').click(function(e) {
var data = $('#Demoform').serializeArray();
// localStorage.setItem('formData', JSON.stringify(data));
var formData = JSON.parse(localStorage.getItem('formData'));
$.each(formData, function(i, val) {
var data = $("input[name='"+val.name+"']").val(val.value);
console.log(data);
});
});
This is the json data that i want to display
[{
"name": "timezone",
"value": "America/New_York"
}, {
"name": "fiscal_year",
"value": "1"
}, {
"name": "first_day",
"value": "0"
}, {
"name": "highest_level",
"value": "393"
}, {
"name": "company_administrator",
"value": "393"
}, {
"name": "ip_restrictions",
"value": "1"
}, {
"name": "ip_range",
"value": "4"
}, {
"name": "languages_enabled",
"value": "0"
}, {
"name": "language",
"value": ""
}, {
"name": "enable_single_sign",
"value": "0"
}, {
"name": "user_sign_off",
"value": "0"
}, {
"name": "widgets_sort_order",
"value": "Links,Training,Task"
}, {
"name": "confirm",
"value": "1"
}]
You are close here, but this part $("input[name='"+val.name+"']").val(val.value) is what I think your problem is. Try the code below. I think this is what you are trying to do.
I would structure the input like such: var data = $('<input name="'+ val.name +'" value="'+ val.value +'" />');
I'd put a stack snippet up, but it doesn't work well with localStorage, so click on the jsfiddle link and click the IP Range button to see the form get the inputs with the proper names.
Demo: https://jsfiddle.net/ygh8pdk1/
var data = [
{
"name": "timezone",
"value": "America/New_York"
}, {
"name": "fiscal_year",
"value": "1"
}, {
"name": "first_day",
"value": "0"
}, {
"name": "highest_level",
"value": "393"
}, {
"name": "company_administrator",
"value": "393"
}, {
"name": "ip_restrictions",
"value": "1"
}, {
"name": "ip_range",
"value": "4"
}, {
"name": "languages_enabled",
"value": "0"
}, {
"name": "language",
"value": ""
}, {
"name": "enable_single_sign",
"value": "0"
}, {
"name": "user_sign_off",
"value": "0"
}, {
"name": "widgets_sort_order",
"value": "Links,Training,Task"
}, {
"name": "confirm",
"value": "1"
}
];
localStorage.setItem('formData', JSON.stringify(data));
$('#ip_range').click(function(e) {
var formData = JSON.parse(localStorage.getItem('formData'));
$.each(formData, function(i, val) {
var data = $('<input name="'+ val.name + '" value="'+ val.value +'" />');
$('#form-data').append(data);
});
});

Uncaught ReferenceError: Tankvalue is not defined

I want to display response data in charts. but Tankvalue is getting out of scope and giving error message
Tankvalue is not defined.
How to make variable can be accessed globally. Charts are not loading due to an undefined value. want to show Tankvalue in the chart.
var app = angular.module('myApp', []);
app.controller('myCtrl', function ($scope, $http) {
$http.get('url', {
headers: {
'Authorization': 'Basic Pasword=='
}
})
.then(function (response) {
$scope.names = response.data;
$scope.decodedFrame = atob($scope.names.dataFrame);
var Tankvalue = $scope.decodedFrame.substring(6);
});
});
FusionCharts.ready(function () {
var fusioncharts = new FusionCharts({
type: 'cylinder',
dataFormat: 'json',
id: 'fuelMeter-1',
renderAt: 'chart-container',
width: '200',
height: '350',
dataSource: {
"chart": {
"theme": "fint",
"caption": "Tank",
"subcaption": "Bakersfield Central",
"lowerLimit": "0",
"upperLimit": "25",
"lowerLimitDisplay": "Empty",
"upperLimitDisplay": "Full",
"numberSuffix": " ltrs",
"showValue": "1",
"chartBottomMargin": "45",
"showValue": "0"
},
"value": Tankvalue,
"annotations": {
"origw": "400",
"origh": "190",
"autoscale": "1",
"groups": [{
"id": "range",
"items": [{
"id": "rangeBg",
"type": "rectangle",
"x": "$canvasCenterX-45",
"y": "$chartEndY-30",
"tox": "$canvasCenterX +45",
"toy": "$chartEndY-75",
"fillcolor": "#6caa03"
}, {
"id": "rangeText",
"type": "Text",
"fontSize": "11",
"fillcolor": "#333333",
"text": "80 ltrs",
"x": "$chartCenterX-45",
"y": "$chartEndY-50"
}]
}]
}
},
});
fusioncharts.render();
});
Move FusionCharts.ready() inside then block as shown below.
.then(function (response) {
$scope.names = response.data;
$scope.decodedFrame = atob($scope.names.dataFrame);
var Tankvalue = $scope.decodedFrame.substring(6);
FusionCharts.ready(function () {
var fusioncharts = new FusionCharts({
type: 'cylinder',
dataFormat: 'json',
id: 'fuelMeter-1',
renderAt: 'chart-container',
width: '200',
height: '350',
dataSource: {
"chart": {
"theme": "fint",
"caption": "Tank",
"subcaption": "Bakersfield Central",
"lowerLimit": "0",
"upperLimit": "25",
"lowerLimitDisplay": "Empty",
"upperLimitDisplay": "Full",
"numberSuffix": " ltrs",
"showValue": "1",
"chartBottomMargin": "45",
"showValue": "0"
},
"value": Tankvalue,
"annotations": {
"origw": "400",
"origh": "190",
"autoscale": "1",
"groups": [{
"id": "range",
"items": [{
"id": "rangeBg",
"type": "rectangle",
"x": "$canvasCenterX-45",
"y": "$chartEndY-30",
"tox": "$canvasCenterX +45",
"toy": "$chartEndY-75",
"fillcolor": "#6caa03"
}, {
"id": "rangeText",
"type": "Text",
"fontSize": "11",
"fillcolor": "#333333",
"text": "80 ltrs",
"x": "$chartCenterX-45",
"y": "$chartEndY-50"
}]
}]
}
},
});
fusioncharts.render();
});
});
$http.get() is an async function, so FusionCharts.ready() runs before the value assigned to Tankvalue variable.
To fix this move ready() function inside .then().
Do it like:
var app = angular.module('myApp', []);
app.controller('myCtrl', function ($scope, $http) {
$http.get('url', {
headers: {
'Authorization': 'Basic Pasword=='
}
})
.then(function (response) {
$scope.names = response.data;
$scope.decodedFrame = atob($scope.names.dataFrame);
var Tankvalue = $scope.decodedFrame.substring(6);
FusionCharts.ready(function () {
var fusioncharts = new FusionCharts({
type: 'cylinder',
dataFormat: 'json',
id: 'fuelMeter-1',
renderAt: 'chart-container',
width: '200',
height: '350',
dataSource: {
"chart": {
"theme": "fint",
"caption": "Tank",
"subcaption": "Bakersfield Central",
"lowerLimit": "0",
"upperLimit": "25",
"lowerLimitDisplay": "Empty",
"upperLimitDisplay": "Full",
"numberSuffix": " ltrs",
"showValue": "1",
"chartBottomMargin": "45",
"showValue": "0"
},
"value": Tankvalue,
"annotations": {
"origw": "400",
"origh": "190",
"autoscale": "1",
"groups": [{
"id": "range",
"items": [{
"id": "rangeBg",
"type": "rectangle",
"x": "$canvasCenterX-45",
"y": "$chartEndY-30",
"tox": "$canvasCenterX +45",
"toy": "$chartEndY-75",
"fillcolor": "#6caa03"
}, {
"id": "rangeText",
"type": "Text",
"fontSize": "11",
"fillcolor": "#333333",
"text": "80 ltrs",
"x": "$chartCenterX-45",
"y": "$chartEndY-50"
}]
}]
}
},
});
fusioncharts.render();
});
});
});
You can not use local variable out of other function.make it a global or make as scope variable by using $scope.
$scope.Tankvalue = $scope.decodedFrame.substring(6);

Animation of line chart with D3.js (v4)?

Is it possible to create an animation with D3.js (version 4)? In particular I want to create multiple line charts that "runs" from left to right like in this example with react-fusionchart:
http://jsfiddle.net/thadeuszlay/m18qaekm/12/
(just look at the example above.)
FusionCharts.ready(function () {
var myDataSource = {
"chart": {
"caption": "Actual Revenues, Targeted Revenues & Profits",
"subcaption": "Last year",
"xaxisname": "Month",
"yaxisname": "Amount (In USD)",
"numberprefix": "$",
"theme": "ocean"
},
"categories": [{
"category": [{
"label": "Jan"
}, {
"label": "Feb"
}, {
"label": "Mar"
}, {
"label": "Apr"
}, {
"label": "May"
}, {
"label": "Jun"
}, {
"label": "Jul"
}, {
"label": "Aug"
}, {
"label": "Sep"
}, {
"label": "Oct"
}, {
"label": "Nov"
}, {
"label": "Dec"
}]
}],
"dataset": [{
"seriesname": "Projected Revenue",
"renderas": "line",
"showvalues": "0",
"data": [{
"value": "15000"
}, {
"value": "16000"
}, {
"value": "17000"
}, {
"value": "18000"
}, {
"value": "19000"
}, {
"value": "19000"
}, {
"value": "19000"
}, {
"value": "19000"
}, {
"value": "20000"
}, {
"value": "21000"
}, {
"value": "22000"
}, {
"value": "23000"
}]
}]
};
var chartConfigs = {
id: "revenue-profits-chart",
renderAt: "revenue-profits-chart-container",
type: "mscombi2d",
width: 600,
height: 400,
dataFormat: "json",
dataSource: myDataSource
};
React.render( < react_fc.FusionCharts {...chartConfigs
}
/>,
document.getElementById("chart-container")
);
});
Yes you can do that: you just need to replace the methods that have changed from d3 v3 to v4, such as:
var parse = d3.timeParse("%b %Y");
var x = d3.scaleTime().range([0, width]),
y = d3.scaleLinear().range([height, 0]),
xAxis = d3.axisBottom(x).tickSize(-height),
yAxis = d3.axisLeft(y).tickArguments(4);
Etc. Etc.
You can find the working example on my bl.ocks.
My example is the v4 update of another bl.ocks.
Hope that helps.

LabelDisplay for fusion charts MScombi3d charts

I need some help in displaying the xaxis labels for a MSCombi3d chart. I have checked and for 2d charts, there are below two attributes available. which when we set in the chart, the x axis labels will display in a rotated format.
labelDisplay='Rotate' & slantLabels='1'
But when I try to use the above for a MScombi3d chart it doesnot work. I have gone through the documentation and could only find this attribute xLabelGap='50'. But it does not rotate/display the x axis labels in a slant.
Can someone please suggest the attribute that needs to be used for MSCombi3d charts to display the x axis labels in a slant.
Any help on this is much appreciated.
The attribute xLabelGap is perhaps a deprecated or at least not applicable in FusionCharts Javascript version. Although I found some usage of this attribute here, but nowhere in the official FusionCharts docs
I found the attributes labelDisplay and slantLabels in MSCombi3d charts(JS version) functional since its 3.4.0 version. Might work before that too! :D
Below snippet illustrates the use of these attributes with its latest version. You can visit the download page.
FusionCharts.ready(function() {
var revenueChart = new FusionCharts({
type: 'stackedcolumn3dlinedy',
renderAt: 'chart-container',
width: '550',
height: '350',
dataFormat: 'json',
dataSource: {
"chart": {
"caption": "Business Results 2005 v 2006",
"xaxisname": "Month",
"yaxisname": "Revenue",
"showvalues": "0",
"numberprefix": "$",
"labelDisplay": "rotate",
"slantLabels": "1",
"animation": "1"
},
"categories": [{
"category": [{
"label": "Jan"
}, {
"label": "Feb"
}, {
"label": "Mar"
}, {
"label": "Apr"
}, {
"label": "May"
}, {
"label": "Jun"
}, {
"label": "Jul"
}, {
"label": "Aug"
}, {
"label": "Sep"
}, {
"label": "Oct"
}, {
"label": "Nov"
}, {
"label": "Dec"
}]
}],
"dataset": [{
"seriesname": "2006",
"data": [{
"value": "27400"
}, {
"value": "29800"
}, {
"value": "25800"
}, {
"value": "26800"
}, {
"value": "29600"
}, {
"value": "32600"
}, {
"value": "31800"
}, {
"value": "36700"
}, {
"value": "29700"
}, {
"value": "31900"
}, {
"value": "34800"
}, {
"value": "24800"
}]
}, {
"seriesname": "2005",
"renderas": "Area",
"data": [{
"value": "10000"
}, {
"value": "11500"
}, {
"value": "12500"
}, {
"value": "15000"
}, {
"value": "11000"
}, {
"value": "9800"
}, {
"value": "11800"
}, {
"value": "19700"
}, {
"value": "21700"
}, {
"value": "21900"
}, {
"value": "22900"
}, {
"value": "20800"
}]
}, {
"seriesname": "2004",
"renderas": "Line",
"data": [{
"value": "7000"
}, {
"value": "10500"
}, {
"value": "9500"
}, {
"value": "10000"
}, {
"value": "9000"
}, {
"value": "8800"
}, {
"value": "9800"
}, {
"value": "15700"
}, {
"value": "16700"
}, {
"value": "14900"
}, {
"value": "12900"
}, {
"value": "8800"
}]
}],
"trendlines": [{
"line": [{
"startvalue": "22000",
"color": "91C728",
"displayvalue": "Target"
}]
}],
"styles": {
"definition": [{
"name": "bgAnim",
"type": "animation",
"param": "_xScale",
"start": "0",
"duration": "1"
}],
"application": [{
"toobject": "BACKGROUND",
"styles": "bgAnim"
}]
}
}
}).render();
});
<script src="http://static.fusioncharts.com/code/latest/fusioncharts.js"></script>
<!-- Stacked Column 3D + Line Dual Y axis chart showing quarterly cost analysis for the last year. -->
<div id="chart-container">FusionCharts will render here</div>
A fiddle link for the avobe implementation.
Get to know more about the supported attributes in MSCombination 3d charts from here.

Fusion chart multilevelpie text truncate/overlap issue

I have used "multilevelpie" chart .
As the data in the chart is less (say 10 or 1) ,the label names are merging with another.
I have attached the screenshot with the message ,please consider it and send me a solution
Kindly check the JsFiddle re-generated the issue.. & i have attached images also, Strange error
Js Fiddle example
FusionCharts.ready(function () {
var topProductsChart = new FusionCharts({
type: 'multilevelpie',
renderAt: 'chart-container',
id : "myChart",
width: '500',
height: '500',
dataFormat: 'json',
dataSource: {
"chart": {
"caption": "Split of Top Products Sold",
"subCaption": "Last Quarter",
"captionFontSize": "14",
"subcaptionFontSize": "14",
"baseFontColor" : "#333333",
"baseFont" : "Helvetica Neue,Arial",
"basefontsize": "9",
"subcaptionFontBold": "0",
"bgColor" : "#ffffff",
"canvasBgColor" : "#ffffff",
"showBorder" : "0",
"showShadow" : "0",
"showCanvasBorder": "0",
"pieFillAlpha": "60",
"pieBorderThickness": "2",
"hoverFillColor": "#cccccc",
"pieBorderColor": "#ffffff",
"useHoverColor": "1",
"showValuesInTooltip": "1",
"showPercentInTooltip": "0",
"numberPrefix": "$",
"plotTooltext": "$label, $$valueK, $percentValue"
},
"category": [
{
"label": "Sales by category",
"color": "#ffffff",
"value": "150",
"category": [
{
"label": "Food & {br}Beverages",
"color": "#f8bd19",
"value": "55.5",
"category": [
{
"label": "Breads",
"color": "#f8bd19",
"value": "11.1"
},
{
"label": "Juice",
"color": "#f8bd19",
"value": "27.75"
},
{
"label": "Noodles",
"color": "#f8bd19",
"value": "19.99"
},
{
"label": "Seafood",
"color": "#f8bd19",
"value": "0"
}
]
},
{
"label": "Apparel &{br}Accessories",
"color": "#e44a00",
"value": "42",
"category": [
{
"label": "Sun Glasses",
"color": "#e44a00",
"value": "62.08"
},
{
"label": "Clothing",
"color": "#e44a00",
"value": "18.9"
},
{
"label": "Handbags",
"color": "#e44a00",
"value": "6.3"
},
{
"label": "Shoes",
"color": "#e44a00",
"value": "6.72"
}
]
},
{
"label": "Baby {br}Products",
"color": "#008ee4",
"value": "22.5",
"category": [
{
"label": "Bath &{br}Grooming",
"color": "#008ee4",
"value": "9.45"
},
{
"label": "Feeding",
"color": "#008ee4",
"value": "16.3"
},
{
"label": "Diapers",
"color": "#008ee4",
"value": "76.75"
}
]
},
{
"label": "Electronics",
"color": "#33bdda",
"value": "30",
"category": [
{
"label": "Laptops",
"color": "#33bdda",
"value": "8.1"
},
{
"label": "Televisions",
"color": "#33bdda",
"value": "10.5"
},
{
"label": "SmartPhones",
"color": "#33bdda",
"value": "11.4"
}
]
}
]
}
]
}
});
topProductsChart.render();
});
Lets pin-point the concerns we have here:
Problem 1: If the dataValue is 0, there should be no label for it in the chart.
Solution: There might be a philosophy that how to get the context of a zero data and an absent data. Say if I have a category with 0 value, and I remove it from chart, how to set the context that there was at all a data. No matter what for the sake of this requirement, we might think of a dataRefiner() thats just refines out the zero and null data in the dataSource. :)
Problem2: Texts are overlapping.
Solution: Currently FusionCharts seems not to support overlapping management of texts in a ML pie chart. :'( But definitely I can walk through work-arounds that comes in my mind. Lets get our hands dirty!!!
Soultion 1: Attach a {br} tag to the label so that it breaks the line and accommodate in the arc. Not much useful in very thin slices.
Solution 2: Reduce the data labels font-size to an extent it just accommodates. Docs might be useful.
Solution 3: Access the internal graphic labels and rotate it.Word of caution: Accessing internal graphic elements has no official support from FusionCharts.
Creating a workaround accommodating some of the fixes mentioned avobe. This code is compatible with FC 3.11.0. Extending the support for:
enableSmartLabels
manageLabelOverflow
useEllipsesWhenOverflow
now even in MultiLevel Pie charts. This is a temporary and an approximate workaround until FusionCharts natively supports it.
Run the following snippet or play with the fiddle:
/*
Recursively removes the data containing falsy values.
#param data {Object} - The original data.
#return {Object} - The refined data.
*/
function dataRefiner(data) {
var i,
category = data.category,
len = category && category.length;
for (i = 0; i < len; i += 1) {
elem = category[i];
if (elem.category) {
dataRefiner(elem);
} else if (!Number(elem.value)) {
category.splice(i, 1);
i -= 1;
len -= 1;
}
}
return data;
}
var overlapManager = (function() {
return function(chartRef, dataSet) {
var jsonData = chartRef.getJSONData(),
chartAttrs = jsonData.chart;
if (Number(chartAttrs.enablesmartlabels) === 0 || Number(chartAttrs.managelabeloverflow) === 0) {
return;
}
/*
* Returns the point to point distance for two points.
* #return {Number}
*/
function dist_point(point1, point2) {
var math = Math;
return math.sqrt((math.pow((point1.x - point2.x), 2)) + (math.pow((point1.y - point2.y), 2)))
}
/*
* given a radius, center, and two ends of a chord.
* return: {
inner: Coordinate of the dipped point on the inner circle.
outer: coordinate of the dipped point on the outer circle.
}
*/
function give_dips(center_circle, angle, innerRadius, outerRadius) {
var math = Math,
res = {
inner: {},
outer: {}
},
getExtreme = function(radius) {
return {
x: center_circle.x + (radius * math.cos(angle)),
y: center_circle.y - (radius * math.sin(angle))
}
};
if (center_circle) {
res.inner = getExtreme(innerRadius);
res.outer = getExtreme(outerRadius);
}
return res;
}
/*
* Manages the overlapping of the texts in ML pie chart.
* #params: elem - {Object} - Internal store for the graphic and configurations.
* #params: chartRef - {Object} - The reference for the chart.
*/
function wrapText(elem, chartRef) {
var conf = elem && elem.config || {},
smartLabel = chartRef.jsVars.instanceAPI.linkedItems.smartLabel,
jsonData = chartRef.getJSONData(),
chart = jsonData.chart,
useEllipsesWhenOverflow = chart && !!Number(chart.useellipseswhenoverflow),
math = Math,
graphics = elem && elem.graphics,
ringpath = graphics.element && graphics.element.attr('ringpath') || [],
center_circle = {
x: ringpath[0],
y: ringpath[1]
},
innerRadius = ringpath[3],
outerRadius = ringpath[2],
strechAngle = conf.angleStrech,
angle = (2 * math.PI) - conf.startAngle - (strechAngle / 2),
dipPoints = give_dips(center_circle, angle, innerRadius, outerRadius),
center = {
x: (dipPoints.inner.x + dipPoints.outer.x) / 2,
y: (dipPoints.inner.y + dipPoints.outer.y) / 2
},
textObj,
radius = math.min(dist_point(center, center_circle) * math.sin(strechAngle / 2) - (conf.borderWidth || 0),
dist_point(center, dipPoints.inner)),
offset = radius * math.cos(math.PI / 4),
side = math.sqrt(2) * radius;
smartLabel.useEllipsesOnOverflow(useEllipsesWhenOverflow);
textObj = smartLabel.getSmartText(conf.displayValue, side, side);
if (graphics.label && graphics.label.getBBox().width > side) {
(innerRadius !== 0) && graphics.label
.attr({
text: textObj.text,
});
}
}
if (!dataSet) {
dataSet = chartRef.jsVars.instanceAPI.components.dataset[0];
}
var data = dataSet.components.data || [],
len = data.length,
i;
for (i = 0; i < len; i += 1) {
// recursively traverse the graphical objects.
overlapManager(chartRef, data[i]);
}
wrapText(dataSet, chartRef);
}
})();
FusionCharts.ready(function() {
topProductsChart = new FusionCharts({
type: 'multilevelpie',
renderAt: 'chart-container',
id: "myChart",
width: '500',
height: '500',
dataFormat: 'json',
dataSource: dataRefiner(data),
events: {
"rendered": function(e, a) {
if (FusionCharts.version.join('.') !== '3.11.0') {
// It access the internal architechural properties of fusioncharts which might change in future release.
console.log('overlapManager() is a work around supported for FusionCharts 3.11.0 and might not work in this version.');
}
overlapManager(e.sender);
}
}
});
topProductsChart.render();
});
var topProductsChart,
data = {
"chart": {
"useEllipsesWhenOverflow": "1",
"caption": "Split of Top Products Sold",
"subCaption": "Last Quarter",
"captionFontSize": "14",
"subcaptionFontSize": "14",
"baseFontColor": "#333333",
"baseFont": "Helvetica Neue,Arial",
"basefontsize": "9",
"subcaptionFontBold": "0",
"bgColor": "#ffffff",
"canvasBgColor": "#ffffff",
"showBorder": "0",
"showShadow": "0",
"showCanvasBorder": "0",
"pieFillAlpha": "60",
"pieBorderThickness": "2",
"hoverFillColor": "#cccccc",
"pieBorderColor": "#ffffff",
"useHoverColor": "1",
"showValuesInTooltip": "1",
"showPercentInTooltip": "0",
"numberPrefix": "$",
"plotTooltext": "$label, $$valueK, $percentValue"
},
"category": [{
"label": "Sales by category",
"color": "#ffffff",
"value": "150",
"category": [{
"label": "Food & {br}Beverages",
"color": "#f8bd19",
"value": "55.5",
"category": [{
"label": "Breads",
"color": "#f8bd19",
"value": "11.1"
}, {
"label": "Juice",
"color": "#f8bd19",
"value": "27.75"
}, {
"label": "Noodles",
"color": "#f8bd19",
"value": "19.99"
}, {
"label": "Seafood",
"color": "#f8bd19",
"value": "0"
}]
}, {
"label": "Apparel &{br}Accessories",
"color": "#e44a00",
"value": "42",
"category": [{
"label": "Sun Glasses",
"color": "#e44a00",
"value": "62.08"
}, {
"label": "Clothing",
"color": "#e44a00",
"value": "18.9"
}, {
"label": "Han",
"color": "#e44a00",
"value": "6.3"
}, {
"label": "Shoes",
"color": "#e44a00",
"value": "6.72"
}]
}, {
"label": "Baby {br}Products",
"color": "#008ee4",
"value": "22.5",
"category": [{
"label": "Bath & Grooming",
"color": "#008ee4",
"value": "9.45"
}, {
"label": "Feeding",
"color": "#008ee4",
"value": "16.3"
}, {
"label": "Diapers",
"color": "#008ee4",
"value": "76.75"
}]
}, {
"label": "Electronics",
"color": "#33bdda",
"value": "30",
"category": [{
"label": "Laptops",
"color": "#33bdda",
"value": "8.1"
}, {
"label": "Televisions",
"color": "#33bdda",
"value": "10.5"
}, {
"label": "SmartPhones",
"color": "#33bdda",
"value": "11.4"
}]
}]
}]
};
<script src="http://static.fusioncharts.com/code/latest/fusioncharts.js"></script>
<!--
Sales by category shown using Multi-level Pie Chart.
-->
<div id="chart-container">FusionCharts will render here</div>
You might also refer to the fusion treeMap chart to represent the tree and hierarchal data.

Categories

Resources