Adding a functionality in the chart.js file - javascript

This is a chart.js file with functionality of of clicking and adding of data to the graph but I want to add some data beforehand so that opening it shows some of the point.
Please, help me telling me how to do this so that some of data as points in shown on the graph when the user opens it.
Here is my code :
let globalChartRef;
window.addEventListener('DOMContentLoaded', function () {
createGraph();
document.getElementById('ChartCnvs').onmousedown = function (result) {
ourClickHandler(result);
};
}, false);
function randomColor(alpha) {
return String('rgba(' + Math.round(Math.random() * 255) + ',' + Math.round(Math.random() * 255) + ',' + Math.round(Math.random() * 255) + ',' + alpha + ')');
}
function ourClickHandler(element) {
let scaleRef,
valueX,
valueY;
for (var scaleKey in globalChartRef.scales) {
scaleRef = globalChartRef.scales[scaleKey];
if (scaleRef.isHorizontal() && scaleKey == 'x-axis-1') {
valueX = scaleRef.getValueForPixel(element.offsetX);
} else if (scaleKey == 'y-axis-1') {
valueY = scaleRef.getValueForPixel(element.offsetY);
}
}
if (valueX > globalChartRef.scales['x-axis-1'].min && valueX < globalChartRef.scales['x-axis-1'].max
&& valueY > globalChartRef.scales['y-axis-1'].min && valueY < globalChartRef.scales['y-axis-1'].max) {
globalChartRef.data.datasets.forEach((dataset) => {
dataset.data.push({
x: valueX,
y: valueY,
extraInfo: 'info'
});
});
globalChartRef.update();
}
}
function createGraph() {
var config = {
type: 'scatter',
data: {
datasets: [{
label: "Dataset Made of Clicked Points",
data: [],
fill: false,
showLine: true
}]
},
options: {
title: {
display: true,
text: "Chart.js Interactive Points"
},
scales: {
xAxes: [{
type: "linear",
display: true,
scaleLabel: {
display: true,
labelString: 'X-Axis'
},
ticks: {
min: -10,
suggestedMax: 5
}
},],
yAxes: [{
display: true,
scaleLabel: {
display: true,
labelString: 'Y-Axis'
},
ticks: {
beginAtZero: true,
suggestedMax: 15
}
}]
},
responsive: true,
maintainAspectRatio: true
}
};
config.data.datasets.forEach(function (dataset) {
dataset.borderColor = randomColor(0.8);
dataset.backgroundColor = randomColor(0.7);
dataset.pointBorderColor = randomColor(1);
dataset.pointBackgroundColor = randomColor(1);
dataset.pointRadius = 7;
dataset.pointBorderWidth = 2;
dataset.pointHoverRadius = 8;
});
var ctx = document.getElementById('ChartCnvs').getContext('2d');
globalChartRef = new Chart(ctx, config);
}

Related

Monitoring datas with HighChart using .net6 and javaScript

I have a BackgroundService class that is load 60 point of data at first load then add a point every minute to chart.I have used SignalR with HighChart in .Net6,the problem is that adding point in javascript class does not work.I want to add a point with it's data's at the end of the chart then shift it .
this is backgroundService Class:
public class TxnRespHistoryBackgroundCaller : BackgroundService
{
public ITxnRespHistoryRepository Repository { get; }
public IHubContext<MonitoringHub> HubContext { get; }
private bool isFirstCall = true;
public TxnRespHistoryBackgroundCaller(ITxnRespHistoryRepository repository, IHubContext<MonitoringHub> hubContext)
{
Repository = repository;
HubContext = hubContext;
}
private static List<string> FailResps
{
get
{
try
{
return new List<string>() { "3", "92", "91", "96", "80", "84" };
}
catch
{
return new List<string>();
}
}
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
await Task.Run(async () =>
{
while (!stoppingToken.IsCancellationRequested)
{
if (isFirstCall == true)
{
try
{
var datasets = new List<dynamic>();
DateTime FinishTime = DateTime.Now;
try
{
FinishTime = Repository.GetMax(TxnRespHistory.Columns.EndTime);
}
catch
{
try
{
FinishTime = Repository.GetServerTime();
}
catch
{
FinishTime = DateTime.Now;
}
}
var yesterdayalltxn = await Repository.GetTxnHisByResp(59, TransactionType.Yesterday, FinishTime, FailResps);
var failtxn = await Repository.GetTxnHisByResp(59, TransactionType.fail, FinishTime, FailResps);
var alltxn = await Repository.GetTxnHisByResp(59, TransactionType.All, FinishTime, FailResps);
var suctxn = await Repository.GetTxnHisByResp(59, TransactionType.successful, FinishTime, FailResps);
datasets.Add(new
{
data = suctxn.Value,
label = "Success",
Key = "Success",
color = "#308014"
});
datasets.Add(new
{
data = failtxn.Value,
label = "UnSuccess",
Key = "Fail",
color = "#ff0000"
});
datasets.Add(new
{
data = alltxn.Value,
label = "Total",
Key = "Total",
color = "#7094db"
});
datasets.Add(new
{
data = yesterdayalltxn.Value,
label = "Yesterday",
Key = "Yesterday",
color = "#b3b3b3"
});
var result = new
{
success = true,
labels = alltxn.Key,
datasets = datasets
};
await HubContext.Clients.All.SendAsync("populatetxns", JsonConvert.SerializeObject(result));
isFirstCall = false;
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
else
{
try
{
var newtxn = Repository.AddtxnHisByResp(FailResps);
var result = new
{
labels = newtxn.Key,
datasets = newtxn.Value
};
await HubContext.Clients.All.SendAsync("populatetxns", JsonConvert.SerializeObject(result));
Thread.Sleep(10000);
}
catch (Exception)
{
throw;
}
}
}
});
}
}
and this is javaScript Code :
let txnresphisbycha = {};
$(document).ready(function () {
let isFirstCallSuccess = false;
var connection = new signalR
.HubConnectionBuilder()
.withUrl("/monitoringHub").build();
connection.start().then(() => console.log("hubconnected")).catch(() => console.log(error));//establish connection
connection.on("populatetxns", (result) => {
if (isFirstCallSuccess == false)
getChartData(JSON.parse(result));
else
addChartData(JSON.parse(result));
});
function getChartData(result) {
var dataSets = new Array();
for (i = 0; i < result.datasets.length; i++) {
var entity = {};
entity.name = result.datasets[i].label;
entity.data = result.datasets[i].data;
entity.color = result.datasets[i].color;
entity.type = 'area';
dataSets.push(entity);
}
txnresphisbycha = Highcharts.chart('txnhisbyrespcha', {
chart: {
zoomType: 'x',
alignTicks: false,
height: (10 / 22 * 100) + '%',// set ratio
},
title: {
text: 'Total Transaction Chart'
},
credits: {
text: ''
},
legend: {
enabled: true,
rtl: true,
y: 25,
margin: 0,
shadow: true,
verticalAlign: 'top',
itemStyle: {
cursor: "pointer",
}
},
tooltip: {
enabled: true,
rtl: true,
split: false,
shared: true,
xDateFormat: '%H:%M',
useHTML: true,
style: {
fontSize: '15px',
rtl: true,
},
distance: 30,
padding: 5,
headerFormat: '<span>{point.key}</span><br/>'
},
xAxis: {
zoomEnabled: true,
categories: result.labels,
type: 'datetime',
tickInterval: 1,
labels: {
type: 'datetime',
step: 1,
rotation: 55,
style: {
fontSize: '11px'
},
}
},
yAxis: {
title: {
text: "Quantity",
style: {
fontSize: '15px',
},
},
opposite: false,
endOnTick: true,
showLastLabel: true,
labels: {
style: {
fontSize: '15px',
},
align: 'right',
x: -7,
y: 5,
formatter: function () {
return this.value;
}
}
},
plotOptions: {
series: {
pointRange: 1 * 60 * 1000,
fillOpacity: 0.2,
marker: {
symbol: 'circle'
}
}
},
series: dataSets,
navigator: {
enabled: true
}
});
isFirstCallSuccess = true;
}
function addChartData(result) {
if (!isFirstCallSuccess) return;
debugger;
if (txnresphisbycha.series[0].data[txnresphisbycha.series[0].data.length - 1].category != result.labels[0]) {
txnresphisbycha.series[0].addPoint({
x: result.labels[0],
function() {
for (var i in result.datasets) {
y: result.datasets[i]
}
},
dataLables: { enabled: true }
},
true
,true)
txnresphisbycha.update();
}
}
})

How to contain category data in tooltip

I've seen tutorials and posts about getting data from the x axis into the tooltip but I am overriding it with categories and cannot figure out how to get the x axis to show up in the tooltip.
This is what im working with:
function showTooltip(x, y, contents) {
$('<div id="tooltip" class="flot-tooltip tooltip"><div class="tooltip-arrow"></div>' + contents + '</div>').css({
top: y - 43,
left: x - 15,
}).appendTo("body").fadeIn(200);
}
var data = [[1492854610, -1240],[1492939020, -1273],[1493025073, -1279],[1493117066, -1186],[1493198484, -1269],[1493289175, -1198],[1493370646, -1280],[1493458518, -1255],[1493543731, -1275],[1493630250, -1273],[1493716306, -1279],[1493803609, -1264],[1493889258, -1276],[1493975557, -1278],[1494064529, -1235],[1494155440, -1160],[1494237980, -1224],[1494321047, -1280],[1494407990, -1271],[1494494125, -1275],[1494581609, -1257],[1494668321, -1252],[1494753220, -1277],[1494847855, -1140],[1494925963, -1278],[1495012537, -1275],[1495099289, -1269],[1495188205, -1227],[1495273568, -1244],[1495358329, -1272]];
$.plot($("#placeholder"), [{
label: "Delay: ",
data: data,
color: "#3a8ce5"
}], {
xaxis: {
mode: "categories",
tickLength: 0,
ticks: [[0, "1:50 AM"],[1, "1:17 AM"],[2, "1:11 AM"],[3, "2:44 AM"],[4, "1:21 AM"],[5, "2:32 AM"],[6, "1:10 AM"],[7, "1:35 AM"],[8, "1:15 AM"],[9, "1:17 AM"],[10, "1:11 AM"],[11, "1:26 AM"],[12, "1:14 AM"],[13, "1:12 AM"],[14, "1:55 AM"],[15, "3:10 AM"],[16, "2:06 AM"],[17, "1:10 AM"],[18, "1:19 AM"],[19, "1:15 AM"],[20, "1:33 AM"],[21, "1:38 AM"],[22, "1:13 AM"],[23, "3:30 AM"],[24, "1:12 AM"],[25, "1:15 AM"],[26, "1:21 AM"],[27, "2:03 AM"],[28, "1:46 AM"],[29, "1:18 AM"]]
},
yaxis: {
min: -2000,
max: 1000,
},
series: {
lines: {
show: true,
fill: true
},
points: {
show: true,
}
},
grid: {
hoverable: true,
clickable: true,
markings: [
{ color: '#000', lineWidth: 1, yaxis: { from: 0, to: 0 } },
]
},
legend: {
show: false
}
});
$("#placeholder").bind("plothover", function(event, pos, item) {
if (item) {
if (previousPoint != item.dataIndex) {
previousPoint = item.dataIndex;
$("#tooltip").remove();
var y = item.datapoint[1].toFixed();
showTooltip(item.pageX, item.pageY,
item.series.label + " = " + y);
}
} else {
$("#tooltip").remove();
previousPoint = null;
}
});
I am trying to get the times part of the categories. The item array has 3 pieces of data, none of which are the times
jFiddle:
http://jsfiddle.net/zw14y8c3/2/
The item.datapoint[0] data has the index of the x-axis tick. With that you can get the actual tick label from the ticks array:
var x = $("#placeholder").data('plot').getAxes().xaxis.ticks[item.datapoint[0]].label;
See the updated fiddle for the full example.

flot chart hoverable markings

I made a few graphs with the possibility of putting a mark inside, but I don't understand how to make the mark hoverable with the y-axis value.
$.plot($("#flot-chart-#ControlID"), series_#ControlID, {
series: {
lines: {
lineWidth: 2,
fill: #((Model.Series.Count() == 1).ToString().ToLower()),
},
bars: {
barWidth: 0.6,
align: "center"
},
points: {
fill: #((Model.Series.Count() == 1).ToString().ToLower()),
}
},
xaxis: {
ticks: xlabels_#ControlID,
tickDecimals: 0
},
colors: #Html.Raw(Newtonsoft.Json.JsonConvert.SerializeObject(Model.Series.Select(o => o.Color).ToArray())),
grid: {
color: "#999999",
hoverable: true,
clickable: true,
borderWidth: 0,
#if (Model.LimitLine != null)
{
<text>
markings: [
{ color: '#000', lineWidth: 1, yaxis: { from: #Model.LimitLine, to: #Model.LimitLine }},
]
</text>
}
},
legend: {
show: true
},
tooltip: true,
tooltipOpts: {
content: function(label, xval, yval) {
var content = getLabel_#(ControlID)(xval) + ": " + yval;
return content;
},
}
});
How can i show a tooltip with the value?
Graph example:
You can't do that with the tooltips plugin, but it is possible when doing the tooltips yourself. Something like this:
$("#placeholder").bind("plothover", function (event, pos, item) {
if (item) { // hovering over a datapoint
var x = item.datapoint[0].toFixed(2),
y = item.datapoint[1].toFixed(2);
$("#tooltip").html(item.series.label + " of " + x + " = " + y)
.css({top: item.pageY+5, left: item.pageX+5}).fadeIn(200);
} else {
var hideTooltip = true;
// you need to save the Flot object for this (here as "plot")
$.each(plot.getOptions().grid.markings, function(idx, marking) {
if (Math.abs(pos.y - marking.yaxis.to) < 10) {
$("#tooltip").html("Limit: " + marking.yaxis.to)
.css({top: pos.pageY + 5, left: pos.pageX + 5}).fadeIn(200);
hideTooltip = false;
return false;
}
});
if (hideTooltip) {
$("#tooltip").hide();
}
}
});
Based on this example.

How to get total of highcharts multiple series

With the Highcharts value-in-legend plugin http://www.highcharts.com/plugin-registry/single/10/Value-In-Legend, I have been able to kind of implement a sort of multiple series total, but I do not understand how to get a total for a clicked y-axis point.
For example when I click, one day I will get the 3 separate series numbers, but I would like to get a total somehow as well, but I only know the y points on load and the visible y-points on redraw. I think the difficulty is getting the total of the 3 series points versus getting the individual point's value.
$(function() {
// Start the standard Highcharts setup
var seriesOptions = [],
yAxisOptions = [],
seriesCounter = 0,
names = ['MSFT', 'AAPL', 'GOOG'],
colors = Highcharts.getOptions().colors;
$.each(names, function(i, name) {
$.getJSON('http://www.highcharts.com/samples/data/jsonp.php?filename=' + name.toLowerCase() + '-c.json&callback=?', function(data) {
seriesOptions[i] = {
name: name,
data: data
};
// As we're loading the data asynchronously, we don't know what order it will arrive. So
// we keep a counter and create the chart when all the data is loaded.
seriesCounter++;
if(seriesCounter == names.length) {
createChart();
}
});
});
// create the chart when all data is loaded
function createChart() {
$('#container').highcharts('StockChart', {
chart: {
events: {
load: function(event) {
console.log('load');
var total = 0;
for(var i = 0, len = this.series[0].yData.length; i < len; i++) {
total += this.series[0].yData[i];
}
totalText_posts = this.renderer.text('Total: ' + total, this.plotLeft, this.plotTop - 35).attr({
zIndex: 5
}).add()
},
redraw: function(chart) {
console.log('redraw');
console.log(totalText_posts);
var total = 0;
for(var i = 0, len = this.series[0].yData.length; i < len; i++) {
if(this.series[0].points[i] && this.series[0].points[i].visible) total += this.series[0].yData[i];
}
totalText_posts.element.innerHTML = 'Total: ' + total;
}
}
},
rangeSelector: {
selected: 4
},
yAxis: {
labels: {
formatter: function() {
return(this.value > 0 ? '+' : '') + this.value + '%';
}
},
plotLines: [{
value: 0,
width: 2,
color: 'silver'
}]
},
legend: {
enabled: true,
floating: true,
align: 'left',
verticalAlign: 'top',
y: 35,
labelFormat: '<span style="color:{color}">{name}</span>: <b>{point.y:.2f} USD</b> ({point.change:.2f}%)<br/>',
borderWidth: 0
},
plotOptions: {
series: {
compare: 'percent',
cursor: 'pointer',
point: {
events: {
click: function () {
alert('Category: ' + this.category + ', value: ' + this.y);
}
}
}
}
},
series: seriesOptions
});
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="http://code.highcharts.com/stock/highstock.src.js"></script>
<script src="http://code.highcharts.com/stock/modules/exporting.js"></script>
<script src="https://rawgithub.com/highslide-software/value-in-legend/master/value-in-legend.js"></script>
<div id="container" style="height: 400px; min-width: 500px"></div>
I was able to find out a way to put the total result as a title in a multi series by reading the source code for the Highcharts value-in-legend plugin https://rawgithub.com/highslide-software/value-in-legend/master/value-in-legend.js.
$(function () {
var seriesOptions_likes = [],
seriesCounter_likes = 0,
names_likes = ['MSFT', 'AAPL', 'GOOG'],
totalText_likes = 0;
/**
* Create the chart when all data is loaded
* #returns {undefined}
*/
function createLikesChart() {
Highcharts.stockChart('container_likes', {
chart: {
},
rangeSelector: {
selected: 4
},
title: {
text: 'Total Results: '
},
yAxis: {
labels: {
formatter: function () {
return (this.value > 0 ? ' + ' : '') + this.value + '%';
}
},
plotLines: [{
value: 0,
width: 2,
color: 'silver'
}]
},
plotOptions: {
series: {
compare: 'percent',
showInNavigator: true
}
},
tooltip: {
pointFormat: '<span style="color:{series.color}">{series.name}</span>: <b>{point.y}</b> ({point.change}%)<br/>',
valueDecimals: 2,
split: true
},
series: seriesOptions_likes,
legend: {
enabled: true,
floating: true,
align: 'left',
verticalAlign: 'top',
y: 65,
borderWidth: 0
},
});
}
$.each(names_likes, function (i, name) {
$.getJSON('https://www.highcharts.com/samples/data/jsonp.php?filename=' + name.toLowerCase() + '-c.json&callback=?', function (data) {
seriesOptions_likes[i] = {
name: name,
data: data
};
// As we're loading the data asynchronously, we don't know what order it will arrive. So
// we keep a counter and create the chart when all the data is loaded.
seriesCounter_likes += 1;
if (seriesCounter_likes === names_likes.length) {
createLikesChart();
}
});
});
});
(function (H) {
H.Series.prototype.point = {}; // The active point
H.Chart.prototype.callbacks.push(function (chart) {
$(chart.container).bind('mousemove', function () {
var legendOptions = chart.legend.options,
hoverPoints = chart.hoverPoints,
total = 0;
if (!hoverPoints && chart.hoverPoint) {
hoverPoints = [chart.hoverPoint];
}
if (hoverPoints) {
var total = 0,
ctr = 0;
H.each(hoverPoints, function (point) {
point.series.point = point;
total += point.y;
});
H.each(chart.legend.allItems, function (item) {
item.legendItem.attr({
text: legendOptions.labelFormat ?
H.format(legendOptions.labelFormat, item) :
legendOptions.labelFormatter.call(item)
});
});
chart.legend.render();
chart.title.update({ text: 'Total Results: ' + total.toFixed(2) });
}
});
});
// Hide the tooltip but allow the crosshair
H.Tooltip.prototype.defaultFormatter = function () { return false; };
}(Highcharts));
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://code.highcharts.com/stock/highstock.js"></script>
<script src="https://code.highcharts.com/stock/modules/exporting.js"></script>
<div id="container_likes" style="height: 400px; min-width: 600px"></div>

FlotChart do not work zooming mode

I have following example: http://jsfiddle.net/ondra15/7mb8K/1/.
I want to have together two example (multiple axes and zooming). Example zooming do not work correct - if I indicate some data in chart for zooming - do not work. Nothing happens.
Original Zooming (correct) solution works here http://www.flotcharts.org/flot/examples/zooming/index.html
Can any some idea for my code? Thanks
code
Hi I managed to get it working using code from an example I found here. I will update your jsfiddle too:
<script type="text/javascript">
var datasets = { ... };
data = null;
function plotByChoice(doAll) {
data = [];
if (doAll != null) {
$.each(datasets, function (key, val) {
data.push(val);
});
}
else {
$('#legend .legendCB').each(
function () {
if (this.checked) {
data.push(datasets[this.id]);
}
else {
data.push({ label: this.id, data: [] })
}
}
);
}
$.plot($("#placeholder"), data, {
yaxes: [{ min: 0 }, { position: "right" }],
xaxis: { tickDecimals: 0 },
legend: {
container: legend,
labelFormatter: function (label, series) {
var cb = '<input class="legendCB" type="checkbox" ';
if (series.data.length > 0) {
cb += 'checked="true" ';
}
cb += 'id="' + label + '" /> ';
cb += label;
return cb;
}
}, selection: { mode: "x" }
});
$('#legend').find("input").click(function () { setTimeout(plotByChoice, 100); });
}
plotByChoice(true);
// Create the overview plot
var overview = $.plot("#overview", data, {
legend: {
show: false
},
series: {
lines: {
show: true,
lineWidth: 1
},
shadowSize: 0
},
xaxis: {
ticks: 4
},
yaxes: [{ min: 0 }, { position: "right" }],
grid: {
color: "#999"
},
selection: {
mode: "x"
}
});
$("#placeholder").bind("plotselected", function (event, ranges) {
var options = {
series: {
lines: { show: true },
points: { show: true }
},
legend: { noColumns: 2 },
xaxis: { tickDecimals: 0 },
yaxis: { min: 0 },
selection: { mode: "x" }
};
var placeholder = $("#placeholder");
placeholder.bind("plotselected", function (event, ranges) {
$("#selection").text(ranges.xaxis.from.toFixed(1) + " to " + ranges.xaxis.to.toFixed(1));
plot = $.plot(placeholder, data,
$.extend(true, {}, options, {
xaxis: { min: ranges.xaxis.from, max: ranges.xaxis.to }
}));
});
// don't fire event on the overview to prevent eternal loop
overview.setSelection(ranges, true);
});
$("#overview").bind("plotselected", function (event, ranges) {
plot.setSelection(ranges);
});
</script>

Categories