Can't get Highstock "scroll" to work - javascript

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"

Related

plotly.js Multiple plots created, only last one is working as intended

If I click on a symbol on a map I want to create timeseries-plots with plotly. If i click on the next symbol there should be a new plot etc.
This is working fine, but I am not able to use the plotly interface in the first plots again.
I build a jfiddle that shows my problem and my code:
var treediv_ids = [-1];
var timeseries_div_HTML = function(id) {
var ts_div_html_vis =
"<div class='ts_con_vis' id='ts_data_" + id + "'>\n\
<div class='ts_data_div' name='ts_data_div" + id + "' id='ts_data_div_" + id + "_env'></div>"
treediv_ids.push(id);
return ts_div_html_vis;
};
var addTS = function() {
// Create the subdivs for timeseries_production
var new_id = Math.max(...treediv_ids) + 1;
var new_div = timeseries_div_HTML(new_id);
$('#timeseriescontainer').html($('#timeseriescontainer').html() + new_div);
// Create timeseries using plotly and local datasets
//
// Environmental Data
// Create layout object
var layout_E = {
title: 'Tim',
yaxis: {
title: 'Value'
},
margin: {
t: 40,
b: 20,
r: 40,
l: 40
},
}
plot("ts_data_div_" + new_id + "_env", layout_E);
}
function plot(target_div, layout) {
var data = [];
for (var i = 1; i < 3; i++) {
var randomColor = Math.floor(Math.random() * 16777215).toString(16);
var trace = {
type: "scatter",
mode: "lines",
name: i,
x: [1, 2, 3, 4, 5, 6, 7, 8],
y: [1, 2, 3, 4, 5, 6, 7, 8],
line: {
color: randomColor
}
}
data.push(trace)
}
layout.title = layout.title + target_div.slice("ts_data_div_".length);
target = document.getElementById(target_div);
Plotly.newPlot(target, data, layout);
}
https://jsfiddle.net/wmg5k8xn/2/
I found this thread: Plotly.js only one plot working when using multiple plots on same page
But I did not understand why it is working in the accepted answer and why it is not working for me.
Edit: my HTML and CSS code:
<html>
<head>
<link rel="stylesheet" href="style.css" />
</head>
<body>
<button onclick=addTS() style="z-index:100">
ABC
</button>
<div id="timeseriescontainer"></div>
<script data-require="plotly#1.0.0" data-semver="1.0.0" src="https://cdn.plot.ly/plotly-latest.min.js" defer></script>
<script src="script.js" defer></script>
</body>
</html>
#timeseriescontainer{
width:90%;
height:100%;
position:absolute;
right:0px;
top: 0px;
background-color: green;
overflow-y: scroll;
}
.ts_con_vis{
background-color: red;
width: 99%;
height: 49%;
margin-left:5px;
margin-top:1px;
position: relative;
display: block;
}
.ts_data_div{
width: 100%;
height:100%;
position: absolute;
}
Your problem is caused by this line:
$('#timeseriescontainer').html($('#timeseriescontainer').html() + new_div);
Just use native browser functions instead:
const container = document.getElementById('timeseriescontainer');
container.insertAdjacentHTML('beforeend', new_div);
See https://jsfiddle.net/qhk7nmsp/

new dataset is not accepted by chartj template

I am trying to plot a line chart on the node red dashboard.
This template creates the desired scrollable chart with 100 randomly generated datapoints:
<style>.chartWrapper {
position: relative;
}
.chartWrapper > canvas {
position: absolute;
left: 0;
top: 0;
pointer-events: none;
}
.chartAreaWrapper {
width: auto;
overflow-x: scroll;
}
</style>
<div class="chartWrapper">
<div class="chartAreaWrapper">
<div class="chartAreaWrapper2">
<canvas id="chart-Test" height="351" width="4000"></canvas>
</div>
</div>
<canvas id="axis-Test" height="351" width="0"></canvas>
</div>
<script>
$(document).ready(function () {
function generateLabels() {
var chartLabels = [];
for (x = 0; x < 100; x++) {
chartLabels.push(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(),
pointRadius: 0,
borderColor: "#4ED7FC",
borderWidth: 2,
fill: false
}]
};
$(function () {
var rectangleSet = false;
var canvasTest = $('#chart-Test');
var chartTest = new Chart(canvasTest, {
type: 'line',
data: chartData,
maintainAspectRatio: false,
responsive: true,
});
addData(5, chartTest);
});
});
</script>
Next I wanted to replace the generated datapoints with a payload message coming into the dashboard template node, where msg.payload[0].data is an array[2500].
I thought I would be able to achieve this by replacing generateData()like so:
<style>.chartWrapper {
position: relative;
}
.chartWrapper > canvas {
position: absolute;
left: 0;
top: 0;
pointer-events: none;
}
.chartAreaWrapper {
width: auto;
overflow-x: scroll;
}
</style>
<div class="chartWrapper">
<div class="chartAreaWrapper">
<div class="chartAreaWrapper2">
<canvas id="chart-Test" height="351" width="4000"></canvas>
</div>
</div>
<canvas id="axis-Test" height="351" width="0"></canvas>
</div>
<script>
$(document).ready(function () {
function generateLabels() {
var chartLabels = [];
for (x = 0; x < 100; x++) {
chartLabels.push(x);
}
return chartLabels;
}
/*function generateData() {
var chartData = [];
for (x = 0; x < 100; x++) {
chartData.push(Math.floor((Math.random() * 100) + 1));
}
return chartData;
}*/
function generateData(msg) {
var chartData = [];
chartData = msg.payload[0].data;
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(),
pointRadius: 0,
borderColor: "#4ED7FC",
borderWidth: 2,
fill: false
}]
};
$(function () {
var rectangleSet = false;
var canvasTest = $('#chart-Test');
var chartTest = new Chart(canvasTest, {
type: 'line',
data: chartData,
responsive: true,
options: {
maintainAspectRatio: false,
tooltips: {
titleFontSize: 0,
titleMarginBottom: 0,
bodyFontSize: 12
},
legend: {
display: false
},
scales: {
xAxes: [{
ticks: {
fontSize: 12,
display: false
}
}],
yAxes: [{
ticks: {
fontSize: 12,
beginAtZero: true
}
}]
},
}
});
addData(5, chartTest);
});
});
</script>
But then the chart is just showing a blank:
Why is that?
[edit]
the incoming payload is not empty:
I would try the follwing:
1.- Check that your array[2500] has values between 1 and 100 and pass in the first 100 instead the whole 2500 array to check if that works
2.- Might depend on the chartjs version, but I would try to put the maintainAspectRatio property inside an options: {} object. See below.
var chart = new Chart('blabla', {
type: 'bar',
data: {},
options: {
maintainAspectRatio: false,
}
});
Apart from that, 2500 records seems to be a too big amount of data to handle. If the graph renders for smaller amounts, I would try to keep the graph drawn with an amount that gets rendered, and the fetch the data + update the chart depending on the users x-scroll.
Edit:
I think you need to call the addData for your new array with a modified addData function that would look something like this, for the width to fit.
function addData(chart) {
for (var i = 0; i < chart.data[0].data.length; i++) {
//chart.data.datasets[0].data.push(Math.random() * 100);
//chart.data.labels.push("Label" + i);
var newwidth = $('.chartAreaWrapper2').width() + 60;
$('.chartAreaWrapper2').width(newwidth);
}
}
Note that your script work up determined num of records with the arrangements mentioned, so if the graph goes blank can only be that your new array is empty or has some issue.
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.2/Chart.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<style>.chartWrapper {
position: relative;
}
.chartWrapper > canvas {
position: absolute;
left: 0;
top: 0;
pointer-events: none;
}
.chartAreaWrapper {
width: auto;
overflow-x: scroll;
}
</style>
<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 class="chartWrapper">
<div class="chartAreaWrapper">
<div class="chartAreaWrapper2">
<canvas id="chart-Test" height="351" width="4000"></canvas>
</div>
</div>
<canvas id="axis-Test" height="351" width="0"></canvas>
</div>
<script>
$(document).ready(function () {
function generateLabels() {
var chartLabels = [];
for (x = 0; x < 100; x++) {
chartLabels.push(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(),
pointRadius: 0,
borderColor: "#4ED7FC",
borderWidth: 2,
fill: false
}]
};
$(function () {
var rectangleSet = false;
var canvasTest = $('#chart-Test');
var chartTest = new Chart(canvasTest, {
type: 'line',
data: chartData,
options: {
maintainAspectRatio: false,
responsive: true
}
});
addData(300, chartTest);
});
});
</script>
I found out that the dashboard template node does not easily accept payload messages on the script section.
watch function
I have to use something like:
// Watch the payload and update
(function(scope) {
scope.$watch('msg.payload', function(data) {
update(data);
});
})(scope);
function update(dta) {
theScope.send({payload:dta});
bleh = dta.name;
otherStuff();
}
to watch a incoming payload and store it.
My initial question "Why is that?" is therefore answered.
Unfortunately I am not quite sure how to implement this new bit of code to the array coming in in msg.payload[0.data in my specific case.

Make y-axis sticky when having horizontal scroll on chartJS and Angular

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.

Title: TypeError: Plotly.newPlot(...).Promise is undefined

If I use the below line of code:
return Plotly.newPlot(div1, data, layout, { displayModeBar: false, staticPlot: true }) ;
in the below plotly plot function and call plot(crypto("BTC")) in the online code editor I get
[object Promise]
and if I change the above line of code to:
CreateInputDiv();
return Plotly.newPlot(div1, data, layout, { displayModeBar: false, staticPlot: true }).Promise.resolve();
then I get the plot in the online code editor but then I also get the following error in the console.log
TypeError: Plotly.newPlot(...).Promise is undefined
I doubt I am doing thing correctly because I have a hard time understanding how async functions and promises work. The solution to my problem might be very simple or not. If the above code was working correctly I would not have to create a new input div because function parse() creates input and output divs and I would also not get an error in the console log. How can the error message in the console.log be solved?
JavaS.js and HTML below
// counts the number of input divs created
function increment() {
increment.n = increment.n || 0;
return ++increment.n;
}
// creates an input div
function CreateInputDiv() {
increment();
cc = increment.n;
//console.log("increment.n = " + cc);
input = document.createElement("div");
input.setAttribute("id", "input" + cc);
input.setAttribute("class", "input");
input.innerHTML = "&nbsp";
input.setAttribute("contenteditable", "true");
input.setAttribute("onkeypress", "parse(event, this)");
document.getElementById('calc').appendChild(input);
input.focus();
}
// creates an output div
function CreateOutputDiv() {
output = document.createElement("div");
output.setAttribute("id", "output" + cc);
output.setAttribute("class", "output");
output.setAttribute("tabindex", "0");
output.setAttribute("contenteditable", "false");
document.getElementById('calc').appendChild(output);
}
function parse(e1, e2) {
console.log("e2 = " + e2);
if (e1.keyCode == 13) { // keycode for enter
event.preventDefault();
var inId = e2.id;
console.log("inId = " + inId);
var outId = "output" + inId.substring(5);
console.log("outId = " + outId);
var inz = input.innerText;
// check if input contains a colon. Hides output if colon exist.
if (inz.indexOf(':') > -1) {
var inz = input.innerText.replace(/:/g, '');
console.log("input with colon = " + inz);
var outz = eval(inz);
console.log("hidden out = " + outz);
document.getElementById("count").value += '\n' + '\n' + eval(cc + 1);
CreateOutputDiv();
CreateInputDiv();
}
else { // no colon = display and revaluate input
if (document.getElementById(outId)) {
console.log("Already created");
inz = document.getElementById(inId).innerText;
console.log("inz = " + inz);
var outz = eval(inz);
console.log("outz = " + outz);
document.getElementById(outId).innerHTML = outz;
input.focus();
}
else { // no colon = display create new lines
document.getElementById("count").value += '\n' + '\n' + eval(cc + 1);
CreateOutputDiv();
// calculate and assign output value to output div
// console.log("input = " + inz);
var outz = eval(inz);
// console.log("out z = " + outz);
output.innerHTML = outz;
CreateInputDiv();
}
}
}
}
function T(UNIX_timestamp) {
var MyDate = new Date(UNIX_timestamp * 1000);
var MyDateString = MyDate.getFullYear() + '-' + ('0' + (MyDate.getMonth() + 1)).slice(-2) + '-' + ('0' + MyDate.getDate()).slice(-2);
return JSON.stringify(MyDateString);
}
function crypto(ticker) {
var ApiKey = "ddd85b386e1a7c889e468a4933f75f22f52b0755b747bdb637ab39c88a3bc19b";
var urlA = "https://min-api.cryptocompare.com/data/histoday?fsym=" + ticker + "&tsym=USD&limit=1000&api_key=" + ApiKey;
var result = null;
$.ajax({
url: urlA,
async: false, // makes a synchrously data call to cryptocompare
dataType: "json",
success: function (data) { result = data; }
});
var y = result.Data;
var D1 = [];
var D2 = [];
for (var i = 0; i < y.length; i++) {
D1.push(T(y[i].time));
D2.push(y[i].close);
}
console.log(D2);
return D2;
}
// plots a give data array
function plot(z) {
var yy = z;
var xx = [];
for (var i = 0; i <= yy.length; i++) {
xx[i] = JSON.stringify(i);
}
var data = [{
x: xx,
y: yy,
type: 'scatter',
line: { color: 'green', width: 2 }
}];
var layout =
{
width: 700,
height: 300,
paper_bgcolor: 'lightblue',
plot_bgcolor: 'lightblue',
margin: { l: 60, b: 60, r: 20, t: 20 },
title: "",
xaxis: {
title: 'x-axis', titlefont: {
family: 'Courier New, monospace', size: 18,
color: 'black'
}
},
yaxis: {
title: 'y-axis', titlefont: { family: 'Courier New, monospace', size: 18, color: 'black' },
width: 1000, height: 380,
xaxis: {
tickfont: { size: 12, color: 'black' }, showgrid: true, tickmode: "linear",
gridcolor: 'black', linecolor: 'black'
},
yaxis: {
tickfont: { size: 12, color: 'black' }, showgrid: true,
gridcolor: 'black', linecolor: 'black'
}
}
};
cc = increment.n;
div1 = 'output' + cc;
// return Plotly.newPlot(div1, data, layout, { displayModeBar: false, staticPlot: true }) ; // object promise
CreateInputDiv();
return Plotly.newPlot(div1, data, layout, { displayModeBar: false, staticPlot: true }).Promise.resolve();
}
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="JavaS.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdn.plot.ly/plotly-latest.min.js"></script>
<meta charset="utf-8" />
<style>
.input {
background-color: lightgreen;
width: 980px;
border: none;
font-size: 16px;
resize: none;
}
.output {
background-color: lightblue;
width: 980px;
line-height: 20px;
border: none;
font-size: 16px;
resize: none;
overflow-wrap: break-word;
}
#count {
background-color: lightblue;
color: black;
width: 25px;
height: 500px;
font-size: 17px;
resize: none;
border: none;
}
#calc {
background-color: lightblue;
vertical-align: top;
border: none;
overflow: hidden;
}
</style>
</head>
<body bgcolor="grey">
<table align="center" width="1000px" height="500px" bgcolor="lightblue" overflow="hidden">
<tr>
<td><textarea id="count" disabled>1 </textarea> </td>
<td id="calc"></td>
</tr>
</table>
<script> CreateInputDiv(); </script>
</body>
</html>
A working solution to the above plotting problem can be found below. Replace
the line
return Plotly.newPlot(div1, data, layout, { displayModeBar: false, staticPlot: true }) ; // object promise
in the plot function with
setTimeout(function(){Plotly.newPlot(div1, data, layout, { displayModeBar: false, staticPlot: true });}, 10);
return "";
That will give you the plotly.js plot in the web editor without getting [object Promise] or any error messages in the console log.

jQuery flot hover not working when user moves down the page

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! :)

Categories

Resources