Accessing a previously drawn plot in javascript/jquery - javascript

I draw a plot like this:
var items = $.get("./moonlight_sonata_diameter.data", function(data) {
items = data.split(/\r?\n/).map( pair => pair.split(/\s+/).map(Number) );
$(function () {
plot = $.plot($("#placeholder"),
[ { data: linePoints} ], {
series: {
lines: { show: true }
},
crosshair: { mode: "x" },
grid: { hoverable: true, autoHighlight: false },
yaxis: { min: 0, max: 5 }
});
});
});
Now at a later moment in time, I want to update the crosshair of the plot. However, because it is embedded in so many functions, I don't know how to access it as I am not familiar with jQuery.
Within the script, I can run:
plot.setCrosshair({x: 100})
However, in another script, at another time, there is no object called plot. Is there a way to access it still?

Actually you have put your plot creation code in document ready function and your
plot.setCrosshair({x:100}) is executed just before your plot creation code. so A simple settimeout will do the trick.
just replace
plot.setCrosshair({x: 4})
with
setTimeout(function(){ plot.setCrosshair({x: 41})}, 3000);
and this will work fine. if you call your setCrosshair function after loading the complete dom then you will not need of setTimeout function. I hope this will help and if not then let me know.
Check it at http://plnkr.co/edit/3cMHmzWEIk6c39mblb0Z?p=preview

Related

Chart.js showing different graphs with select

basically, I have made a Graph that looks like this Image.
I want to make the Graph update whenever I choose an option ( a location in this example). Any idea how could I go on about this?
It sounds like you need to update the chart data whenever the user selects a value from the dropdown. So, add an event listener to the location selector dropdown element, then replace the chart data with the data for the selected location, then call chart update. That part is very simple. It's explained in the chart.js docs under Updating Charts. https://www.chartjs.org/docs/latest/developers/updates.html
For example, if you had location data in an object and a transformData function to convert it to x/y coordinates, you might do something like this for a line chart:
const defaultLocation = 'munchen';
const chart = new Chart(chartCanvas,
{
type: 'line',
data: transformData(locationData[defaultLocation]),
options: {
animation: false,
responsive: true,
maintainAspectRatio: false,
scales: {
y: {
beginAtZero: true,
},
x: {
type: 'timeseries',
},
},
},
});
const locationSelector = document.getElementById("location-selector");
locationSelector.addEventListener('change', ({ target }) => {
chart.data = transformData(locationData[target.value]);
chart.update();
});

Highcharts annotations not rendering

I'm trying to dynamically add annotations to my high charts in React. I'm using the addAnnotation function to add a new annotation whenever a hover event is triggered on my app, but the annotation does not render. I dropped a debugger into my code, and when I call chart.annotations I can see there is currently an array of annotations, but they are not rendering. I even have make a call to the addPlotLine in this function and the plotline is rendered on the chart. My config file looks like this
chart: {
annotations: [{
labelOptions: {
backgroundColor: 'rgba(0, 0, 0, 0.5)',
verticalAlign: 'top',
align: 'right',
}
}],
annotationsOptions: {
},
.... some lots more config options
}
and my on hover function to add the annotation is as follows
if( isNumber(value) )
//this renders a plotline
chart.xAxis[0].addPlotLine(baseChartHandle.generateInteractivePlotLine(value));
// this doesn't render my annotation however
chart.addAnnotation({
linkedTo: value,
title: {
text: "It works!"
}
});
}
I found that when I added annotations using Highcharts that the "linkedTo" function never worked despite my trials.
Despite adding a guid to my point, it never was able to apply it. I would suggest in your case adding it by x and y value, then finding the point that way instead. Here is how I have added annotations in the past successfully:
series.data.forEach(function (point) {
var annotationObject =
{
id: point.id,
labelOptions: {
y: 15,
verticalAlign: 'bottom',
distance: 25
},
labels: []
};
}
var text = <get text you want to push>;
annotationObject.labels.push(
{
point: {
xAxis: 0,
yAxis: 0,
x: point.x,
y: point.y
},
text: text
}
);
_chart.addAnnotation(annotationObject);
});
I also found a bug in HighCharts when using remove annotations, as a heads up. Each point will need an id like above, but it should be called by this line:
_chart.removeAnnotation(id);
It will remove the annotation, however you will get lots of complaints from highcharts if you try to do anything after, and it will break. I found the answer here, in annotations.js :
The red box is code I added. If you do removeAnnotation(ann.id), and it rerenders, it will fail because the labels object is null. Adding this check lets you do that without the labelCollectors failing.
Happy charting.

Javascript Unresponsive Script Error

I am trying to get data to load on my chart from an API. All the data is getting to the chart correctly, but the chart doesn't load and I get the unresponsive script error. I'm using Highcharts. Any suggestions? Thanks. My code is below.
Model
public function ajax_get_chart() {
$quotes = $this->rest->get('api/1/BTCUSD/trades/fetch');
$series_data = array();
$results = $quotes->return;
$i = 0;
foreach ($results as $quote)
{
$series_tmp = array(
'date' => $quote->date,
'price' => $quote->price
);
$series_data[]= $series_tmp;
$i= $i+1;
}
die (json_encode($series_data));
return TRUE;
}
Javascript
$(document).ready(function() {
var chart;
$.ajax({
url: "/chart/ajax_get_chart", // the URL of the controller action method
dataType: "json",
success: function(result)
{
chart = new Highcharts.Chart({
chart: {
renderTo: 'container',
defaultSeriesType: 'bar'
},
title: {
text: 'Stacked bar chart'
},
xAxis: {
title: {
text: 'Price'
}
},
yAxis: {
min: 0,
title: {
text: 'Date'
}
},
legend: {
backgroundColor: '#FFFFFF',
reversed: true
},
tooltip: {
formatter: function() {
return ''+
this.series.name +': '+ this.y +'';
}
},
plotOptions: {},
series: result
});
}
});
});
Sounds like the problem is that there's too much data to present.
You can try using a speedier browser (Chrome usually works pretty fast), limiting the data, or trying another charting library.
Limiting the data is probably the most likely one to work. If you need to show all the data, the best way to go about it would be to only load partial data and then if the user for example scrolls the chart, load the missing data.
Another way to present more data at the same time would be to calculate averages for the data on server. For example, if the ticker data is from every second, you could pre-calculate hourly or even daily averages on the server. This generally allows you to show a relatively accurate chart without causing performance problems, and many libraries also support dynamically loading more accurate data if you zoom the chart.
Highcharts can not handle so huge number of data, but using Highstock with dataGrouping or lazy-loading you should be able to handle a lot of points, see demo.
Also this article should help.

Parsing JSON data for Highcharts

I have been going in circles for a few hours with this and have exhausted all the similar stackoverflow threads and also highcharts docs, so hopefully someone can help.
I am trying to plot a pie chart with a gender split. I have worked with line charts before and so had my data in the format for x and y axis, like this:
[{"y":"Mr","x":"145"},{"y":"Miss","x":"43"},{"y":"Mrs","x":"18"},{"y":"Ms","x":"2"}]
This was getting me somewhere, i could tap into the json and pull out the ints but i couldnt for the life of me get the titles associated with the figures...
function genderData() {
$.getJSON('/statsboard/gender', function(data_g) {
$.each(data_g, function(key_g, val_g) {
obj_g = val_g;
genderChart.series[0].addPoint(parseInt(obj_g.x));
//genderChart.xAxis[0].categories.push(obj_g.y);
});
});
}
I then just called the function genderData as follows:
genderChart = new Highcharts.Chart({
chart: {
renderTo: 'gender',
events: {
load: genderData
}
}
title: {
text: 'Gender Split'
},
plotOptions: {
pie: {
allowPointSelect: true,
cursor: 'pointer',
dataLabels: {
enabled: false
},
showInLegend: true
},
},
series: [{
type: 'pie',
name: 'Gender Split',
data: []
}]
});
So i ended up with an accurate chart but with out the labels, and they would just default to 'slice'...
So close but no cigar ;-)
Soooo i altered my serverside code to return the following format as per the docs :-), now returning the following:
[{"Mr":"145"},{"Miss":"43"},{"Mrs":"18"},{"Ms":"2"}]
This looks pretty much spot on to me, but alas, when i try to accomodate for this on the js code, everything falls apart.
I have been looking at this:
Write JSON parser to format data for pie chart (HighCharts)
but cant get the practice applied here to fit my circumstances.. Can anyone help?
The forms:
[{"name": "Mr", "y": 145}, ...]
or
[["Mr", 145], ...]
will work. Notice the second form is an array of arrays not an array of objects (you were close).
See basic-pie demo (click view options and scroll down to data), series.data docs, and series.addPoint docs for more info.
If you make the server side return the data in one of the two above forms you can just do:
function genderData() {
$.getJSON('/statsboard/gender', function(data_g) {
genderChart.series[0].setData(data_g, true);
});
}
You can set your points as follows:
genderChart.series[0].addPoint({
name: key_g,
y: val_g
});
By rearranging my Json to have "name" and "y" as the keys i was able to make progress i.e:
[{"name":"Mr","y":"145"},{"name":"Miss","y":"43"},{"name":"Mrs","y":"18"},{"name":"Ms","y":"2"}]
Then by looping through the json data and parsing the "y" value as a int with the function parseInt() in the JS i was able to get my desired result...
function genderData() {
$.getJSON('/statsboard/gender', function(data_g) {
$.each(data_g, function(key_g, val_g) {
obj_g = val_g;
genderChart.series[0].addPoint({
name: obj_g.name,
y: parseInt(obj_g.y)
});
console.log(obj_g.y)
});
});
}
I know this question has been solved. but the map function for array might be a good choice in these cases, I love map in functional language!
data = [{"y":"Mr","x":"145"},{"y":"Miss","x":"43"},
{"y":"Mrs","x":"18"},{"y":"Ms","x":"2"}];
var series = data.map(function(e){ return parseInt(e.x); });
.... hight chart ....

With flot, how can I create a linked pie chart that takes you to other web pages?

In flot, how can I create a pie chart where each wedge is a link to a different web-page?
I gave it a shot, but I wasn't able to do it. I started with this example, then added:
grid: { clickable: true },
right above the "pie: {" line. Then I added a plotclick function at the end:
$("#placeholder").bind("plotclick", function (event, pos, item) {
alert('click!');
for(var i in item){
alert('my '+i+' = '+ item[i]);
}
});
You'll see the "click!" message, but "item" has no properties.
I was thinking you'd just add URLs to the data ojects, then forward the browser to the appropriate URL from within the plotclick function. If you figure it out, I'd be interested to know!
Update: Here's something that might work -- it just turns the labels into links. Put the URLs in your data like this:
$.plot($("#placeholder"), [
{ label: "Serie1", data: 10, url: "http://stackoverflow.com"},
{ label: "Serie2", data: 30, url: "http://serverfault.com"},
{ label: "Serie3", data: 90, url: "http://superuser.com"},
{ label: "Serie4", data: 70, url: "http://www.google.com"},
{ label: "Serie5", data: 80, url: "http://www.oprah.com"},
{ label: "Serie6", data: 110, url: "http://www.realultimatepower.net/"}
],
Then set the labelFormatter to something like:
return ''+serie.label+'<br/>'+Math.round(serie.percent)+'%';
Clicking in the pie wedges themselves still does nothing special, though.
I know this is an old thread but I have discovered another way of doing this.
Make sure grid is set to clickable
var data = [{
"label" : "series1",
"data" : 24,
"url" : "http://stackoverflow.com"
},
{
// etc etc
}];
$.plot($('.chart'), data, function() {
// Your options
grid: {
clickable:true
}
});
Bind a click function to the element and use javascript to redirect to the url.
$('.chart').bind("plotclick", function(event,pos,obj) {
window.location.replace(data[obj.seriesIndex].url);
});
Adding to the answer by Derek Kurth...
It looks like flot is ignoring any additional objects that we include in the JSON. For example when I used
data: [10, 0, "http://stackoverflow.com"]
// 0 is used as an intercept value for y-axis
it worked without any trouble and I was able to access the data from the event handler like
$("#placeholder").bind("plotclick", function (event, pos, item) {
alert(item.series.data);
});
I am new to this flot library and not great at JavaScript. So probably this is not the right way to do things but it works. I have always felt that embedding additional information in UI elements in HTML is a pain :(

Categories

Resources