Feeding highchart with x and y values from ajax - ajax

I'm trying to feed my highchart from a database using ajax. From my ajax request, I want to return both x and y values (the x value is like that: year-week, ie 2020-16; the y value is a random number). My chart remains blank, I have a silent error that I cannot figure out. I'm pretty sure it comes from the strucure of the data returned by ajax, but I can't seem to fix it on my own.
Here's my javascript:
var weekOptions = {
chart: {
renderTo: 'weekContainer',
type: 'column',
},
title: {
text: 'Last 52 weeks',
},
credits: {
enabled: false,
},
xAxis: {
lineWidth: .5,
tickWidth: 1,
tickLength: 10,
},
yAxis: {
title: {
text: 'Distance (miles)'
},
labels: {
formatter: function() {
return this.value;
},
},
allowDecimals: false,
gridLineWidth: 1,
},
tooltip: {
crosshairs: true,
split: true,
useHTML: true,
valueDecimals: 2,
valueSuffix: ' miles',
formatter: '',
},
plotOptions: {
spline: {
marker: {
symbol: "circle",
radius: 3,
}
}
},
lang: {
noData: "No Data. Make sure at least one activity type is selected."
},
noData: {
style: {
fontWeight: 'bold',
fontSize: '15px',
color: '#303030'
}
},
exporting: {
buttons: {
contextButton: {
menuItems: ['viewFullscreen']
}
},
},
series: [{}],
};
//get series from ajax filtered by activity types
$.ajax({
url: "weekGetSeries.php",
type: "POST",
data: {
activityType: activityTypeSelected,
dataToDisplay: dataToDisplay,
},
dataType: "JSON",
success: function (json) {
weekOptions.series = json;
var chart = new Highcharts.Chart(weekOptions);
}
});
And here my ajax php file:
<?php
require 'dbConnection.php';
$activityType = array(1,2,3,4,5);
$dataToDisplay = "distance";
$startingDate = date('Y-m-d', strtotime('-52 week', time()));
$firstWeek = strtotime($startingDate);
$conditionActivityType = ' WHERE startingTime >= "' . $startingDate . '" AND (type=' . implode(" OR type=",$activityType) . ')';
$dataSerie = array("name" => "Weekly Stats","data" => array());
for($i = 0; $i < 52; $i++){
$nextWeek = strtotime('+'.$i.' week', $firstWeek);
$dataSerie["data"][date("o",$nextWeek) . "-" . date("W",$nextWeek)] = 0;
}
$getActivities = $conn->query("SELECT * FROM activity" . $conditionActivityType . " ORDER BY startingTime ASC");
if ($getActivities->num_rows > 0) {
while($row = $getActivities->fetch_assoc()) {
$date = substr($row["startingTime"],0,10);
$date = strtotime($date);
$week = date("W",$date);
$category = date("Y-",$date).$week;
$distance = ($row["distance"]);
$movingTime = $row["movingTime"];
$elapsedTime = $row["elapsedTime"];
$totalElevationGain = ($row["totalElevationGain"])*3.28084;
switch ($dataToDisplay) {
//distance
case "distance":
$dataSerie["data"][$category] += $distance;
break;
//Moving Time
case "movingTime":
break;
//Elapsed Time
case "elapsedTime":
break;
//elevation gain
case "totalElevationGain":
break;
//number activities
case "activities":
break;
}
}
};
$data = array();
array_push($data,$dataSerie);
echo json_encode($data);
?>
My ajax returns this:
[{"name":"Weekly Stats","data":{"2019-17":13184.4,"2019-18":73560.2,"2019-19":36899.4,"2019-20":0,"2019-21":38691.3,"2019-22":165127.8,"2019-23":188163.2,"2019-24":12888.5,"2019-25":60011.3,"2019-26":32585.2,"2019-27":12952.8,"2019-28":7944.8,"2019-29":79258.3,"2019-30":60885.2,"2019-31":0,"2019-32":0,"2019-33":0,"2019-34":0,"2019-35":0,"2019-36":0,"2019-37":30974.6,"2019-38":7766.5,"2019-39":7685,"2019-40":21128.7,"2019-41":28996,"2019-42":46362.6,"2019-43":0,"2019-44":0,"2019-45":63694.8,"2019-46":81551.1,"2019-47":104595.9,"2019-48":18121.7,"2019-49":18691.6,"2019-50":37538,"2019-51":40671.8,"2019-52":22109.6,"2020-01":22079,"2020-02":22086.7,"2020-03":21933.2,"2020-04":30702.1,"2020-05":58259,"2020-06":38811.3,"2020-07":43754,"2020-08":45109.1,"2020-09":50870.1,"2020-10":62917.8,"2020-11":0,"2020-12":95912.5,"2020-13":20836.2,"2020-14":25293,"2020-15":110540.5,"2020-16":150804.9}}]
How do I structure my data so I can feed my chart?

In your case series.data needs to be an array of arrays or an array of objects. Now it is an object.
data: [
[0, 6],
[1, 2],
[2, 6]
]
Or:
data: [{
x: 1,
y: 9
}, {
x: 1,
y: 6
}]
Live demo: http://jsfiddle.net/BlackLabel/6m4e8x0y/4977/
API Reference: https://api.highcharts.com/highcharts/series.column.data

Related

How to sort time column in jsgrid?

We are binding a table using jqgrid. We have the first column start as a time column with a 12-hour format. We are facing an issue with sorting this data. The data is sorted correctly but it is not taking am/pm into consideration. Below is our code for binding the jqgrid:
var newFieldsArray =
[
{ name: "ID", title: "ID", type: "number", width: "50px", visible: false },
{
name: "TimeStart", title: "Start", type: "customTime", width: "100px", validate: "required",
sorttype: "date",
formatter : {
date : {
AmPm : ["am","pm","AM","PM"],
}
},
// datefmt: "m/d/Y h:i A",
//sorttype: 'datetime', formatter: 'date', formatoptions: {newformat: 'd/m/y', srcformat: 'Y-m-d H:i:s'},
insertTemplate: function () {
var $result = jsGrid.fields.customTime.prototype.insertTemplate.call(this); // original input
$result.val(varendTime);
return $result;
},
itemTemplate: function (value, item) {
return "<b style='display:none'>" + Date.parse(item.StartDate) + "</b><span>" + (item.TimeStart) + "</span>";
}
},
{
name: "TimeEnd", title: "End", type: "customTime", width: "100px", validate: "required",sorttype: "date", datefmt: "h:i"
},
{ name: "TimeTotal", title: "Time", type: "text", width: "50px", readOnly: true },
{
name: "CoilPO", title: "Coil PO", type: "text", width: "50px", validate: "required",
insertTemplate: function () {
var $result = jsGrid.fields.text.prototype.insertTemplate.call(this); // original input
$result.val(varlot);
return $result;
}
},
{ name: "Joints", title: "Joints", type: "integer", width: "60px" },
{ name: "CommercialGrade", title: "Commercial Grade", type: "integer", width: "80px" },
{ name: "QAHold", title: "QA Hold", type: "integer", width: "60px" },
{ name: "Rejected", title: "Reject", type: "integer", width: "60px" },
{ name: "ActionTaken", title: "Reason of Delay / Action Taken", type: "text", width: "120px" },
{
name: "ClassId", title: "Class",
type: "select", items: classDataArr,//classData.filter(function(n){return classdt.indexOf(n.Id) != -1 }),//classData,
valueField: "Id", textField: "Title",
insertTemplate: function () {
debugger;
var taxCategoryField = this._grid.fields[12];
var $insertControl = jsGrid.fields.select.prototype.insertTemplate.call(this);
var classId = 0;
var taxCategory = $.grep(voiceData, function (team) {
return (team.ClassId) === classId && (team.StationId) == parseInt($('#ddlEquipmentName').val());
});
taxCategoryField.items = taxCategory;
$(".tax-insert").empty().append(taxCategoryField.insertTemplate());
$insertControl.on("change", function () {
debugger;
var classId = parseInt($(this).val());
var taxCategory = $.grep(voiceData, function (team) {
return (team.ClassId) === classId && (team.StationId) == parseInt($('#ddlEquipmentName').val());
});
taxCategoryField.items = taxCategory;
$(".tax-insert").empty().append(taxCategoryField.insertTemplate());
});
return $insertControl;
},
editTemplate: function (value) {
var taxCategoryField = this._grid.fields[12];
var $editControl = jsGrid.fields.select.prototype.editTemplate.call(this, value);
var changeCountry = function () {
var classId = parseInt($editControl.val());
var taxCategory = $.grep(voiceData, function (team) {
return (team.ClassId) === classId && (team.StationId) == parseInt($('#ddlEquipmentName').val());
});
taxCategoryField.items = taxCategory;
$(".tax-edit").empty().append(taxCategoryField.editTemplate());
};
debugger;
$editControl.on("change", changeCountry);
changeCountry();
return $editControl;
}
},
{
name: "VoiceId", title: "Voice", type: "select", items: voiceData,
valueField: "Id", textField: "Title", width: "120px", validate: "required",
insertcss: "tax-insert",
editcss: "tax-edit",
itemTemplate: function (teamId) {
var t = $.grep(voiceData, function (team) { return team.Id === teamId; })[0].Title;
return t;
},
},
{ name: "Remarks", title: "Remarks", type: "text", width: "110px" },
{ name: "control", type: "control" }
];
hoursGrid.jsGrid("option", "fields", newFieldsArray);
Below is two screenshots of data that appear when we sort:
Can someone tell me what we are doing wrong?
You're mixing up jsGrid and jqGrid. The way to achieve it in jsGrid is using the built-in sorter jsGrid.sortStrategies.date, I added an example below.
As commented by #Tomy Tomov (the creator of jqGrid), you're using jsGrid, not jqGrid. This is evident both by your code and by the UI in the screenshot.
Specifically, you took the date sorter of jqGrid and used it in your jsGrid code, but (of course) it's not supported there. You can go ahead and look in jsGrid source for AmPm which you used - and see it's not there.
So how to do it in jsGrid?
Just pass the built-in sorter jsGrid.sortStrategies.date to the sorter property. However, it does require Date objects, so if you only got time strings, you'll have to convert those to dates.
Below is a quick demo (jsfiddle), click the date column title to sort:
Note that getData gets a function parameter that is responsible to get all data as Date objects, and that the value of isUTC depends on whether you actually use it
$(document).ready(function () {
const dataFunc = getDataTimes;
$("#jsGrid").jsGrid({
width: "100%",
data: getData(dataFunc),
sorting: true,
fields: [{
name: "name",
type: "text",
width: 50
}, {
name: "date",
type: "date",
width: 50,
sorter: jsGrid.sortStrategies.date,
cellRenderer: (value, item) => {
const withYear = false;
const isUTC = dataFunc == getDataTimes;
return renderDateTime(value, item, withYear, isUTC);
}
}
]
});
});
function getData(getDates) {
const data = [
{name: "a"}, {name: "b"}, {name: "c"},
{name: "d"}, {name: "e"}, {name: "f"},
];
const dates = getDates();
for (let i = 0; i < dates.length; i++) {
data[i].date = dates[i];
}
return data;
}
function getDataDates() {
const date1 = new Date(2022, 10, 1, 4, 50);
const date2 = new Date(2022, 10, 1, 8, 50);
const date3 = new Date(2022, 10, 1, 15, 50);
const date4 = new Date(2021, 10, 1, 4, 50);
const date5 = new Date(2021, 10, 1, 8, 50);
const date6 = new Date(2021, 10, 1, 15, 50);
return [date1, date2, date3, date4, date5, date6];
}
function getDataTimes() {
const time1 = "3:50 AM";
const time2 = "8:50 AM";
const time3 = "4:50 AM";
const time4 = "3:50 PM";
const time5 = "8:50 PM";
const time6 = "4:50 PM";
const times = [time1, time2, time3, time4, time5, time6];
return times.map(t => convertTime12to24(t));
}
function convertTime12to24(time12h) {
const [time, modifier] = time12h.split(' ');
let [hours, minutes] = time.split(':');
if (modifier === 'PM') {
hours = parseInt(hours, 10) + 12;
}
return new Date(Date.UTC(2022,0,1,hours, minutes));
}
function renderDateTime(value, row, withYear, isUTC) {
return `<td>${getDateTimeAsString(value, withYear, isUTC)}</td>`;
}
function getDateTimeAsString(date, withYear, isUTC) {
var options = {
hour: 'numeric',
minute: 'numeric',
hour12: true
};
if (withYear) {
options.withYear = 'numeric';
}
if (isUTC) {
options.timeZone = 'UTC';
}
return date.toLocaleString('en-US', options);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jsgrid/1.5.3/jsgrid.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.13.2/jquery-ui.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/jsgrid/1.5.3/jsgrid-theme.min.css" rel="stylesheet">
<link href="https://cdnjs.cloudflare.com/ajax/libs/jsgrid/1.5.3/jsgrid.min.css" rel="stylesheet">
<div id="jsGrid" class="jsgrid"></div>
Let me give it a try, we have 2 options to perform Sorting operation in JsGrid:
1.Custom Field (Topic Name you can refer below link)
Reference Link :http://js-grid.com/docs/#grid-fields
In this, you can define custom property in your config and extend it.
You can use sorter property and call your user defined function werein you can logic to sort date with time stamps directly.
2.Sorting Strategies (Topic Name you can refer below link)
Reference Link :http://js-grid.com/docs/#grid-fields
In this, you can create your custom objects and then apply sorting strategies of date directly on to the object to perform sorting operation as per your logic.

Codeigniter Full Calendar Integration

I used full calendar in my CodeIgniter project to manage events. All other parts of the project are working properly. But the calendar output is look like this :
The dates are collapsed in the output. Relevant JavaScript for calendar as follows :
<Script>
$(document).on('click', '.month_select', function() {
var month = $(this).data('month');
var moment = $('#calendar').fullCalendar('getDate');
var currentMonth = moment.format('YYYY') + '-' + month + '-' + 10;
$('#calendar').fullCalendar('gotoDate', currentMonth);
});
$(function() {
$('#viewed,#new,#issued,#recieved,#request,#return, #requestProofs').on('ifChanged', function(event) {
$('#calendar').fullCalendar('refetchEvents');
});
var date = new Date();
var d = date.getDate(),
m = date.getMonth(),
y = date.getFullYear();
$('#calendar').fullCalendar({
aspectRatio: 1.7,
firstDay: 1,
header: {
left: 'prev,next today',
center: 'title',
right: 'month,agendaWeek,agendaDay',
},
allDay: true,
buttonText: {
today: 'today',
month: 'month',
week: 'week',
day: 'day'
},
events: {
url: "<?= site_url('document/getImprestDocuments') ?>",
data: function() {
return {
viewed: $('#viewed').is(':checked'),
new: $('#new').is(':checked'),
issued: $('#issued').is(':checked'),
recieved: $('#recieved').is(':checked'),
request: $('#request').is(':checked'),
requestProofs: $('#requestProofs').is(':checked'),
return: $('#return').is(':checked'),
};
},
error: function() {
$('#script-warning').show();
}
},
eventClick: function(event) {
if (event.url) {
window.open(event.url);
event.color = event.default_color;
$('#calendar').fullCalendar('updateEvent', event);
return false;
}
},
eventRender: function(event, element) {
},
loading: function(bool) {
if (bool) {
$(this).block({
message: '<div class="loading-message"><h3 style="margin: 5px;"><img style="width:35px;" src="<?= base_url() ?>public/dist/img/ring-alt.gif" > Processing...</h3></div>',
cenrerY: true,
css: {
border: '3px solid rgb(221, 75, 57)'
}
});
} else {
$(this).unblock();
}
}
});
});
$(document).ready(function() {
var table = $("#request_imprest").DataTable({
"order": [
[1, "desc"]
],
columnDefs: [{
sortable: false,
"class": "index",
targets: 0
}]
})
table.on('order.dt search.dt', function() {
table.column(0, {
search: 'applied',
order: 'applied',
}).nodes().each(function(cell, i) {
cell.innerHTML = i + 1;
});
}).draw();
})
</script>
url: "<?= site_url('document/getImprestDocuments') ?>" is also working fine. What may be going wrong ? Can anyone help ?

setData Series Highchart using Ajax and CodeIgniter

I want to redraw and update data Highcart based on click button with ajax. This code still not working.
$('#chartday').on('click', function() {
$('#my_start_date').datepicker();
$('#my_end_date').datepicker();
var p_id_resto = $('#p_id_resto').val();
var start_date = $('#my_start_date').val();
var end_date = $('#my_end_date').val();
var idResto = JSON.stringify(p_id_resto);
var startDate = JSON.stringify(start_date);
var endDate = JSON.stringify(end_date);
var base_url = '<?php echo base_url();?>main2nd/charts_day';
console.log('get Id resto = ' + idResto);
console.log('get Start date = ' + startDate);
console.log('get URL = ' + base_url);
$.ajax({
url: base_url,
type: 'POST',
dataType: "json",
data : {p_id_resto : idResto,
start_date : startDate,
end_date : endDate},
}).done(function(result) {
console.log(result.data_stock);
chart.series[0].setData(['BD', result.data_stock['BD']],
['BDF',result.data_stock['BDF']],
['BP',result.data_stock['BP']],
['BPF',result.data_stock['BPF']],
['AD',result.data_stock['AD']],
['ADF',result.data_stock['ADF']],
['AP',result.data_stock['AP']],
['APF',result.data_stock['APF']],
['SB',result.data_stock['SB']],
['SRW',result.data_stock['SRW']], false
);
});
});
});
This my series highchart:
var chart = Highcharts.chart('reportChart', {
chart: {
type: 'column'
},
title: {
text: ''
},
subtitle: {
text: ''
},
series: [{
name: 'STOCK',
color: "#2a82ff",
data: [],
dataLabels: {
enabled: true,
color: '#045396',
align: 'center',
formatter: function() {
return Highcharts.numberFormat(this.y, 0);
},
y: 0,
style: {
fontSize: '13px',
fontFamily: 'Verdana, sans-serif',
position: 'relative'
}
}
},
{
name: 'SALES',
color: "teal",
data: []
}]
}
This My controller
function charts_day(){
$n_id_resto= json_decode($this->input->post('p_id_resto'));<br/>
$start_date= json_decode($this->input->post('start_date'));<br/>
$end_date= json_decode($this->input->post('end_date'));<br/>
$data1['data_sales'] = $this->Model_All->getSumSales($n_id_resto, $start_date, $end_date);<br/>
$data2['data_stock'] = $this->Model_All->charts_stokCbg($n_id_resto,$start_date, $end_date);<br/>
$dataMerge = array_merge($data1, $data2);$this->output->set_content_type('application/json')->set_output(json_encode($dataMerge),JSON_NUMERIC_CHECK);
}
Data still not display correctly in highchart.
I am sure using comment above
$this->output->set_content_type('application/json')->set_out‌​put(json_encode($dat‌​aMerge,JSON_NURIC_‌​CMEHECK));
you will get
Object { BD: 8, BDF: 10, BP: 10, BPF: 10, AD: 10, ADF: 10, AP: 10, APF: 10, SB: 10, SRW: 10 }
Now you have to process data as required by highcharts
var data={ BD: "8", BDF: "10", BP: "10", BPF: "10", AD: "10", ADF: "10", AP: "10", APF: "10", SB: "10", SRW: "10" }
var series_data=[]; //creating empty array for highcharts series data
Object.keys(data).map(function(item, key) {
series_data.push({name:item,y:Number(data[item])}) ; //Number(data[item]) converts string to number.Not required if already done using JSON_NUMERIC‌​_CHECK
});
console.log(series_data);// check how data is formed. you can do same in php by creating object array in php
Fiddle demonstration

Chartjs2 Legend Not working

I'm trying to plot a lineal graphic that gets data from ajax using Chartjs 2.5.
This is the main function for this procedure. The main problem is that the legend doesn't appear.
function initDigitalValueChart(divName, ids) {
if ($(divName)) {
/*for (var j=0; j<ids.length; j++) {
console.log(j);
datasetValue[j] = {
fillColor: 'rgba(220,220,220,0.5)',
strokeColor :'rgba(220,220,220,1)',
title :'2013',
data : [Math.round(Math.random() * 1),Math.round(Math.random() * 1)]
}
}*/
var datasetValue = [];
var calls = [];
for (var j = 0; j < ids.length; j++) {
var labels = []
URL = "*****" + ids[j];
calls.push($.getJSON(URL, function(response) {
var values = []
if (response != null) {
$.each(response, function(index, data) {
labels.push(data["timestamp"]);
values.push(data["value"]);
title = data["sensorName"]
});
datasetValue.push({
label: title,
lineTension: 0,
borderColor: "rgba(" + Math.floor(Math.random() * 255) + ", " + Math.floor(Math.random() * 255) + ", " + Math.floor(Math.random() * 255) + ", 0.70)",
backgroundColor: "transparent",
data: values,
radius: 0,
pointHitRadius: 0,
steppedLine: true,
});
}
}))
}
$.when.apply($, calls).then(function() {
var ctx = document.getElementById('digital').getContext("2d");
var lineChart = new Chart(ctx, {
type: 'line',
data: {
labels: labels,
datasets: datasetValue
},
options: {
legend: {
display: true,
labels: {
fontColor: "white",
fontSize: 18
}
},
scales: {
xAxes: [{
display: true,
scaleLabel: {
display: true,
labelString: 'Data Hora'
}
}],
yAxes: [{
display: true,
scaleLabel: {
display: true,
labelString: 'Valor'
}
}]
}
}
});
//document.getElementById('digital-legend').innerHTML = lineChart.generateLegend();
});
}
}
I tried to add the position: 'top' option but in this case the console returns
Uncaught TypeError: Cannot read property 'call' of undefined
Has anyone else had problems with this?

How to plot 500 points in a second in highchart?

We are supposed to plot 500 points every second from ajax request which we get it from WCF service(hosted in amazon cloud).
We are using highchart, but its very slow.
Is there any solution ? or any other graph control which we can use it in our case so that performnace is efficient
var chart = new Highcharts.Chart({
chart: {
type: 'spline',
animation: false,//Highcharts.svg, // don't animate in old IE
marginRight: 10,
renderTo: 'Chart',
events: {
load: function () {
}
}
},
title: {
text: 'Data'
},
xAxis: {
type: 'datetime',
tickPixelInterval: 150,
max: ((new Date()).getTime()) + 50 * 10000
},
yAxis: {
title: {
text: 'Data',
min: 50,
max: 500
},
plotLines: [{
value: 0,
width: 1,
color: '#FFFF00'
}]
},
plotOptions: {
line: {
marker: {
enabled: false
}
}
},
tooltip: {
},
legend: {
enabled: false
},
exporting: {
enabled: false
},
plotOptions: {
series: {
marker: {
enabled: false
}
}
},
series: [{
name: 'Chart',
color: '#335de8',
//data: []
data: (function () {
//generate an array of random data
var data = [];
var data = [],
time = (new Date()).getTime(), i;
for (i = 1; i <= 0; i++) {
data.push({
x: time + i * 1000,
y: null
});
}
return data;
})()
}]
});
chart.yAxis[0].setExtremes(-200, 500);
UpdateChart();
function UpdateChart() {
var Chrt = chart.series[0];
setInterval(function () {
$.ajax({
url: 'getChartData/',
cache: false,
type: "POST",
success: function (result) {
for (var tmpJ = 0; tmpJ < result.length; tmpJ++) {
Chrt.addPoint([(new Date()).getTime(), eval(result[tmpJ])], true, false);
Chrt.redraw(false);
}
});
}, 1000);
}
Try to replace this line
Chrt.addPoint([(new Date()).getTime(), eval(result[tmpJ])], true, false);
with
if(tmpJ==result.length-1){
Chrt.addPoint([(new Date()).getTime(), eval(result[tmpJ])], false, false);
} else {
Chrt.addPoint([(new Date()).getTime(), eval(result[tmpJ])], true, false);
}

Resources