How do I draw donut with absolute values intead of percents with Keen.io & c3? - c3.js

I'm using Keen.io ("version": "3.4.1") JavaScript SDK, along with their integration with C3.js, to produce a donut graph by using the code below. However, I don't want percentages, but rather absolute numbers. i.e. Not 25%, but 7.
From reading the docs and looking at examples (see "var c3gauge") and example, I thought you could modify the output by applying the chartOptions. That doesn't seem to be working. At this point, I feel like I'm doing something stupid I'm just not catching.
How do I display absolute values in my donut, not percentages?
var c3donut = new Keen.Dataviz()
.library('c3')
.chartType('donut')
.el(document.getElementById(elem))
.title("Awesome Sauce")
.parseRawData(data)
.chartOptions({
donut: {
label: {
format: function (value) {
console.log("I never fire, why?");
return value;
}
}
}
})
.render();

This is possible with keen-dataviz.js library. I've created a working example here: https://jsfiddle.net/bx9efr4h/1/
Here's part of the code that made it work:
var chart = new Keen.Dataviz()
.el('#chart')
.type("donut")
.chartOptions({
donut: {
label: {
format: function(value) {
return value;
}
}
}
})
.prepare();
keen-js works a little differently because c3.js is not the default dataviz library for it. This is likely why it isn't working like expected for you.

Related

amCharts v5 demo code doesn't compile in VS Code

I'm posting this in case anyone else ran into the same issue. As of Feb 2022 amCharts v5 is still very new and the demo code seems to need a little curation on amCharts' part i.e. Show us that the object needs to be declared with a type - AND TELL US WHICH TYPE TO USE!
I copied the code from this demo example verbatim
// Add bullet
// https://www.amcharts.com/docs/v5/charts/xy-chart/series/#Bullets
let circleTemplate = am5.Template.new({});
series0.bullets.push(function() {
let graphics = am5.Circle.new(root, {
fill: series0.get("fill"),
}, circleTemplate);
return am5.Bullet.new(root, {
sprite: graphics
});
});
and got the following error
Even the documentation page does not suggest specifying the type
I reached out to amCharts via their support system and got the following response:
Hi Adam,
How about specifying Circle as a generics for themplate?
let circleTemplate: am5Template<am5.Circle> Yours sincerely,
Martynas Majeris amCharts
First off am5Template is not valid, but I assumed he meant am5.Template
Second, his code is not complete and did not compile as-is.
I tried a few variations and the following worked:
// Add bullet
// https://www.amcharts.com/docs/v5/charts/xy-chart/series/#Bullets
let circleTemplate = am5.Template.new({}); // <-- demo code
// let circleTemplate3: am5Template<am5.Circle>; // <-- code provided by the support person
let circleTemplate2: am5.Template<am5.Circle> = am5.Template.new({}); // <-- WORKING modification of the suggested code
// let circleTemplate1: am5Template<am5.Circle> = am5.Template.new({}); // attempted variation of the suggested code
series0.bullets.push(function() {
let graphics = am5.Circle.new(root, {
fill: series0.get("fill"),
}, circleTemplate2); // <-- compiler now sees the object as the appropriate object type
return am5.Bullet.new(root, {
sprite: graphics
});
});
Another example (from the same demo) which requires the same modification, but with a different template type:
// Add bullet
// https://www.amcharts.com/docs/v5/charts/xy-chart/series/#Bullets
let starTemplate: am5.Template<am5.Star> =am5.Template.new({});
series1.bullets.push(function() {
let graphics = am5.Star.new(root, {
fill: series1.get("fill"),
spikes: 8,
innerRadius: am5.percent(70),
}, starTemplate);
return am5.Bullet.new(root, {
sprite: graphics
});
});
So yeah, maybe this will help someone who ran into the same issue as me. What would be REALLY nice is if they had Cope Pen examples that use TS and not just JS

dc.js group.top(5) not working in chart

i am trying to display top 5 country based on revenue
i tried feeding in chart its not working
.group(countryGrp.top(10))
but when i tried console.log(countryGrp.top(10)) i can see the values though
var country = data.dimension(function(d){return d.PName});
var countryGrp = lead.group().reduceSum(function(d) {
return d.Amount;
});
var leadBarChart = dc.barChart("#country-chart")
leadBarChart.width(500).height(450).transitionDuration(750)
.margins({
top : 20,
right : 10,
bottom : 80,
left : 50
})
.dimension(country)
.group(countryGrp.top(10))
.ordinalColors([ "#1F77B4" ]).elasticY(true).centerBar(true)
.title(function(d) {
return d.Amount;
}).gap(6).xUnits(function() {
return 2;
})
.x(d3.scale.linear())
.renderHorizontalGridLines(true).xAxis().ticks(5)
.tickFormat(d3.format("d"));
i am getting this error uncaught TypeError: undefined is not a function can any one help me out here. Thanks in advance
So group.top(N) doesn't return a group object; it returns an array. You need to supply a group for the group argument.
Unfortunately the bar chart does not currently support capping but what you can do is prefilter the data as explained here:
https://github.com/dc-js/dc.js/wiki/FAQ#filter-the-data-before-its-charted
Basically you will create a "fake group" which has an .all() function which returns only the items you want.
I am planning to fix .data() so that it works for bar charts:
https://github.com/dc-js/dc.js/issues/584
(and it would also be nice to support capping) but for now I think you are stuck with the "fake group" workaround.
Please comment here if you can't get this to work, or add you example to the wiki linked above if you do get it to work!
You'll want to use something like the following:
function getTops(source_group) {
return {
all: function () {
return source_group.top(5);
}
};
}
var fakeGroup = getTops(groupToFindTopsFor);
You can then use .group(fakeGroup) to properly chart your data.

turning pointLabels on and off in jqplot

I am trying to turn pointLabels on and off programmatically. I thought it would work something like this:
var data_ = [[1,1],[2,5],[4,9]];
var graph = $.jqplot(id_graph, [data_], {
series:[{pointLabels: { show:true } }]
}
);
graph.series[0].pointLabels.show=false;
graph.replot();
However, this still displays the point labels.
Thanks for any help!
althoug this post is old I found a solution for the problem:
var data_ = [[1,1],[2,5],[4,9]];
var graph = $.jqplot(id_graph, [data_], {
series:[{pointLabels: { show:true } }]
}
);
graph.series[0].plugins.pointLabels.show=false;
graph.replot();
Instead of using
graph.series[0].pointLabels.show=false;
use
graph.series[0].plugins.pointLabels.show=false;
In my case this worked.
Adding to Boro's answer, if you want to toggle the marker on a single series, it would be quicker to do:
graph.drawSeries({markerOptions:{show:false}},seriesIndex); //redraw single series
Calls to replot can be expensive with a large number of series.
Revved fiddle here.
I think what you want is actually showMarker option. Since in this code you are not setting point labels therefore they will never be show. The showMarker will let you switch the dots of the graph on/off.
Is that what you are in fact after? Otherwise please provide an example that you use.
Here is a sample made for a similar issue.
Please see this sample. There on the button click the change of makers visibility occurs.
Update:
This sample shows the solution, which uses the approach presented above, i.e. re-plotting the plot while changing the 'pointLabels' new parameter.
jQuery(document).ready(function () {
var data = [
[1, 1],
[2, 5],
[4, 9]
];
var graph;
var isShowPointLabels = true;
function makePlot(showPointLabels) {
graph = $.jqplot("chart", [data], {
series: [{
pointLabels: {
show: showPointLabels
}
}]
});
}
makePlot(isShowPointLabels);
$("#click").click(function () {
isShowPointLabels = !isShowPointLabels;
makePlot(isShowPointLabels);
graph.replot();
});
});
In this case I couldn't figure out how to use drawSeries(...) to re-plot just a single series, as #Mark shows for marker, which would be a good practice to do here.

Skip some tags with stripTags() function in prototypejs

I've successfully implemented a bit of code that strips all HTML from a pasted string using stripTags(). My next goal is to mark a few tags with white flags so they get ignored on 'paste' event using .wrap() to augment the function.
I'm using prototype.js as a framework and have slowly been working through the growing pains of learning both the framework and javascript, but this issue has presented a bit of a roadblock.
I've googled around a bit and found what looks like two great solutions, but I don't seem to be implementing them correctly.
Found solutions:
http://perfectionkills.com/wrap-it-up/ (function to indicate tags to remove)
and
http://pastebin.com/xbymCFi9 (function to allow tags to keep)
I pretty much copied and pasted from the latter.
If I pull the 'br' from the code, then the regex is ignored and all html is stripped. If I leave it, nothing gets pasted.
Here is what I've pieced together (and I feel silly for not being able to figure this out!).
String.prototype.stripTags = String.prototype.stripTags.wrap(
function(proceed, allowTags) {
if (allowTags) {
if (Object.isString(allowTags)) allowTags = $w(allowTags)
this.gsub(/(<\/?\s*)([^\s>]+)(\s[^>]*)?>/, function(match) {
if (allowTags.include(match[2].toLowerCase()))
return match[1] + match[2] + match[3] + '>'
})
} else {
// proceed using the original function
return proceed();
}
});
WysiHat.Commands.promptLinkSelection = function() {
if (this.linkSelected()) {
if (confirm("Remove link?"))
this.unlinkSelection();
} else {
var value = prompt("Enter a URL", "http://www.alltrips.com/");
if (value)
this.linkSelection(value);
}
}
document.on("dom:loaded", function() {
var editor = WysiHat.Editor.attach('event_desc');
var toolbar = new WysiHat.Toolbar(editor);
editor.observe("paste", function(event) {
var el = $(this);
setTimeout(function() {
var pText = el.innerHTML.stripTags('br');
//alert(pText);
$('event_desc_editor').update(pText);
$('event_desc').setValue(pText);
}, 0);
});
(You may recognize the WysiHat code from 37Signals text editor)
note: you can see the alert commented out. If I do alert the ptext, I get 'undefined' returned.
So I've given up on and moved to a regex solution:
el.innerHTML.replace(/<(?!\s*\/?\s*p\b)[^>]*>/gi,'')

prototype get inner html of multiple classes

I am new to prototype and finding it a lot more difficult than jquery. All i want to do is get the inner html of various classes.
$$('.book').each(function() {
var msg = this.down(".information");
alert(msg.innerHTML);
//new Tip(this, msg.innerHTML, {stem: 'topLeft', hook: { tip: 'topLeft', mouse: true }, offset: { x: 14, y: 14 }});
});
I'm trying to create tooltips for multiple items, but I'm not even getting the alert.
I think you can probably prevent the extra dom work of down() like this:
$$('.book .information').each(function(book) {
alert(book.innerHTML);
});
remember you also have the ability to use advanced CSS2 and CSS3 selectors in prototype like this for example:
$$('.book a[rel]').each(function(el) {
alert(el.rel);
});
see the bottom of this page for more examples http://www.prototypejs.org/api/utility/dollar-dollar
The this variable is not pointing to the element you're iterating over in Prototype, you have to explicitly use a parameter:
$$('.book').each(function(book) {
var msg = book.down(".information");
alert(msg.innerHTML);
});

Resources