I am using jQuery flot. I can't seem to explain the bug well. But by the looks of it, the hover does not work when the user moves down to the page: Here's the video:
http://screencast.com/t/qZIjJ8jsi
Notice when i'm on top of my page the hover is working, but when I'll go down the page, then the hover on the points won't work.
My page is responsive(not sure if that's related, but just saying). Looks like this is a CSS problem. So here's my code:
var graphData = decodeURIComponent(jQuery("#graphData").val());
graphData = jQuery.parseJSON(graphData);
var visitors = new Array();
var totalVisitors = 0;
jQuery.each(graphData,function(index,value){
visitors[index] = [value[0],value[1]];
totalVisitors = totalVisitors + parseInt(value[1]);
});
jQuery(".date-figures").text(totalVisitors);
var visitor = $("#activeUsers"),
data_visitor = [{
data: visitors,
color: '#058DC7'
}],
options_lines = {
series: {
lines: {
show: true,
fill: true,
fillColor: "#E5F3F9",
color:"#058DC7",
},
points: {
show: true
},
hoverable: true
},
grid: {
backgroundColor: '#FFFFFF',
borderWidth: 0,
borderColor: '#CDCDCD',
hoverable: true
},
legend: {
show: true
},
xaxis: {
mode: "time",
},
yaxis: {
show:true
},
};
$.plot(visitor, data_visitor, options_lines);
function showTooltip(x, y, contents) {
$('<div id="tooltip">' + contents + '</div>').css({
position: 'absolute',
display: 'none',
top: y + 5,
left: x + 5,
padding: '2px 10px 2px 10px',
opacity: 0.8,
}).appendTo("body").fadeIn(200);
}
var previousPoint = null;
$('#visitor-stat, #order-stat, #user-stat,#activeUsers').bind("plothover", function (event, pos, item) {
if (item) {
if (previousPoint != item.dataIndex) {
previousPoint = item.dataIndex;
$("#tooltip").remove();
var d = new Date(item.datapoint[0]);
var day = parseDay(d.getDay());
var date = d.getDate();
var month = parseMonth(d.getMonth());
var year = d.getFullYear();
var tooltipWording = "<b>"+day+", "+month+" "+date+", "+year+"</b>";
tooltipWording += "<ul>";
tooltipWording += "<li>Visits: <b>"+item.datapoint[1]+"</b></li>";
tooltipWording += "</ul>";
showTooltip(item.pageX, item.pageY, tooltipWording);
}
}
else {
$("#tooltip").remove();
previousPoint = null;
}
});
});
What seems to be problem here? Your help will be greatly appreciated! Thanks! :)
Related
I want to convert a HTML page like the given one having a form in it to PDF using jsPDF, but the table isn't getting printed with all of the columns in it. So I am thinking to print it on a landscape page but I am confused with the size measurements. Can anyone help me to get it done correctly?
And this is how it gets printed:
<script src="https://code.jquery.com/jquery-1.12.4.min.js" integrity="sha256-ZosEbRLbNQzLpnKIkEdrPv7lOy9C27hHQ+Xp8a4MxAQ=" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/1.3.5/jspdf.min.js"></script>
<script>
(function () {
var
form = $('.form'),
cache_width = form.width(),
a4 = [595.28, 841.89]; // for a4 size paper width and height
$('#create_pdf').on('click', function () {
$('body').scrollTop(0);
createPDF();
});
//create pdf
function createPDF() {
getCanvas().then(function (canvas) {
var
img = canvas.toDataURL("image/png"),
doc = new jsPDF({
unit: 'px',
format: 'a4'
});
doc.addImage(img, 'JPEG', 20, 20);
doc.save('suman-html-to-pdf.pdf');
form.width(cache_width);
});
}
// create canvas object
function getCanvas() {
form.width((a4[0] * 1.33333) - 80).css('max-width', 'none');
return html2canvas(form, {
imageTimeout: 2000,
removeContainer: true
});
}
}());
</script>
<script>
/*
* jQuery helper plugin for examples and tests
*/
(function ($) {
$.fn.html2canvas = function (options) {
var date = new Date(),
$message = null,
timeoutTimer = false,
timer = date.getTime();
html2canvas.logging = options && options.logging;
html2canvas.Preload(this[0], $.extend({
complete: function (images) {
var queue = html2canvas.Parse(this[0], images, options),
$canvas = $(html2canvas.Renderer(queue, options)),
finishTime = new Date();
$canvas.css({ position: 'absolute', left: 0, top: 0 }).appendTo(document.body);
$canvas.siblings().toggle();
$(window).click(function () {
if (!$canvas.is(':visible')) {
$canvas.toggle().siblings().toggle();
throwMessage("Canvas Render visible");
} else {
$canvas.siblings().toggle();
$canvas.toggle();
throwMessage("Canvas Render hidden");
}
});
throwMessage('Screenshot created in ' + ((finishTime.getTime() - timer) / 1000) + " seconds<br />", 4000);
}
}, options));
function throwMessage(msg, duration) {
window.clearTimeout(timeoutTimer);
timeoutTimer = window.setTimeout(function () {
$message.fadeOut(function () {
$message.remove();
});
}, duration || 2000);
if ($message)
$message.remove();
$message = $('<div ></div>').html(msg).css({
margin: 0,
padding: 10,
background: "#000",
opacity: 0.7,
position: "fixed",
top: 10,
right: 5,
fontFamily: 'Tahoma',
color: '#fff',
fontSize: 12,
borderRadius: 12,
width: 'auto',
height: 'auto',
textAlign: 'center',
textDecoration: 'none'
}).hide().fadeIn().appendTo('body');
}
};
})(jQuery);
</script>
I would like to fix y-axis position when scrolling horizontally.
Here's an example that works but without using Angular
$(document).ready(function () {
function generateLabels() {
var chartLabels = [];
for (x = 0; x < 100; x++) {
chartLabels.push("Label" + x);
}
return chartLabels;
}
function generateData() {
var chartData = [];
for (x = 0; x < 100; x++) {
chartData.push(Math.floor((Math.random() * 100) + 1));
}
return chartData;
}
function addData(numData, chart) {
for (var i = 0; i < numData; i++) {
chart.data.datasets[0].data.push(Math.random() * 100);
chart.data.labels.push("Label" + i);
var newwidth = $('.chartAreaWrapper2').width() + 60;
$('.chartAreaWrapper2').width(newwidth);
}
}
var chartData = {
labels: generateLabels(),
datasets: [{
label: "Test Data Set",
data: generateData()
}]
};
$(function () {
var rectangleSet = false;
var canvasTest = $('#chart-Test');
var chartTest = new Chart(canvasTest, {
type: 'bar',
data: chartData,
maintainAspectRatio: false,
responsive: true,
options: {
tooltips: {
titleFontSize: 0,
titleMarginBottom: 0,
bodyFontSize: 12
},
legend: {
display: false
},
scales: {
xAxes: [{
ticks: {
fontSize: 12,
display: false
}
}],
yAxes: [{
ticks: {
fontSize: 12,
beginAtZero: true
}
}]
},
animation: {
onComplete: function () {
if (!rectangleSet) {
var sourceCanvas = chartTest.chart.canvas;
var copyWidth = chartTest.scales['y-axis-0'].width;
var copyHeight = chartTest.scales['y-axis-0'].height + chartTest.scales['y-axis-0'].top + 10;
var targetCtx = document.getElementById("axis-Test").getContext("2d");
targetCtx.canvas.width = copyWidth;
targetCtx.drawImage(sourceCanvas, 0, 0, copyWidth, copyHeight, 0, 0, copyWidth, copyHeight);
var sourceCtx = sourceCanvas.getContext('2d');
sourceCtx.clearRect(0, 0, copyWidth, copyHeight);
rectangleSet = true;
}
},
onProgress: function () {
if (rectangleSet === true) {
var copyWidth = chartTest.scales['y-axis-0'].width;
var copyHeight = chartTest.scales['y-axis-0'].height + chartTest.scales['y-axis-0'].top + 10;
var sourceCtx = chartTest.chart.canvas.getContext('2d');
sourceCtx.clearRect(0, 0, copyWidth, copyHeight);
}
}
}
}
});
addData(5, chartTest);
});
});
.chartWrapper {
position: relative;
}
.chartWrapper > canvas {
position: absolute;
left: 0;
top: 0;
pointer-events: none;
}
.chartAreaWrapper {
width: 600px;
overflow-x: scroll;
}
<script src="https://github.com/chartjs/Chart.js/releases/download/v2.6.0/Chart.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="chartWrapper">
<div class="chartAreaWrapper">
<div class="chartAreaWrapper2">
<canvas id="chart-Test" height="300" width="1200"></canvas>
</div>
</div>
<canvas id="axis-Test" height="300" width="0"></canvas>
</div>
When I use this in my angular example , it does not work anymore, the axis does not follow the scroll
Here's a stackblitz reproduction
In your StackBlitz, the section (rectanlge) of the y-axis is correctly created on the target canvas and removed from the source canvas. The problem is that the wrong div is horizontally scrolled. This can be fixed by changing the template and corresponding css.
Please have a look at the following StackBlitz.
UPDATE (dynamic data)
In cases where the chart component receives dynamically changing data through an #Input() property, your component needs to implement the OnChange lifecycle hook.
See the following StackBlitz.
Please note that this code is far from being optimized. Instead of creating the chart from scratch on every data change, you should simply update the data and options on the existing chart.
Is there a way to highlight a specific point when mouse is over or near that specific point ? The thing is that I don't want to highlight all the lines but only the point(s) under or near my cursor. My goal is to show a tooltip at that position with the informations for that point.
This ChartJs example demonstrate pretty well what I would like to do:
http://www.chartjs.org/samples/latest/scales/time/line.html
And these are my current options:
{
drawPoints: true,
showRoller: false,
highlightCircleSize: 5,
labels: ['Time', 'Vac', 'Temp'],
ylabel: 'Vaccum (In/Hg)',
y2label: 'Temperature ('+ TemperatureUnitFactory.getTemperatureUnit() + ')',
series : {
'Vac': {
axis: 'y'
},
'Temp': {
axis: 'y2'
}
},
axes: {
y: {
drawGrid: true,
independentTicks: true,
valueRange: [0, -32],
label: 'Vaccum'
},
y2: {
drawGrid: false,
independentTicks: true,
valueRange: [
TemperatureUnitFactory.getTemperatureForUnit(-30),
TemperatureUnitFactory.getTemperatureForUnit(35)
],
ylabel: 'Temperature'
}
}
}
If you feel like I am missing informations that would help you enlighting me, just let me know in a comment.
Thank you all!
So here's a snippet for the solution to my problem. I believe it could be optimized by throtling the mousemouve callback, but in my case it did just fine. I converted the snippet from angular to jQuery for "simplicity".
var data = [
[new Date(20070101),62,39],
[new Date(20070102),62,44],
[new Date(20070103),62,42],
[new Date(20070104),57,45],
[new Date(20070105),54,44],
[new Date(20070106),55,36],
[new Date(20070107),62,45],
[new Date(20070108),66,48],
[new Date(20070109),63,39],
[new Date(20070110),57,37],
[new Date(20070111),50,37],
[new Date(20070112),48,35],
];
var graph = new Dygraph(
document.getElementById("chart"), data, {
rollPeriod: 1,
labels: ['Time', 'Vac', 'Temp'],
showRoller: false,
drawPoints: true,
}
);
var tooltip = {
element: $('#tooltip'),
x: function(_x){
this.element.css('left', _x);
},
y: function(_y) {
this.element.css('top', _y);
},
shown: false,
throttle: null,
currentPointData: null,
show: function() {
if(!this.shown) {
this.element.show();
this.shown = true;
}
},
hide: function() {
this.cancelThrottle();
if(this.shown) {
this.element.hide();
this.shown = false;
}
},
cancelThrottle: function () {
if(this.throttle !== null) {
clearTimeout(this.throttle);
this.throttle = null;
}
},
bindPoint: function (_point) {
this.element.html([_point.point.name,_point.point.xval, _point.point.yval].join(' | '))
console.log('Handle point data', _point);
}
};
var chartElement = $('#chart');
var isMouseDown = false;
chartElement.on('mousedown', function(){ isMouseDown = true; });
chartElement.on('mouseup', function(){ isMouseDown = false; });
chartElement.on('mousemove', function(){
if(graph === null) { return; }
if(isMouseDown) {
tooltip.hide();
return;
}
const ACCEPTABLE_OFFSET_RANGE = 8;
const TOOLTIP_BOTTOM_OFFSET = 25;
const TOOLTIP_THROTTLE_DELAY = 600;
var graphPos = Dygraph.findPos(graph.graphDiv),
canvasX = Dygraph.pageX(event) - graphPos.x,
canvasY = Dygraph.pageY(event) - graphPos.y,
rows = graph.numRows(),
cols = graph.numColumns(),
axes = graph.numAxes(),
diffX, diffY, xPos, yPos, inputTime, row, col, axe;
for (row = 0; row < rows; row++)
{
inputTime = graph.getValue(row, 0);
xPos = graph.toDomCoords(inputTime, null)[0];
diffX = Math.abs(canvasX - xPos);
if (diffX < ACCEPTABLE_OFFSET_RANGE)
{
for (col = 1; col < cols; col++)
{
var inputValue = graph.getValue(row, col);
if (inputValue === null) { continue; }
for(axe = 0; axe < axes; axe++)
{
yPos = graph.toDomCoords(null, inputValue, axe)[1];
diffY = Math.abs(canvasY - yPos);
if (diffY < ACCEPTABLE_OFFSET_RANGE)
{
tooltip.cancelThrottle();
if(!tooltip.shown)
{
var self = this;
tooltip.throttle = setTimeout(function () {
var ttHeight = tooltip.element.height(),
ttWidth = tooltip.element.width();
tooltip.x((xPos - (ttWidth / 2)));
tooltip.y((yPos - (ttHeight + TOOLTIP_BOTTOM_OFFSET)));
tooltip.show();
var closestPoint = graph.findClosestPoint(xPos, yPos);
if(closestPoint) {
tooltip.bindPoint(closestPoint);
}
}, TOOLTIP_THROTTLE_DELAY);
}
return;
}
}
}
}
}
tooltip.hide();
});
.chart-container {
position:relative;
}
.chart-container > .tooltip {
position:absolute;
padding: 10px 10px;
background-color:#ababab;
color:#fff;
display:none;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/dygraph/2.1.0/dygraph.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/dygraph/2.1.0/dygraph.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="chart-container">
<div id="chart"></div>
<div id="tooltip" class="tooltip">
Some data to be shown
</div>
</div>
I would like to add a % tag to the z value that is show on hover. Also, right now, my colorscale is only displaying -10 to 10, but I would like it to show % so -10% to 10%. Here is the code I have.
I have tried to add the ticksuffix : "%", but I'm not sure where I should put it since it seems like the colorscale is not an axis like the x and y axis.
var xValues = ['A', 'B', 'C',];
var yValues = ['W', 'X', 'Y', 'Z'];
var zValues = [[-2.45,-0.4,1.3],
[2.9,3.9,-5.66],
[0.5,-2.6,-3.2],
[-8.3,-0.5,-0.1]];
var a_text = [["Comodities + producers","Consumer Discretionary","Utilities Equities"],
["Health and Biotech","Global Real Estate","Financial Equities"],
["Emerging Market Bonds","Technology Equities","Industrials Equities"],
["Oil and Gas","China Equities","Diversified Portfolio"]];
var data = [{
x: xValues,
y: yValues,
z: zValues,
hoverinfo: "z",
reversescale: true,
type: 'heatmap',
// zsmooth: "best",
colorscale: "Spectral",
zauto: false,
zmin:-10,
zmax:10,
showscale: true,
}];
var layout = {
title: 'Annotated Heatmap',
annotations: [],
xaxis: {
ticks: '',
side: 'top',
tickfont: {color: 'rgb(255,255,255)'}
},
yaxis: {
ticks: '',
ticksuffix: ' ',
width: 700,
height: 700,
autosize: true,
tickfont: {color: 'rgb(255,255,255)'},
}
};
for ( var i = 0; i < yValues.length; i++ ) {
for ( var j = 0; j < xValues.length; j++ ) {
var currentValue = (zValues[i][j]);
if (currentValue < -0.05) {
var textColor = 'white';
}else{
var textColor = 'black';
}
var result = {
xref: 'x1',
yref: 'y1',
x: xValues[j],
y: yValues[i],
text: a_text[i][j],
font: {
family: 'Arial',
size: 12,
color: 'rgb(50, 171, 96)'
},
showarrow: false,
font: {
color: textColor
}
};
layout.annotations.push(result);
}
}
Plotly.newPlot('myDiv', data, layout);
You need to change two things, the color bar and the hover text.
Color bar
Add this info to your variable data.
colorbar: {
title: 'Relative change',
ticksuffix: '%',
}
Hover text
First convert the z-values into strings and append %.
var zText = [];
var prefix = "+";
var i = 0;
var j = 0;
for (i = 0; i < zValues.length; i += 1) {
zText.push([]);
for (j = 0; j < zValues[i].length; j += 1) {
if (zValues[i][j] > 0) {
prefix = "+";
} else {
prefix = "";
}
zText[i].push(prefix + zValues[i][j] + "%");
}
}
Then assign the new text to the plot.
Add
text: zText,
hoverinfo: "text",
to your variable data.
Here is a fiddle with the complete data and code: https://jsfiddle.net/Ashafix/e6936boq/2/
trying to compare two sensor readings - the data is coming from thingspeak. I've got the zoom part working, but for some reason I cant get the scroll to work.
<script type="text/javascript">
// variables for the first series
var series_1_channel_id = 43330;
var series_1_field_number = 4;
var series_1_read_api_key = '7ZPHNX2SXPM0CA1K';
var series_1_results = 480;
var series_1_color = '#d62020';
var series_1_name = 'Zims Sensor';
// variables for the second series
var series_2_channel_id = 45473;
var series_2_field_number = 2;
var series_2_read_api_key = 'N12T3CWQB5IWJAU9';
var series_2_results = 480;
var series_2_color = '#00aaff';
var series_2_name = 'UVM30a';
// chart title
var chart_title = 'UV Sensors Zim / UVM30A';
// y axis title
var y_axis_title = 'UV Index';
// user's timezone offset
var my_offset = new Date().getTimezoneOffset();
// chart variable
var my_chart;
// when the document is ready
$(document).on('ready', function() {
// add a blank chart
addChart();
// add the first series
addSeries(series_1_channel_id, series_1_field_number, series_1_read_api_key, series_1_results, series_1_color, series_1_name);
// add the second series
addSeries(series_2_channel_id, series_2_field_number, series_2_read_api_key, series_2_results, series_2_color, series_2_name);
});
// add the base chart
function addChart() {
// variable for the local date in milliseconds
var localDate;
// specify the chart options
var chartOptions = {
chart: {
renderTo: 'chart-container',
defaultSeriesType: 'line',
zoomType: 'x', // added here
backgroundColor: '#ffffff',
events: { }
},
title: { text: chart_title },
plotOptions: {
series: {
marker: { radius: 3 },
animation: true,
step: false,
borderWidth: 0,
turboThreshold: 0
}
},
tooltip: {
// reformat the tooltips so that local times are displayed
formatter: function() {
var d = new Date(this.x + (my_offset*60000));
var n = (this.point.name === undefined) ? '' : '<br>' + this.point.name;
return this.series.name + ':<b>' + this.y + '</b>' + n + '<br>' + d.toDateString() + '<br>' + d.toTimeString().replace(/\(.*\)/, "");
}
},
xAxis: {
type: 'datetime',
scrollbar: {
enabled: true,
barBackgroundColor: 'gray',
barBorderRadius: 7,
barBorderWidth: 0,
buttonBackgroundColor: 'gray',
buttonBorderWidth: 0,
buttonArrowColor: 'yellow',
buttonBorderRadius: 7,
rifleColor: 'yellow',
trackBackgroundColor: 'white',
trackBorderWidth: 1,
trackBorderColor: 'silver',
trackBorderRadius: 7
},
title: { text: 'Date' }
},
yAxis: { title: { text: y_axis_title } },
exporting: { enabled: true },
legend: { enabled: true },
credits: {
text: 'ThingSpeak.com',
href: 'https://thingspeak.com/',
style: { color: '#D62020' }
}
};
// draw the chart
my_chart = new Highcharts.Chart(chartOptions);
}
// add a series to the chart
function addSeries(channel_id, field_number, api_key, results, color, name) {
var field_name = 'field' + field_number;
// get the data with a webservice call
$.getJSON('https://api.thingspeak.com/channels/' + channel_id + '/fields/' + field_number + '.json?offset=0&round=2&results=' + results + '&api_key=' + api_key, function(data) {
// blank array for holding chart data
var chart_data = [];
// iterate through each feed
$.each(data.feeds, function() {
var point = new Highcharts.Point();
// set the proper values
var value = this[field_name];
point.x = getChartDate(this.created_at);
point.y = parseFloat(value);
// add location if possible
if (this.location) { point.name = this.location; }
// if a numerical value exists add it
if (!isNaN(parseInt(value))) { chart_data.push(point); }
});
// add the chart data
my_chart.addSeries({ data: chart_data, name: data.channel[field_name], color: color });
});
}
// converts date format from JSON
function getChartDate(d) {
// offset in minutes is converted to milliseconds and subtracted so that chart's x-axis is correct
return Date.parse(d) - (my_offset * 60000);
}
</script>
<style type="text/css">
body { background-color: white; height: 100%; margin: 0; padding: 0; }
#chart-container { width: 800px; height: 400px; display: block; position:absolute; bottom:0; top:0; left:0; right:0; margin: 5px 15px 15px 0; overflow: hidden; }
</style>
<!DOCTYPE html>
<html style="height: 100%;">
<head>
<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script type="text/javascript" src="//code.highcharts.com/stock/highstock.js"></script>
<script type="text/javascript" src="//thingspeak.com/exporting.js"></script>
</head>
<body>
<div id="chart-container">
// <img alt="Ajax loader" src="//thingspeak.com/assets/ajax-loader.gif" style="position: absolute; margin: auto; top: 0; left: 0; right: 0; bottom: 0;" />
</div>
</body>
</html>
I would also like to get the chart updating automatically, so any help on that score would also be appreciated. The final issue I am having is trying to get the legend to display the sensor names properly: UV Index (red) should read "Zims Sensor" and UV Index (blue) should read "UVM30A"