I am using a dygraph to monitor a CSV file and use the dynamic update function. When I hover over the graph to show the values of the curves in the legend, they disappear as soon as the graph is updated, which is a bit annoying.
<html>
<head>
<script type="text/javascript" src="/static/dygraph-combined.js"></script></head>
<body>
<div id="psu"></div>
<script type="text/javascript">
g = new Dygraph(document.getElementById("psu"), "/data/psu",
{
legend: 'always',
hideOverlayOnMouseOut: false,
ylabel: 'current (A)',
height: 480,
width: 640,
sigFigs: 2,
title: 'power interface monitor',
xValueFormatter: Dygraph.dateString_,
xAxisLabelFormatter: Dygraph.dateString_,
xTicker: Dygraph.dateTicker
} );
window.intervalId = setInterval(function(){g.updateOptions( { 'file': "/data/psu" } ); }, 1000);
</script>
</html>
So the graph is all displaying correctly and the data is updated, only the legend values disappear after the graph is refreshed with g.updateOptions(). I was thinking maybe I can re-trigger some kind of "mouseover" event after g.updateOptions() so the values come back, but there might be a cleaner way of doing it.
Thanks.
I found a solution to my problem, but I am not sure how well it is implemented. I share it here so others might find it:
$(document).ready(function() {
var data = [];
var t = new Date();
for (var i = 10; i >= 0; i--) {
var x = new Date(t.getTime() - i * 1000);
data.push([x, Math.random()]);
}
var last_mousemove_evt = null;
var on_graph = false;
var g = new Dygraph(document.getElementById("div_g"), data, {
legend: 'always',
drawPoints: true,
showRoller: true,
valueRange: [0.0, 1.2],
labels: ['Time', 'Random'],
highlightCallback: function(e, x, pts, row) {
last_mousemove_evt = e;
on_graph = true
},
unhighlightCallback: function(e) {
on_graph = false;
}
});
// It sucks that these things aren't objects, and we need to store state in window.
window.intervalId = setInterval(function() {
var x = new Date(); // current time
var y = Math.random();
data.push([x, y]);
g.updateOptions({
'file': data
});
if (on_graph) {
g.mouseMove_(last_mousemove_evt);
}
}, 1000);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/dygraph/1.1.1/dygraph-combined.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js"></script>
<div id="div_g" style="width:600px; height:300px;"></div>
So I end up using the highlightCallback and unhighlightCallback options so I can figure out the mouse position and after a dynamic update call then the dygraph.mouseMove_() function to redraw the legend values. Seems to work.
Please let me know if there is a nicer solution around. Might be good to include this functionality in the dygraph.updateOptions() by default, as it seems weird that the legend values disappear after an update.
Related
I want to hide labels on x-axis as i have a solution to set
$scope.labels = ['', '', '', '', '', '', ''];
but in that case labels are also getting hidden on tooltip. What i want is to show labels on bars hover but i don't want to show those labels on x-axis. As it also disturbs my UX as well because charts width is too low.
I did spend too much time on this but couldn't find a solution to get rid of x-axis labels. Please help me here....
I think that's something you can do it with options setting in the latest versions of chartjs:
options: {
scales: {
xAxes: [
{
ticks: {
display: false
}
}
];
}
}
You can extend the chart to do this, like so
Chart.types.Bar.extend({
name: "BarAlt",
initialize: function(data){
Chart.types.Bar.prototype.initialize.apply(this, arguments);
var xLabels = this.scale.xLabels;
for (var i = 0; i < xLabels.length; i++)
xLabels[i] = '';
}
});
and call it like so
var myBarChart = new Chart(ctx).BarAlt(data);
Fiddle - http://jsfiddle.net/kq3utvnu/
Thanks #Samuele for pointing this out! For really long labels, you'll need to set the labels to something shorter and then set it back to the original ones (in the chart elements) so that no space is taken up below the x axis for the labels.
Chart.types.Bar.extend({
name: "BarAlt",
initialize: function(data){
var originalLabels = data.labels;
data.labels = data.labels.map(function() { return '' });
Chart.types.Bar.prototype.initialize.apply(this, arguments);
this.datasets[0].bars.forEach(function(bar, i) {
bar.label = originalLabels[i];
});
var xLabels = this.scale.xLabels;
for (var i = 0; i < xLabels.length; i++)
xLabels[i] = '';
}
});
Fiddle - http://jsfiddle.net/nkbevuoe/
I was able to hide labels on the x-axis, while keeping the title in the tooltip by doing the following:
In chart data: labels: [""]
In chart options, add object.label = "ToolTipTitle"; before the line specifying the values that should be returned
Hi here I set the data to the bar chart:
setDatosBarra: function(data){ //
var self = this;
var horaEstim = 0;
var horaReal = 0;
var horaTotal = 0;
if(data[0].horas_estim != '-'){
horaEstim = data[0].horas_estim;
}
if(data[0].horas_real != '-'){
horaReal = data[0].horas_real;
}
if(data[0].total_horas != '-'){
horaTotal = data[0].total_horas;
}
var datosBarra =[{data: [[0,horaEstim]], color: "#691717"}, {data: [[1,horaReal]], color: "#173D69"},{data: [[2,horaTotal]], color: "#176469"}];
self.flotLinea(datosBarra);
},
When all is ready I send the data to self.flotBar;
This is the flotBar function:
flotBar: function(datos){
var self = this;
if(datos == 0){
var data = [["SIN REGISTROS",0]];
}else{
var data = datos;
}
function getTooltip(label, x, y) {
return "<strong style='font-size:18px;'> " + y + " </strong> horas";
}
var plot = $.plot("#placeholder",data, {
series: {
bars: {
show: true,
barWidth: 0.3,
align: "center",
lineWidth: 0,
fill:.75
}
},
xaxis: {
ticks: [[0,"Horas estimadas"],[1,"Horas reales"],[2,"Total horas"]],
mode: "categories",
tickLength: 0
},
grid: {
hoverable: true,
clickable: true
},
tooltip: true,
tooltipOpts : {
content : getTooltip,
defaultTheme : false
},
});
},
Ok , and this is my problem, example:
I select a option in an dropDown:
And the bar chart looks like this:
If I select other option in the dropDown:
The bar chart looks like this:
And if I select again the first option "Correcion de errores", the bar chart looks like this:
So.. always the first time that I show the bar chart looks like in the first image , with the numbers in the line, but If I select other option looks good.
I need see good the bar chart always and no just when I select other option.
I'm using flot javascript library.
How can I fix this? sorry by my english
The main issue with the question as stated is that we do not have all the code. In essence, you should either provide all the code, or shrink down the problem to something that shows the issue and then, well, provide all the code. As far as I can guess, you have some other code somewhere else that is drawing the initial chart. The second and subsequent times? Drawn properly. To support my assertion, notice that in your initial image the captions for the x-axis tick markers (ditto the bars themselves) are right aligned not centered.
For fun, I wrote a quick jsFiddle that showed how to switch datasets using a button (much as you want to do with the drop-down) and redraw the chart:
drawChart = function(index) {
var chartData = getDataForChart(rawData[index]);
if (chart) {
chart.setData(chartData);
chart.draw();
}
else {
chart = $.plot("#barchart", chartData, chartOptions);
}
},
switchDataset = function() {
datasetIndex = (datasetIndex + 1) % datasetCount;
drawChart(datasetIndex);
};
$("#switchButton").on("click", switchDataset);
Because I decided to load new data into the chart rather than redraw it all from scratch (to be honest I saw no real difference either way), it meant that I had to pre-calculate the maximum value for the y-axis:
calcValueMax = function() {
var max = 0;
rawData.forEach(function(values) {
values.forEach(function(value) {
if (value > max) {
max = value;
}
});
});
return max;
},
// other code
chartOptions.yaxis.max = calcValueMax();
Hope that helps.
Though I have successfully colored the bars of google chart individually but not able to keep them when we hover mouse over it. It is getting reset back to blue(which is default).
Here is the jsfiddle of what I have done jsfiddle.
I tried to control the hover behaviour with multiple ways like below.
This I am keeping outside (document.ready) but inside script tag.
1)
$('#chart_div').hover(
function() {
$('#chart_client').hide(); // chart_client is another google chart div.
}, function() { // just for testing I was doing hide/show of that.
$('#chart_client').show();
}
);
2)
$("#chart_div").on({
mouseenter: function () {
$('#chart_client').hide();
},
mouseleave:function () {
$('#chart_client').show();
}
},'rect');
3)
google.visualization.events.addListener('#chart_div', 'ready', function () {
$('#chart_div rect').mouseover(function (e) {
alert('hello');
});
});
I must be doing something wrong, could you please tell me what and where.
I solved it using below code. Earlier I was trying to create charts using dynamically adding rows into chart(please visit my jsfiddle) but with this below approach I am first preparing data(converting dynamic to static) and adding that static data in to chart's 'arrayToDataTable' method.
google.load("visualization", "1", {packages:["corechart"]});
google.setOnLoadCallback(drawUserKeywordChart);
function drawUserKeywordChart() {
var val = 'Tax:47;Finance:95;Awards:126;Bank:137;Debt:145;';
var length = val.length;
var array = [];
//preparing data
while(length>0){
var sepAt = val.indexOf(";");
var value = parseInt(val.substring(val.indexOf(":")+1, sepAt));
array.push(val.substring(0, val.indexOf(":")));
array.push(value);
val = val.substring(val.indexOf(";")+1, length);
length = val.length;
}
var data = google.visualization.arrayToDataTable([
['Keyword', 'Occurences', { role: 'style' }],
[array[0], array[1], '#8AA3B3'],
[array[2], array[3], '#A9B089'],
[array[4], array[5], '#848C49'],
[array[6], array[7], '#44464A'],
[array[8], array[9], '#704610'],
]);
var options = {
title: 'Keyword Matches',
width: 660,
height: 450,
titleTextStyle:{bold:true,fontSize:20},
legend:{position:'none'}
};
var chart = new google.visualization.ColumnChart(document.getElementById('chart_keyword1'));
chart.draw(data, options);
}
Please advice if you find anything wrong here or you have better approach than this.
<html>
<head>
<script type="text/javascript"
src="dygraph-combined.js"></script>
</head>
<body>
<div id="graphdiv"></div>
<script type="text/javascript">
g = new Dygraph(
// containing div
document.getElementById("graphdiv"),
// CSV or path to a CSV file.
"Date,Duration,Error\n" +
"2008-05-07,75,23\n" +
"2008-05-08,70,45\n" +
"2008-05-09,70,0\n" +
"2008-05-10,70,23\n" +
"2008-05-11,70,11\n" +
"2008-05-12,70,\n" +
"2008-05-13,80,33\n",
{
// options go here. See http://dygraphs.com/options.html
legend: 'always',
animatedZooms: true,
title: 'dygraphs chart template',
includeZero: false
}
);
</script>
</body>
</html>
Is it possible to for the graph to ignore the zero or null values so it connects directly from 45 to 23 or 11 to 33. in excel we the option does this option exists? incluedZero does not seem to have any affect.
The really simple answer is to remove the comma where the value is unneeded or not wanted.
So for example
"2008-05-09,70,0\n"+
//Should be "2008-05-09,70\n"+
and
"2008-05-12,70,\n"+
//Should be "2008-05-12,70\n"+
However, if you really cannot modify the data that is being passed to DyGraphs, then you have two options
Create the graph, pull out the data, and then remove the column value where it equals 0 or null using array.pop(), then reload the modified data back into Dygraphs using updateOptions(). You can use the method I describe in my answer here as a starting point
OR
Create a custom plotter (as below) that just draws a line to the next non-zero/null value. The above two are better solutions because Dygraphs will still think that there are zero values at certain points in time (because it is afterall in the data you gave it).
//Define the custom plotter
var custom_plotter = function(e) {
var context = e.drawingContext;
var points = e.points;
var num_points = points.length;
context.beginPath(); //Start
//Move "paint brush" to the start location
context.moveTo(points[0].canvasx, points[0].canvasy);
var p; //var to store current point
for(var i = 1; i < num_points; i++) {
p = points[i];
if(p.yval != 0 && p.yval != null) {
//Map out a line if the current value is desirable
context.lineTo(p.canvasx, p.canvasy);
}
}
context.stroke(); //Actually draw the lines mapped out in the loop above
context.closePath(); //Close
}
g = new Dygraph(
// containing div
document.getElementById("graphdiv"),
// CSV or path to a CSV file.
"Date,Duration,Error\n" +
"2008-05-07,75,23\n" +
"2008-05-08,70,45\n" +
"2008-05-09,70,0\n" +
"2008-05-10,70,23\n" +
"2008-05-11,70,11\n" +
"2008-05-12,70,\n" +
"2008-05-13,80,33\n",
{
// options go here. See http://dygraphs.com/options.html
legend: 'always',
animatedZooms: true,
title: 'dygraphs chart template',
plotter: custom_plotter, //Pass Dygraphs the custom plotter defined above
}
);
Currently having a problem trying to get YUI Tooltips to display on top of a YUI Panel after it is shown that were previously created. The problem is is that the Panel cannot be registered to the overlay manager because it would require a TON of code to be changed and tested extending a hard deadline. The only way to get this to work is to setup the Tooltips after the Panel is shown. Problem there is the amount of code changes that would have to be done to attach another function call. My problem is that I was hoping that I could use the event handling to use "showEvent" but I cannot seem to get it to work (I apologize for word count):
var panel_obj = new YAHOO.widget.Panel('someID', {
width: "700px",
height: "500px",
close: true,
draggable: false,
modal: true,
constraintoviewport: true,
visible: false,
fixedcenter: true
});
panel_obj.render();
var tooltip_name = 'newTooltip1';
var element_id = 'htmlElementIDToBecomeTooltip';
function createTooltip() {
window[tooltip_name] = new YAHOO.widget.Tooltip(tooltip_name, {
context: element_id,
xyoffset: [15, -15],
zIndex: 999
});
}
function successfulScenario() {
panel_obj.show();
createTooltip();
}
function failedScenario1() {
YAHOO.util.Event.addListener(
'someID',
"showEvent",
createTooltip
);
}
function failedScenario2() {
createTooltip();
panel_obj.show();
}
The only way I have seem to get it working is by running something like successfulScenario(). I'm coming from a jQuery background so I'm still learning YUI. I would love to be able to just extend (subclass) YAHOO.widget.Panel's show() function to call createTooltip but I'm not that much of a guru or I would probably need to change a very large codebase to do it.
try using the "container" property for the tooltip config (so the container would be the panel's element):
function createTooltip() {
window[tooltip_name] = new YAHOO.widget.Tooltip(tooltip_name, {
container: panel_obj.element,
context: element_id,
xyoffset: [15, -15]
});
}
This is the quick solution, using the show event and/or extending the class would be nice but gotta run, if you still need help, I'll check back (also check the example that i made with your code http://jsfiddle.net/3GWaM/2/ ).
function createTooltip() {
var tooltipEl = document.createElement('DIV');
panel_obj.get('element').appendChild(tooltipEl);
window[tooltip_name] = new YAHOO.widget.Tooltip(tooltipEl, {
context: element_id,
xyoffset: [15, -15],
zIndex: 999
});
}
This will ensure the that the tool tip div is created inside the dialog box, instead of in the document body, ensuring it does not appear below the dialog box.
Also, if you want to extend the panel class just do the following
function MyPanel(el, config) {
MyPanel.superclass.constructor.apply(this, arguments);
this.createToolTip();
}
YAHOO.lang.extend(MyPanel, YAHOO.widget.Panel , {
createToolTip: function () {
// create tool tip here
this.on('show', this.showTooltip, this, true);
},
showToolTip: function () {this.toolTip.show();}
});
function getPanelIDFromElementID (element_id) {
var parent_panel = YAHOO.util.Dom.getAncestorByClassName(element_id, 'yui-panel');
var parent_id = null;
if (parent_panel) {
parent_id = parent_panel.id;
}
return parent_id;
}
function createTooltips() {
var tooltip_elements = YAHOO.util.Dom.getElementsByClassName('tooltip');
for (var i = 0; i < tooltip_elements.length; i++) {
var ele_id = tooltip_elements[i].getAttribute('id');
var name = ele_id.charAt(0).toLowerCase() + ele_id.slice(1);
var nameArray = name.split("_");
for (var x=1; x < nameArray.length; x++) {
nameArray[x] = nameArray[x].charAt(0).toUpperCase() + nameArray[x].slice(1);
}
var elementName = nameArray.join('');
window[elementName] = new YAHOO.widget.Tooltip(elementName, {
context: escape(ele_id),
xyoffset: [15, -15],
zIndex: 999,
container: getPanelIDFromElementID(ele_id)
});
}
}