I am working on asp.net MVC 5. I have created 4 different types of charts in it which are viewing on same page. I am getting data from a meter at almost 15-20 seconds interval. All i want to do is to refresh my charts after each 15/20 seconds so for every new entry in DB i should not refresh my page manually. For this i have used javascript setInterval in my graph view like bellow
setInterval(function () {
$.ajax({
url: '/Home/MultiGraph',
type: "POST",
success: function (result) {
$("#c1").html(result);
}
});
alert("hello");
}, 3000);
Bellow are my divs in which i have placed my charts
<div id="c1">
<div id="container1" style="height: 400px; width:auto"></div>
<div id="container2" style="height: 400px; width:auto"></div>
<div id="container3" style="height: 400px; width:auto"></div>
<div id="container4" style="height: 400px; width:auto"></div>
</div>
At $(window).on('load', function () { } i have placed my 4 charts initialization like bellow
var chart1 = new Highcharts.Chart({//rendered to container1});
var chart2 = new Highcharts.Chart({//rendered to container2});
var chart3 = new Highcharts.Chart({//rendered to container3});
var chart4 = new Highcharts.Chart({//rendered to container4});
All the data in charts are coming in array format
So after running my page look like bellow image
After i press Ok i get bellow
I don't know why it's happening, i just want to refresh/reload the charts only but all i am getting the above results as it's refresh the whole page also on refresh i am unable to view my charts
Moreover my charts are placed in a view and this view is following the main layout i.e. else charts and search bar all my view is coming from layout
UPDATE:
Bellow is the image which is showing me the data in result
Any help would be highly appreciated
since you are using setInterval it repeats everything inside on that clause, it keeps adding HighChart object in that object.
What you can do is add beforeSend in your ajax:
$.ajax({
url: '/Home/MultiGraph',
type: "POST",
beforeSend: function (result) {
$("#c1").empty(); //empty first the div
},
success: function (result) {
$("#c1").html(result);
}
});
Related
I am supporting a website. On one of the pages, the site uses ajax to retrieve data from the backend and, after receiving data, build charts (i.e. pie and bar charts) one by one and append each chart to the page. The 3rd party chart tool is Highcharts. Here is the code structure:
HTML:
<div id="charts"></div>
Javascript:
$.ajax({
url: backend_URL
dataType: json,
success: function(data) {
var container = $('#charts');
$.each(data, function(index, item) {
var chart = ...build-a-chart-by-using-data-item-and-Highcharts...;
container.append(chart);
}
}
});
The problem with this code is that the page doesn't display anything until all charts are built and appended. If there are 100 charts, then it is a quite long wait for a user. The better user experience should be building a chart and showing it to the user so that the user can see the progress and look at what is displayed (instead of seeing a blank screen or a modal spinning wheel). How can I do it the better way? I must be missing something.
In your query, you create one container and load data into it, which is possibly why it doesn't work smoothly.
You are loading large amounts of data at once. Instead, you could try creating separate divs for each chart.
Demo: http://jsfiddle.net/BlackLabel/59ucxq1a/
Highcharts.ajax({
url: 'https://cdn.jsdelivr.net/gh/highcharts/highcharts#v7.0.0/samples/data/activity.json',
dataType: 'text',
success: function(data) {
data = JSON.parse(data);
data.datasets.forEach(function(dataset, i) {
var chartDiv = document.createElement('div');
chartDiv.className = 'chart';
document.getElementById('container').appendChild(chartDiv);
Highcharts.chart(chartDiv, {
title: {
text: dataset.name,
},
series: [{
data: dataset.data,
name: dataset.name,
type: dataset.type,
}]
});
});
}
});
.chart {
height: 220px;
}
<script src="https://code.highcharts.com/highcharts.js"></script>
<script src="https://code.highcharts.com/modules/data.js"></script>
<script src="https://code.highcharts.com/modules/accessibility.js"></script>
<div id="container"></div>
I have been trying to solve this problem with ChartJS for a few days now, and I am completely stumped
My program shows the user a set of input elements they use to select data needing to be charted, plus a button that has an event to chart their data. The first chart works great. If they make a change to the data and click the button a second, third, or more time, all the data from the previous charts is plotted, PLUS their most recent selection.
It is behaving exactly like you might expect if the chart.destroy() object is not working, or perhaps would work if I created the chart object using a CONST (and could therefore add new data but not delete the beginning data).
I have tried all combinations of the browsers, chartjs and jquery libraries below:
Three different browsers:
• Chrome: Version 107.0.5304.121 (Official Build) (64-bit)
• Microsoft Edge: Version 107.0.1418.56 (Official build) (64-bit)
• Firefox: 107.0 64-bit
I have tried at least three different versions of Chart.js, including
• Versions 3.9.1
• 3.6.2
• 3.7.0
Jquery.js
• v3.6.1
• v1.11.1
Other things I have tried:
"use strict" (no luck)
In addition to destroying the chart object, removed the div containing the canvas, and appending it again.
using setTimeout() function before updating the chart after destroying it (because I thought maybe giving the destroy method more time might help)
type here
Software:
<script type="text/javascript" src="js/jquery.js"></script>
<script type="text/javascript" src="js/chart.js"></script>
<script type="text/javascript" src="js/dropdownLists.js"></script>
<script type="text/javascript" src="js/chartDataFunctions.js"></script>
<script type="text/javascript" src="js/chartJSFunctions.js"></script>
<body>
<div class = metadatasetup4" id = "buttons">
<button class="download" id="getchart" value="Get Chart">Chart</button>
<button class="download" id="downloadchart" value="Download">Download</button>
</div>
<div id = "bigchartdiv" class="bigchart">
<canvas id="myChart"></canvas>
</div>
</body>
<script>
$(window).on('load',function(){
//NOTE 1: In of my attempts to troubleshoot I tried strict mode (it didn't work)
//"use strict";
let data = {
labels: lbl,
datasets: [
]
};
let config = {
type: 'line',
data: data,
options: {
scales: {
y: {
type: 'linear',
display: true,
position: 'left',
min:0,
pointStyle:'circle',
},
y1: {
type: 'linear',
display: true,
position: 'right',
suggestedMax: 25,
min: 0,
pointStyle: 'cross',
// grid line settings
grid: {
drawOnChartArea: false, // only want the grid lines for one axis to show up
},
},
}
}
};
// NOTE 2: The next line below, beginning with "var bigChartHTML =" was one of my later attempts to
// solve the problem. It didn't work, but my thought process was that if I removed
// the div containing the canvas, AND destroyed the chart object, that appending a "fresh"
// chart div to the body might be a work-around. This did not work.
var bigChartHTML = '<div id = "bigchartdiv" class="bigchart"><canvas id="myChart"></canvas></div>'
let ctx = document.getElementById('myChart').getContext('2d');
let bigChart = null;
// The getChartData() function below uses Ajax to populate various dropdown lists
// which enable the user to select the data is to be charted.
// There are no chartjs-related operations in getChartData()
getChartData();
$('#buttons').on('click','#getchart',function(){
if (bigChart!=null) {
//removeData(bigChart);
bigChart.destroy();
//bigChart = 1;
}
$("#bigchartdiv").empty(); //for this and next 2 lines, see NOTE 2 above
$("#bigchartdiv").remove();
$(bigChartHTML).insertAfter("#chartcontrols");
bigChart = new Chart(document.getElementById('myChart'),config);
//NOTE 3: I thought maybe bigChart.destroy() took time, so I tried
// using the setTimeout function to delay updating the chart
// (didn't work, but I left it in the code, anyway.)
setTimeout(function() {updateChart(bigChart)}, 2000);
//updateChart(bigChart);
});
// NOTE: The updateChart() function is actually included in "js/chartDataFunctions.js"
function updateChart(chart) {
/*
This section of the program reads the HTML elements then uses them
to make an Ajax request to sql server, and these become the
parameters for the newDataSet() function below.
*/
newDataset(chart,firstElement,newdataset,backgroundcolor,color);
}
// NOTE: The newDataSet() function is actually included in "js/chartJSFunctions.js"
// I show it here for brevity.
// It decides which axis (y or y1) to use to plot the datasets
// the dataset is pushed into the data, and chart.update() puts it in the chart object
function newDataset(chart,label,data,bgcolor='white',color='rgb(255,255,255)') {
var maxValue = Math.max(...data);
if (Number.isNaN(maxValue)) {
return;
}
if (maxValue == 0) {
return;
}
var axisID = 'y';
var ptStyle = 'circle';
//var pStyle = 'circle';
if (maxValue < 50) {
axisID = 'y1';
bgcolor = 'white';
//ptStyle = 'Star'
}
chart.data.datasets.push({
label:label,
yAxisID:axisID,
data:data,
borderColor:color,
backgroundColor:bgcolor,
//pointStyle:ptStyle
});
chart.update();
}
});
</script>
I found a work-around that solves my problem, but I still think this is a bug in ChartJS. Before calling bigChart.destroy(), I now do two things: First, reset the data object back to it's original value, and second, reset the config object back to it's original value, THEN call bigChart.destroy().
I think the destroy() method should handle that for me, but in my case, for whatever reason, it doesn't.
So, what I have is a work-around, not really a solution, but I'll take it.
that i don't know if it's even possible. I wanna try to load content with Ajax, and animate it right away, piece by piece. I have empty body. And on server side i have document with with h1 paragraph and two images. I wanna load them with ajax with animation from different angles (left, top, right, bottom). I know how to animate but as soon as i load them they are already on the page and i want to animate them into the page. Code looks like this:
<body>
<button id="load"></button>
</body>
My jquery script
<script>
$('#load').click(function() {
callAjax();
return false;
});// end of click function
});
function callAjax() {
$.ajax({
type: "POST",
cache: false,
url: 'content.html',
success: function(data){
if(data !== ""){
$("html").prepend(data);
}
},
error: function () {
console.log('error', data);
},
complete: function () {
console.log("done"); }
}); //ajax call
} //document ready
</script>
server side data
<section class="content">
<h1>About</h1>
<p> Text</p>
<img src="ipad.png" class="rotate">
<img src="ipad1.png" class="circle">
</section>
To animate the elements you'd need more than 1 key frame. Currently you only have 1: the end-state. You'd need another one to animate from. Think of a move: to have a character walk on screen you'd have to position them off-screen first.
I'm going to assume we're doing just that: loading your content off-screen, then walking it on-screen.
Set the position for the elements (via CSS, or explicitly, but do so in the original file) off-screen. For example, use this CSS:
position: absolute;
left: -1000;
which would place the element 1000 pixels to the left of the window. That's your starting position, which is where you're going to "start" at after you have loaded the content (asynchronously).
The next part is the transition phase moving them from START to END via a series of intermediate steps computed by your code. There are many robust JS/HTML/CSS/SVG animation libraries, but I'm going to use a basic JS function: setInterval.
var thing = $('#yourThing'); // select your thing
var distInterval = 1000 / 60; // we're going to move 1000px every 60 steps
var code = function() {
thing.position().left = thing.position().left + distInterval; // move by the distance
// destination is an abs position of 100px from the left
if (thing.position().left == 100) {
window.clearInterval(); // stops the loop
}
};
var delay: 16.7; // 1/60th of a second, in ms
var intervalID = window.setInterval(code, delay); // set and start the loop
Once you are comfortable with this concept you'll soon find that this is a poor implementation choice. Some keywords to google for will be the "requestAnimationFrame()" function and the term "easings".
You could hide 'data' and then animate it in.
$(data).hide().fadeIn("slow");
Pretext: I'm using Ajax to switch between SVG images in an interactive map.
I implemented a loader image into the Ajax requests, but every time it fires the old SVG completely disappears until the new SVG is added (causing the flicker).
The goal is to get the loader image to hover over the old content instead until the new SVG is completely loaded.
AJAX
$.ajax({
type: 'POST',
url: '/doc.php',
data: { var: var },
beforeSend:function(){
$('#container').html('<div class="loader"><img src="loader.gif"/></div>');
},
success:function(data){
$('#container').empty();
$('#container').append(data);
}
});
CSS
.loader {
height:60px; width:60px;
background-color: rgba(0,0,0,0.2);
position: absolute;
top: 25%;
left: 47%;
}
Any ideas on what I'm doing wrong?
It looks like they are removing and trying to populated at the same time. If you let (data) load then .delay(1000) or what ever number works then target that old image by id you could accomplish that. Another option is this:
complete: function(data){
$('#container').append(data).delay(1000).trigger(remove);
};
Function remove(){
$('#container').find('#fooImage').fadeToggle().remove();
};
This should be enough time for the new image to load and once that 1 second is up the function 'remove' is triggered.
I'm trying to create a pie chart through the use of flot charts. I have successfully managed to create one with the following code:
HTML:
<div class="row">
<div class="col-md-6">
<div id="pie-chart"></div>
</div>
</div>
Javascript:
var data = [];
data[0] = { label: "Vertification successful", data: 9 };
data[1] = { label: "Vertification failed", data: 2 };
var series = Math.floor(Math.random() * 10) + 1;
$.plot($("#pie-chart"), data,
{
series: {
pie: {
show: true,
}
},
grid: { hoverable: true },
});
And it displays just fine.
The thing is, if I change the ID of the div element to "pie-chart1" (rather than "pie-chart")
and update the javascript accordingly:
$.plot($("#pie-chart1"), data,
I get the following error:
Uncaught Invalid dimensions for plot, width = 501, height = 0
What on earth could be causing this? I simply wanna rename the ID which apparently for some reason is impossible.
It's very likely that there is some CSS or possibly JS elsewhere on your site that expects the div to be called pie-chart. You need to ensure that it still applies to the new div. For example, if you had:
#pie-chart {
width: 400px;
height: 300px;
}
When you change the ID of the div, you need to update that reference too, or else the placeholder's height and width become undefined, which Flot cannot handle.
If your goal in adding that number is to create several charts, then you should use a class to apply the styles rather than an ID.