Get position in array element - javascript

In JavaScript, I am unable to figure out how to use the data object in the function below to get the position of the clicked-on data point (e.g. third data point in the series).
Using chartsNew.js, a popular fork of charts.js, this code shows the value of the datapoint at the mouse click:
function fnMouseDownLeft(event,ctx,config,data,other){
if(other != null){
window.alert("["+ data.labels[other.v12]+", "+data.datasets[other.v11].data[other.v12] +"]");
}else{
window.alert("You click Left but not on a data");
}
}
How do I display the clicked element's position in the data series?
jsFiddle Example
This seems the most promising but I don't understand the relationship between data.datasets, data.datasets[other] and data.datasets[other].data[other]
window.alert("Position: " + data.datasets[other.v11].data[other.v3] );
Here is documentation:
https://github.com/FVANCOP/ChartNew.js/wiki/100_095_Mouse_Actions
https://github.com/FVANCOP/ChartNew.js/wiki/120_Template_variables#inGraphDataTmpl-annotateLabel
My confusion: v12 (for a line chart) should display the position of data in the series (which is what I want) but instead it displays the x-axis value for that datapoint.

other.v12 seems to do the trick
alert(other.v12);
http://jsfiddle.net/wesn0xm5/1/
Not sure why it's not giving you the series, it does for me.

Related

How to get data index for given pixel in ChartJs?

On one hand I have input which is mouse position over the chart. On the other hand I have to call ChartJs function which requires data index (I am manually triggering showing tooltip -- https://www.chartjs.org/docs/latest/samples/advanced/programmatic-events.html).
I can see there are functions like "getValueForPixel" and "getLabelForValue" but I cannot find function which would translate pixel position into index within the data. Is there such function? If no, how can I translate between those two?

How to pass multivalue data to a choropleth in dc.js

I'm working on a crossfilter between a line chart and choropleth. I recently got a much better understanding of the reduce method in dc.js, so I want to pass through some more metadata about each data point to my line chart and my choropleth. This is working really well for the line chart, and I now have a tooltip showing lots of information about each point.
For my choropleth, however, the transition to using reduce instead of reduceSum has really messed up my data. For example:
The value getting passed to the tooltip isn't the data I would expect, and I have no idea where the calculation is coming from (it almost seems like it's from the SVG path, or even the color accessor?)
As I toggle between different renderings of the choropleth, my choropleth changes, but the value on the tooltip stays exactly the same
The initial render of the choropleth is showing a fully blue map, so it seems like the initial value might be incorrect, anyway.
I'm trying to understand how I can identify the data point that's coming from the group, use that to render the choropleth based on a specific value (total_sampled_sales) and then pass that data to the tooltip so that each state's value and metadata can be displayed.
Also, any tips for debugging this type of issue would be greatly appreciated. As you may be able to see from my console.logs, I'm having a hard time tracing the data through to the tooltip. This is presumably the problem block:
us1Chart.customUpdate = () => {
us1Chart.colorDomain(generateScale(returnGroup()))
us1Chart.group(returnGroup())
}
us1Chart.width(us1Width)
.height(us1Height)
.dimension(stateRegion)
.group(returnGroup())
.colors(d3.scaleQuantize().range(colorScales.blue))
.colorDomain(generateScale(returnGroup()))
.colorAccessor(d => {
// console.log('colorAccessor:', d)
return d ? d : 0
})
.overlayGeoJson(statesJson.features, "state", d => {
// console.log(`geojson`, d, d.properties.name)
return d.properties.name
})
.projection(d3.geoAlbersUsa()
.scale(Math.min(getWidth('us1-chart') * 2.5, getHeight('us1-chart') * 1.7))
.translate([getWidth('us1-chart') / 2.5, getHeight('us1-chart') / 2.5])
)
.valueAccessor(kv => {
// console.log(kv.value)
if (kv.value !== undefined) return kv.value
})
.renderTitle(false)
.on('pretransition', (chart) => {
chart.selectAll('path')
.call(mapTip)
.on('mouseover.mapTip', mapTip.show)
.on('mouseout.mapTip', mapTip.hide);
})
https://jsfiddle.net/ayyrickay/f1vLwhmq/19/
Note that the data's a little wonky because I removed half of the records just for size constraints
Because of the data binding with choropleths, I'm now using the data that's passed through (specifically, the US State that was selected) and then identifying the data point in the crossfilter group:
const selectedState = returnGroup().all().filter(item => item.key === d.properties.name)[0]
So I have a returnGroup method that selects the correct choropleth group (based on some app state), gets the list, and then I filter to see which item matches the name property passed to the tooltip. Because filter returns an array, I'm just being optimistic that it'll filter to one item and then use that item. Then I have access to the full data point, and can render it in the tooltip accordingly. Not elegant, but it works.

Adding dynamic mean to time series chart

I will try to explain my problem as much accurate as possible. I am looking for a javascript chart library filling the two following conditions:
From an ajax request retrieving time series,
display dynamically data when changing the time window.
such as it is perfectly done on highstocks: http://www.highcharts.com/stock/demo/basic-line
And
plot an horizontal line corresponding to the mean,
changing when the user update the time window on the chart.
Actually it is possible to display an horizontal line. But they are fixed on the whole data and do not change accordingly when the time window is modified:
http://www.highcharts.com/stock/demo/yaxis-plotlines
I am quite new to the topic and would like to know if it'sp ossible to modify Highstock classes to have such a result. Or maybe some other js libraries exists?
Using a combination of the answer here:
Highchart, get total of visible series data after setExtremes
And an example of dynamic average using all visible series that I made for a previous question, here:
http://jsfiddle.net/jlbriggs/gweuLegq/
I put together this example, using the afterSetExtremes event, like this:
xAxis : {
events:{
afterSetExtremes:function() {
var ext = this.getExtremes();
getAverage(this.chart, ext.min, ext.max, show, width, avgColor, dashStyle);
}
}
},
Working example here:
http://jsfiddle.net/jlbriggs/c93543yL/
The idea is:
1) capture the afterSetExtremes event
2) get the resulting axis min and max
3) loop through the series data
4) if a point is between the min and max, increment the count, and add the
point's y value to the sum
5) calculate the average accordingly, check for existence of average series, if exists, update, if not, add
It could as easily use a plot line that you add/remove as needed instead of a series, but I like having it as a series so that it has a legend entry.

Labels on d3.js time series chart

I've been working on a d3.js time series line chart.
I am using d3.nest and then looping through the nested groups to create each line.
The complete code Here
What I would like to do is have each line's label (the country name) show up on the y-axis at the position of the last observation (given by credit). To find this position I use:
dataNest.forEach(function(d) {
var position = d.values[6].credit;
console.log("Selected Value", position);
Then later pass position to .attr("y", y(position)) when I append the text.
The issue I'm having is that the position returned from d.values[6].credit is correct as logged in the console. But I get an
Uncaught TypeError: Cannot read property 'credit' of undefined
error. This leads to the axes not being plotted.
(Eventually I want the labels to appear on mouseover, but that is for another day).
Slovak Republic only has 2 data points:
Slovak Republic,SK,Jan 2007,100
Slovak Republic,SK,Jan 2008,105.2
Instead of the hard-coded 6, just use:
var position = d.values[d.values.length-1].credit;
Example here.

Dygraph: How to hide x,y value in legend?

While generating a track with the help of dygraph library, I have set the legend: always (this display the legend with series name present on that particular track even without mouseover). But when I move to certain graph, the legend changes and shows the value of each series at that particular mouse pointer. I don't want the legend to change and it should just show the series name and not the values. I am using javascript to implement my app. Any way to do the same?
One trick that might be good enough is to supply a custom valueFormatter function for each axis which simply returns an empty string:
axes: {x: {valueFormatter: function (x) {return ''}},
y: {valueFormatter: function (y) {return ''}},
y2: {valueFormatter: function (y2) {return ''}}
}
This prevents the values from being shown, but still switches between line samples and ':' characters depending on the position of the mouse.
At the moment there's no easy way to do this. Your best bets are to either generate the legend yourself using dygraphs' API or to throw a transparent div over your chart which captures all the mouse events.
Well! it might be not a good way but I have found an alternative to do it. Declared a new boolean variable in dygraph.js which checks whether user wish to see x-y values on legend. Using this variable in function generateLegendHTML (defined in legend.js), i have made the control to always go in the first if loop. This makes the dygraph to always show static legend.
You can do the following -
Step 0 - Add a few necessary options and tags -
labelsDiv: document.getElementById("labels"),// in the dygraph options
<div id="labels"></div> <!-- Add this somewhere in your HTML-->
Step 1 - Declare a variable -
var defaultLabelHTML = undefined;
Step 2 - Use drawCallback option -
drawCallback: function(dygraph, is_initial){
if (is_initial)
{
defaultLabelHTML = document.getElementById("labels").innerHTML;
}
},
Step 3 - Use highlightCallback option -
function(e, x, pts, row)
{
document.getElementById("labels").innerHTML = defaultLabelHTML;
}

Categories