jqPlot displaying custom tooltip with cursor - javascript

I'm using the Cursor plugin to display a vertical line on a jqplot chart. The tooltip for the Cursor plugin is showing the X and Y values.
I want to add a piece of meta data to the plot points.
[x,y,1337] where 1337 is the meta deta.
I want to modify the Cursor plugin tooltip to show this metadeta as well as the data it already displays.
Use case: I have multiple series that have been scaled to 0-100 across all series for trending. I need to display the unscaled value.
Update:
i've got it working by hacking up jqplot.cursor.js, is there a better way?
Line 468: function updateToolTip(gridpos, datapos, plot){
// ...
s += $.jqplot.sprintf(c.tooltipFormatString, label, sx, sy, data[2]);

This is how I override the tooltipContentEditor jqplot function, it works great.
highlighter: {
show: true,
showMarker:true,
showTooltip:true,
sizeAdjust: 10,
tooltipLocation: 'se',
tooltipAxes: 'xy',
yvalues: 1,
formatString:'<table class="jqplot-highlighter"><tr><td>date:</td><td>%s</td></tr><tr><td>PiecesPerHour:</td><td align="right">%s</td></tr></table>',
useAxesFormatters: true,
tooltipContentEditor: function(str, seriesIndex, pointIndex, plot){
var data = plot.series[seriesIndex].data[pointIndex];
var label = plot.legend.labels[seriesIndex].indexOf('Target')
var format = [];
//A little formatting to the data before I join it to the Html string
if (that.model.get('groupBy')==='month')
format[0] = new Date(data[0] + 1000*60*60*24).format('mmmm yyyy');
else
format[0] = new Date(data[0] ).format('mmmm dd, yyyy');
format[1] = new Number(data[1]).toFixed(1)
//join the data to the Html string:
str = $.jqplot.sprintf.apply($.jqplot.sprintf, [str].concat(format));
return str;
}
}
Basically you get the Series and Point data and join it to an Html string with sprintf and then return the string.

Related

HighChart : plot line click event for multiple chart

I am using highchart for some drilldown functions.
I having a function to let the user click on an area plot and add a line. But then i found out my function has a bug in it. There's should be only one red line between those charts, but when the user click on the other chart the existing red line on the first chart is not removing.
The belowing is the function my charts sharing.
var myPlotLineId = "myPlotLine";
addPlotLine = function(evt) {
var point = evt.point;
var xValue = point.x;
var xAxis = point.series.xAxis;
Highcharts.each(xAxis.plotLinesAndBands, function(p) {
if (p.id === myPlotLineId) {
p.destroy();
}
});
xAxis.addPlotLine({
value: xValue,
width: 1,
color: 'red',
id: myPlotLineId
});
};
It should only allow one red line since i am using ID.
The below is the current situation.
Since i am using id for the plotline is shouldn't allow two line, please see my example:
http://jsfiddle.net/Xm4vW/74/
I want only ONE RED LINE in total out of many charts
UPDATE 1 :
I have tried redraw() in the new demo :
http://jsfiddle.net/Xm4vW/80/
but it doesn't help.
Please do let me know if the question is not clear enough.
There is nothing like 'Highcharts.each(xAxis.plotLinesAndBands, function(p) '. Iterate charts by loop and use 'removePlotLine(PlotLineID)' instead of 'destroy()':
for(i=0;i<Highcharts.charts.length; i++){
var chart=Highcharts.charts[i];
chart.xAxis[0].removePlotLine('myPlotLineId');
}
And set id in parenthesis:
id: 'myPlotLineId'
here is jsfiddle http://jsfiddle.net/asadsarwar89/bh4kz9rw/

Chart.js and right side free space

I wanted to ask, if there is a way to push chart to right side, so there will not be any free space. I attached simple image, red line show, that this space should be filled also by chart.
Also is possible to create vertical lines as dots ? I can't find answers to my questions, on official doc.
An this is my javsacript code:
var lineChartData = {
labels : ["January","February","March","April"],
datasets : [
{
label: "Dataset",
pointHighlightStroke : "rgba(220,220,220,1)",
data : [0,3,4,11]
}
]
};
window.onload = function(){
var ctx = document.getElementById("canvas").getContext("2d");
window.myLine = new Chart(ctx).Line(lineChartData, {
responsive: true,
scaleOverride: true,
scaleSteps: Math.ceil((max-start)/step),
scaleStepWidth: step,
pointDot : false,
});
}
The space is there because the last x axis label (April). Chart.js leaves enough space so that the label does not get clipped off. This also ensures that the tooltip for the last point shows without clipping off.
You could set the last (or all) labels to an empty string to get rid of the space. However, you won't see any labels in the tooltips. If you want to see the labels in the tooltips you need to extend the chart to remove the x axis labels like so
Chart.types.Line.extend({
name: "LineAlt",
initialize: function (data) {
var labels = data.labels;
data.labels = data.labels.map(function () { return '' });
Chart.types.Line.prototype.initialize.apply(this, arguments);
this.datasets[0].points.forEach(function (point, i) {
point.label = labels[i]
})
}
});
Note that you need to use LineAlt instead of Line.
Fiddle - http://jsfiddle.net/0u2c7tez/
However this will still clip off the tooltip for the last point. If you are going to enable tooltips and don't want them to be clipped off, then you need to use custom tooltips so that the tooltip is rendered in an external element (instead of the canvas) and not clipped off (see https://github.com/nnnick/Chart.js/blob/master/samples/line-customTooltips.html)

Highcharts - how can I center labels on a datetime x-axis?

I was having a hard time trying to figure out how to center labels on a datetime x-axis in Highcharts without using categories and tickPlacement (since tickPlacement only works on categories).
My axis was dynamically created so I could not simply set an x-offset or padding, as this would cause axes of different intervals to look strange.
After messing around with the config options I think I may have found a solution using the x-axis formatter and some css / jquery noodling in the Highcharts callback. See my answer below.
The trick is to use the x-axis labels object like this:
xAxis: {
type: 'datetime',
labels: {
useHTML: true,
align: 'center',
formatter: function () {
//using a specific class for the labels helps to ensure no other labels are moved
return '<span class="timeline_label">' + Highcharts.dateFormat(this.dateTimeLabelFormat, this.value) + '</span>';
}
}
You can see that the formatter will keep whatever dateTimeLabelFormat has been set by the user or default.
Then have a callback that does something like this:
function (chart) {
var $container = $(chart.container);
var $labels = $container.find('.highcharts-axis-labels .timeline_label');
var $thisLabel, $nextLabel, thisXPos, nextXPos, delta, newXPos;
$labels.each(function () {
$thisLabel = $(this).parent('span');
thisXPos = parseInt($thisLabel.css('left'));
$nextLabel = $thisLabel.next();
nextXPos = $nextLabel.length ? parseInt($nextLabel.css('left')) : chart.axes[0].left + chart.axes[0].width;
delta = (nextXPos - thisXPos) / 2.0;
newXPos = thisXPos + delta;
if ($nextLabel.length || $(this).width() + newXPos < nextXPos) {
$thisLabel.css('left', newXPos + 'px');
} else {
$thisLabel.remove();
}
});
});
In short, this will go through each label and determine how much it should be moved over (using css) by calculating the distance between itself and the next label. When it reaches the the last label, it either moves it over using the end of the axis for the calculation or removes it if it won't fit. This last part is just the decision I decided to make, you can probably choose to do something else like word wrap, etc.
You can see the jsfiddle here
Hope this helps some people. Also, if there are any improvements it would be great to see them here.
Based on the existing answer, there is a much simpler solution that also works when resizing the browser window (or otherwise forcing the chart to redraw), even when the tick count changes: http://jsfiddle.net/McNetic/eyyom2qg/3/
It works by attaching the same event handler to both the load and the redraw events:
$('#container').highcharts({
chart: {
events: {
load: fixLabels,
redraw: fixLabels
}
},
[...]
The handler itself looks like this:
var fixLabels = function() {
var labels = $('div.highcharts-xaxis-labels span', this.container).sort(function(a, b) {
return +parseInt($(a).css('left')) - +parseInt($(b).css('left'));
});
labels.css('margin-left',
(parseInt($(labels.get(1)).css('left')) - parseInt($(labels.get(0)).css('left'))) / 2
);
$(labels.get(this.xAxis[0].tickPositions.length - 1)).remove();
};
As you see, the extra wrapping of labels is unnecessary (at least if you do not have more than one xAxis). Basically, it works like this:
Get all existing labels (when redrawn, this includes newly added ones). 2. Sort by css property 'left' (they are not sorted this way after some redrawing)
Calculate offset between the first two labels (the offset is the same for all labels)
Set half of the offset as margin-left of all labels, effectively shifting them half the offset to the right.
Remove the rightmost label (moved outside of chart, by sometimes partly visible).

Pie chart using flot

I am using Jquery Flot to create a pie chart based on three different values, pause, nopause and sleeping. Initially it draws th pie chart correctly but after some redraw it gives me the following error.
Could not draw pie with labels contained inside canvas
My code is
Lecturer.socket.onmessage = function (message) {
var str = message.data;
var msg = str.split(":");
if(msg[0] == 'pause'){
var pause = parseInt(msg[1]);
var noPause = parseInt(msg[2]);
var sleeping = parseInt(msg[3]);
var data = [
{label: "Pause", data:pause},
{label: "No Pause", data:noPause},
{label: "Sleeping", data:sleeping}
];
var options = {
series: {
pie: {show: true}
},
legend: {
show: false
}
};
$.plot($("#pie-placeholder"), data, options);
}
};
HTML is
<div id="live-placeholder" class="flot"></div>
All the require js libraries are included. What I m doing wrong? Any Help ?
Thanks
You've got two problems:
1.) your placeholder div id doesn't match the $.plot call. live-placeholder != pie-placeholder.
2.) You don't need to calculate the percents yourself. Flot will do it internally.
See a working fiddle here.

jqplot tooltip on bar chart

I'm using the jquery plugin jqplot for plotting some bar charts.
on hover, I'd like to display the tick for the bar and its value on a tooltip. I've tried
highlighter: { show: true,
showTooltip: true, // show a tooltip with data point values.
tooltipLocation: 'nw', // location of tooltip: n, ne, e, se, s, sw, w, nw.
tooltipAxes: 'both', // which axis values to display in the tooltip, x, y or both.
lineWidthAdjust: 2.5 // pixels to add to the size line stroking the data point marker
}
but it doesn't work. the bar visually gets lighter, and there's a small dot on the top (which would ideally go away--probably from line chart renderer stuff), but there is no tooltip anywhere. Anyone know how I can do this? I'll have lots of bars so the x-axis will be cluttered and kind of a mess if I show them down there only.
I go through jqplot.highlighter.js and find an undocumented property: tooltipContentEditor.
I use it to customize the tooltip to display x-axis label.
Use something like this:
highlighter:{
show:true,
tooltipContentEditor:tooltipContentEditor
},
function tooltipContentEditor(str, seriesIndex, pointIndex, plot) {
// display series_label, x-axis_tick, y-axis value
return plot.series[seriesIndex]["label"] + ", " + plot.data[seriesIndex][pointIndex];
}
nevermind, I did a roundabout way to create my own tooltip via jquery.
I left my highlighter settings as they were in my question (though you probably don't need the tooltip stuff).
In my js file after the bar chart is set up (after $.jqplot('chart', ...) I set up an on mouse hover binding, as some of the examples showed. I modified it like this:
$('#mychartdiv').bind('jqplotDataHighlight',
function (ev, seriesIndex, pointIndex, data ) {
var mouseX = ev.pageX; //these are going to be how jquery knows where to put the div that will be our tooltip
var mouseY = ev.pageY;
$('#chartpseudotooltip').html(ticks_array[pointIndex] + ', ' + data[1]);
var cssObj = {
'position' : 'absolute',
'font-weight' : 'bold',
'left' : mouseX + 'px', //usually needs more offset here
'top' : mouseY + 'px'
};
$('#chartpseudotooltip').css(cssObj);
}
);
$('#chartv').bind('jqplotDataUnhighlight',
function (ev) {
$('#chartpseudotooltip').html('');
}
);
explanation:
ticks_array is previously defined, containing the x axis tick strings. jqplot's data has the current data under your mouse as an [x-category-#, y-value] type array. pointIndex has the current highlighted bar #. Basically we will use this to get the tick string.
Then I styled the tooltip so that it appears close to where the mouse cursor is. You will probably need to subtract from mouseX and mouseY a bit if this div is in other positioned containers.
you can then style #chartpseudotooltip in your css. If you want the default styles you can just add it to .jqplot-highlighter-tooltip in the the jqplot.css.
hope this is helpful to others!
I am using the version of the highlighter plugin on the following link:
https://github.com/tryolabs/jqplot-highlighter
The parameters I am using:
highlighter: {
show:true,
tooltipLocation: 'n',
tooltipAxes: 'pieref', // exclusive to this version
tooltipAxisX: 20, // exclusive to this version
tooltipAxisY: 20, // exclusive to this version
useAxesFormatters: false,
formatString:'%s, %P',
}
The new parameters ensure a fixed location where the tooltip will appear. I prefer to place it on the upper left corner to avoid problems with resizing the container div.

Categories

Resources