TL;DR: Try to figure out what state the radio buttons of this nvd3 multibarchart are in based on the console log - i.e. how can I reliably determine what data streams are currently being shown to the user?
Long version:
I'm trying to figure out which data streams/arrays are displaying in an nvd3 multibar chart so that I can update other DOM nodes with information relevant to those streams. The only trouble is that the chart.state seems to be returning the opposite of what it should: if I toggle a stream "off", chart.state.disabled is true for that stream ... except seemingly the first time something is toggled, when all chart.state.disabled[i] streams is set to false... the entire behaviour of that property seems like it isn't functioning as it should to me. Is it a bug or do I not understand how it's supposed to be used?
Some code to log the state of three streams, for example:
chart.legend.dispatch.on("legendClick", function() {
var state = chart.state;
console.log(state.disabled[0] + ","
+ state.disabled[1] + ","
+ state.disabled[2]);
});
Well, as is typical, I dig around for half an hour, can't get it working, post on SO and then go and try a different approach which immediately works:
chart.dispatch.on("stateChange", function(e){
console.log(JSON.stringify(e.disabled);
}
So I believe it's a bug with the ledgendClick event that doesn't update the chart state correctly.
Related
I want to disable the hover effect on certain data points of a dataset under certain conditions using Chart.js.
I basically need to modify the dataset before drawing the line graph so it looks in the way i want. (e.g extending the line along x axis) And i don't want the hover effect to take place on some of those data points.
After implementing the business logic, I've looked for a scriptable option
so i can use the context regarding the data point the user is on. I've came across solutions for basically cancelling all the hover effects on a single graph but not conditionally just like I've mentioned.
I've tried to use onHover with the context and set the hoverRadius conditionally and it looks as i expected but it gives me an error saying "Cannot assign to read only property 'hoverRadius' of object".
// in the options object
onHover: function (event, context) {
if (!isEmpty(context)) {
context[0]._options.hoverRadius = 0;
}
}
Most probably, the regarding object has been made immutable intentionally.
So what's the correct way of implementing this behavior in Chart.js?
I have a highchart that generates data like so:
What I want to do is when I click the Major Versions drop down button and select a version, the version is displayed and the rest of the series points are removed like so:
As reference, I've used this stackoverflow question as a guide removing datapoints. However when I try to implement this in coffeescript like so:
chart = $('#vulnerability_version_chart').highcharts()
chart.series[0].setData([])
chart.series[1].setData([])
chart.series[2].setData([])
chart.xAxis[0].setCategories(calculateCategory(releases))
chart.series[0].setData(calculateY(releases), calculateHighVulns(releases))
chart.series[1].setData(calculateY(releases), calculateMediumVulns(releases))
chart.series[2].setData(calculateY(releases), calculateLowVulns(releases))
All that this code does is remove all the data points and it doesn't rerender with the new points. I've looked into update(), redraw, reflow and I am still unable to get it to render. What am I missing here?
HOw can I remove the points after 1.4.4? I've tried `setData and for loops. This doesn't seem to work.
I have this (probably weird) setup where I'm ajax'ing a template of sorts into a section of my page, and then trying to draw a chart with D3.js inside one of the elements of that template.
Weirdly, sometimes it renders, others it doesn't, complaining about what I figure out must be the element which holds the chart not being rendered at that moment, as it's coming from an ajax call.
How can I overcome this? I've been reading about jQuery's when() and then() but I can't seem to grasp how it might (if at all) help me in my case.
This is a (simpler) version of my code:
$.get("/url/to/my/template", function(templateData){
// this element is already in the page
$("#elementInThePage").html(templateData);
// this function draws the D3 chart
buildChart();
});
function buildChart(){
// this element comes in the template
// sometimes it's already available, other times it isn't
// and obviously d3 complains about it not being there
var element = d3.select("#elementInTemplate");
// do more stuff (...)
}
To sum it up, how to be sure I only call buildChart() when #elementInTemplate has rendered?
EDIT: I already tried chaining .done() to my $.get, but exactly the same thing happens.
EDIT2: I think I mis-explained my problem. D3.js doesn't complain about it not being there. What actually happens is that it is drawing the chart conditionally in regard to the size (WxH) of the element in the template, and because that element still hasn't rendered, it borks up the chart.
EDIT3: Another (relevant, I think), note: in buildChart(), D3.js depends of the dimensions of the template's element. So, if I
console.log($("#elementInTemplate").width()+" x "+$("#elementInTemplate").height());
If it fails, I get 234 x 0. If it works I get 234 x 456.
I'm wondering if anyone might be able to help with an issue I'm having with NVD3 where the chart occasionally gets drawn erratically. This typically occurs when I leverage the toggle for labels (i.e. where you can show or hide different lines). The result is something that looks like the following image:
Initially the chart looks normal (i.e. a single line). However, after enabling and disable other lines on the chart, the image ends up being drawn in the erratic fashion shown above.
Any help on how to address this would be greatly appreciated. I was not sure what to search for to describe the issue so apologies if the answer was readily available.
In case anyone else runs across this (which is actually unlikely) I tracked down the issue to the following added lines of code to the "mouseover_line" event (commented out below):
function mouseover_line(evt) {
var yaxis = data[evt.seriesIndex].yAxis === 2 ? yAxis2 : yAxis1;
// evt.series.values[evt.pointIndex].x = d3.time.format('%x')(new Date(evt.point.x));
// evt.series.values[evt.pointIndex].y = d3.format(',')(evt.point.y);
evt.value = evt.point.x;
evt.series = {
value: evt.point.y,
color: evt.point.color,
key: evt.series.key
};
tooltip
.duration(0)
.valueFormatter(function(d, i) {
return yaxis.tickFormat()(d, i);
})
.data(evt)
.hidden(false);
}
I had added those lines in to fix the hover over labels for the line graph (my line graphs had a datetime x-axis and comma separated integer y-axis). Upon adding those lines it seems the extra processing time required resulted in the lines drawing eratically whenever you toggle a series on/off.
Not too sure what the mechanism is that causes the issue but those lines were the root cause.
So,
I'm just starting to learn CreateJS and I encountered my first problem: I can't get tweening to work (as I expect it should work).
Here is the example: http://www.hakoniemi.net/labs/createjs-test/
I want to get that cloud to move from right to left - at the moment it only jumps to the target.
The code looks:
createjs.Tween.get(stack["cloud"]).to({"x":25}, 1000).call(test);
where createjs.Tween.get(stack["cloud"]) is valid and function test is executed. However there's no visual effect of 1000ms taking place at all.
I've looked through the tutorials and this is how things should work, but they're not. What am I doing wrong?
Edit: if I re-execute code in console with different value, then tweening and visual effect happens normally (here's a version where setTimeout is used: http://www.hakoniemi.net/labs/createjs-test/index2.html)
You have a type problem when setting the initial x value in
if (this.getAttribute("x")) {
ref.x = this.getAttribute("x");
}
The problem is that getAttribute() returns a string, which you can verify outputing Object.prototype.toString.call(ref.x). This way, it seems the first time the tween tries to run it can't do the proper math. In the end, it correctly updates the value to the end value as a number and that's why next calls to the same method work properly.
You can fix this just by making sure that ref.x is a number. For example:
if (this.getAttribute("x")) {
ref.x = parseInt(this.getAttribute("x"));
}
You can see it working in this fiddle.
One last thing, BitmapImageLoaded is adding the assets to the stage as soon as they are loaded. If your clouds image gets loaded before the background, it will be placed under it and you won't be able to see them. (just in case :))