flot chart hoverable markings - javascript

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.

Related

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.

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>

How to display time on x axis in flot line graph?

I am trying to show time intervals between Min and Max of a certain time range. Eg: 2015-04-30 10:20:00 and 2015-04-30 10:30:00 on x axis
I will be fetching all the values from database(which has datetime stored in 2015-04-30 10:27:58 format and passing it through webmethod.
If I create var data1 as
var data1 = [
['2015-04-30 10:27:58', 1690.25], ...
];
It won't work. So I am guessing I would need to convert '2015-04-30 10:27:58'milisecond ticks when creating var data1.
But I do not want to display time in a proper time format such as 10:27:58 instead of 1430369878000 on xaxis. (I want exclude date part).
How can I achieve this?
//RED
var data1 = [
[1430369878000, 1690.25], [1430369879000, 1696.3], [1430369880000, 1659.65]
];
//BLUE
var data2 = [
[1430369878000, 1682.1], [1430369879000, 1680.65], [1430369880000, 1685.1]
];
var dataset = [
{
label: "Sell out",
data: data1,
color: "#FF0000",
points: { fillColor: "#FF0000", show: true },
lines: { show: true }
},
{
label: "Buy in",
data: data2,
color: "#0062E3",
points: { fillColor: "#0062E3", show: true },
lines: { show: true }
}
];
var options = {
series: {
shadowSize: 5
},
xaxes: { mode: "time",
min: parseInt((new Date("2015-04-30 10:27:58")).getTime()),
max: parseInt((new Date("2015-04-30 10:43:39")).getTime()),
timeformat: "%H/%M/%S"
},
yaxis: {
color: "black",
tickDecimals: 2,
axisLabel: "Gold Price in USD/oz",
axisLabelUseCanvas: true,
axisLabelFontSizePixels: 12,
axisLabelFontFamily: 'Verdana, Arial',
axisLabelPadding: 6
},
legend: {
noColumns: 0,
labelFormatter: function (label, series) {
return "<font color=\"white\">" + label + "</font>";
},
backgroundColor: "#000",
backgroundOpacity: 0.9,
labelBoxBorderColor: "#000000",
position: "nw"
},
grid: {
hoverable: true,
borderWidth: 3,
mouseActiveRadius: 50,
backgroundColor: { colors: ["#ffffff", "#EDF5FF"] },
axisMargin: 20
}
};
$(document).ready(function () {
setInterval(function () {
$.plot($("#flot-placeholder"), dataset, options);
$("#flot-placeholder").UseTooltip();
}, 1000)
});
var previousPoint = null, previousLabel = null;
$.fn.UseTooltip = function () {
$(this).bind("plothover", function (event, pos, item) {
if (item) {
if ((previousLabel != item.series.label) || (previousPoint != item.dataIndex)) {
previousPoint = item.dataIndex;
previousLabel = item.series.label;
$("#tooltip").remove();
var x = item.datapoint[0];
var y = item.datapoint[1];
var date = new Date(x);
var color = item.series.color;
showTooltip(item.pageX, item.pageY, color,
"<strong>" + item.series.label + "</strong><br>" +
x +
" : <strong>" + y + "</strong> (USD/oz)");
}
} else {
$("#tooltip").remove();
previousPoint = null;
}
});
};
function showTooltip(x, y, color, contents) {
$('<div id="tooltip">' + contents + '</div>').css({
position: 'absolute',
display: 'none',
top: y,
left: x,
border: '2px solid ' + color,
padding: '3px',
'font-size': '9px',
'border-radius': '5px',
'background-color': '#fff',
'font-family': 'Verdana, Arial, Helvetica, Tahoma, sans-serif',
opacity: 0.9
}).appendTo("body").fadeIn(200);
}
The options for the x-axis are under the name xaxes not xaxis therefore they are not used. (Also your min and max values are outside of the data range.)
// not xaxes:
xaxis: {
mode: "time",
//min: parseInt((new Date("2015-04-30 10:27:58")).getTime()),
//max: parseInt((new Date("2015-04-30 10:43:39")).getTime()),
timeformat: "%H/%M/%S"
},
See this fiddle for a working example.
PS: You use the $.plot() function with setInterval which is okay but you should only call UseTooltip() once.

Highcharts > Positioning data labels between columns

I'm using Highcharts to show the % difference between the columns.
The labels above the columns represent that bars total. The % between the columns show a % change between each bar. I have positioned the x-axis OK, but the y-axis values are difficult. My aim is to:
Align % values to 50% on the y-Axis (half the height of the chart) and in between the columns so it shows a straight line of values. Currently these numbers are relative to the height of the bar column values.
http://jsfiddle.net/tellmehow/1sr9ab6d/15/
See an image here:
My code as follows.
$(function(){
var data = [1000,800,700,300,250,234,10,1,0,0];
function percent(data) {
var result = [];
for (var i=0; i<data.length -1; i++) {
if(data[i] === 0) {
result[data[i]] = 100;
} else {
result[data[i]] = 100 - (data[i] - data[i +1]) * 100 / data[i];
}
}
return result;
} //percent
$('#highcharts-panel').highcharts({
chart: {
type: 'column',
events: {
redraw: function(event) {
refreshArrowPos();
}
}
},
xAxis: {
categories: [{
text: "various...",
}]
},
yAxis: {
min: 0,
title: {
text: 'whatever'
}
},
tooltip: {
enabled: false,
followTouchMove: false
},
plotOptions: {
column: {
pointPadding: 0.2,
borderWidth: 0,
dataLabels: {
enabled: true
},
}, //col
series: {
marker: {
enabled: false
},
shadow:false,
borderWidth:0,
dataLabels:{
useHTML: true,
enabled:true,
formatter:function() {
var percents = percent(data);
return (Highcharts.numberFormat(this.y,0) + "<div class='dataPercent'>" + (this.y == data[data.length - 1] ? '' : Highcharts.numberFormat(percents[this.y]) + '%' + "<div class='arrow'></div>") + "</div>");
},
style: {
fontSize: "14px",
}
}
}
},
legend: {
enabled: false
},
series: [{
name: 'Total users',
data: data,
}],
}
);
function refreshArrowPos() {
$('.dataPercent').each (function(){
var colWidth = ($('#highcharts-panel').width() / data.length);
var colHeight = ($('#highcharts-panel').height() / data.length);
$(this).css({ left: ($(this).position().left + (colWidth / 2) - ($(this).width() / 4 )) + 'px',
top: ($(this).position().top + (colHeight / 2)) + 'px'
}); //end css
}); //dataPErcent fun
} //refreshArrowPos
refreshArrowPos();
});//highCharts Func
<div id="highcharts-pannel" class="funnelChart"></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