display a weekly Highcharts graph from php and mysql - php

I am trying to get a chart to display using Highcharts. I am pulling data from a mysql db with php and creating arrays of data and inserting them into the Highcharts Jquery.
I need to display the data in this format (not a graphical representation):
mon = 0
tues = 4
wed = 2
thu = 0
fri = 4
sat = 20
sun = 45
With Monday always being first and Sunday last.
But my data is pulled from the DB using a date range and I may only get an array from the database that looks like this:
Array
(
[0] => Array
(
[TotalClicksPerDay] => 35
[weekDay] => 4 (which is my case is Thurs)
)
}
So in this case would need to display:
(the TotalClicksPerDay is the important bit)
mon = 0
tues = 0
wed = 0
thu = 35
fri = 0
sat = 0
sun = 0
How would I add the array values to Highchart and still get the days of the week to show and position 'thu's' value in the correct place?
has anyone done anything similiar? Can you point me on the right direction?
I don't even know how to start.
Here is my highcharts Jquery just so you can see how I am using the arrays:
jQuery(document).ready(function($) {
var chart;
$(document).ready(function() {
chart = new Highcharts.Chart({
chart: {
renderTo: 'container',
type: 'column'
},
title: {
text: '$type'
},
subtitle: {
text: 'Xbox landscape'
},
xAxis: {
categories:
$categoryGraph //php array
,labels: {
rotation: 0,
align: 'center',
x: 0,
y: 20,
style: {
fontSize: '8px',
fontFamily: 'Verdana, sans-serif'
}
}
},
yAxis: {
min: 0,
title: {
text: 'Clicks'
}
},
legend: {
enabled: false
}, /*{
layout: 'Vertical',
backgroundColor: '#FFFFFF',
align: 'left',
verticalAlign: 'top',
x: 0,
y: 30,
floating: false,
shadow: true
},*/
tooltip: {
formatter: function() {
return ''+
this.x +': '+ this.y +' Clicks';
}
},
plotOptions: {
column: {
pointPadding: 0.2,
borderWidth: 0
}
},
series: [{name: '$type', data:[$clickTotalArray //php array }]
});
});
});

You are asking for how to parse your data into something that highcharts understands?
Well, the main dynamic options that you want to set correctly would be the xAxis.categories and the series.data, which you seem to have figured out already.
categories
needs to be an array of strings, nothing more or nothing less will be accepted.
eg:- categories=['Mon','Tue','Wed']
data
needs to be an array of array or array of objects or array of values. See documentation for more details
Since your data is mostly simple values, with the xValue being a string and hence falling into categories, your data object needs to be an array of numbers.
eg:- data=[100,200,300]
So now we have the final form of how your data would look like, we need to parse the available data structure/object graph into this form. You have an option to either do this in PHP or JavaScript.
This is how you can do it in javascript, make sure to do this before calling the Highchart constructor, and use the derived objects while setting the options.
var superData = [{
propertyA: 'A',
propertyB: 10
}, {
propertyA: 'B',
propertyB: 15
}, {
propertyA: 'C',
propertyB: 1
}];
var seriesData = [],
categories = [];
for (var i = 0; i < superData.length; i++) {
//you may want to do a parseInt/parseFloat it this value is a string
seriesData.push(superData[i].propertyB);
categories.push(superData[i].propertyA);
}
...
xAxis: {
categories: categories
},
series: [{
name: 'serie',
type: 'column',
data: seriesData
}]
...
Parsing complex JSON into highchart form | Highchart & Highstock # jsFiddle
Refer convert mysql resultset into a (name, data) object to be fed into HighCharts to see how a similar thing can be done in PHP

Related

Store numbers with '0' as prefix

I dont know how to tell but i still dont get it right. This is my code :
Ext.define("PL.view.list.listOnly", {
extend: 'Ext.form.Panel',
alias: 'widget.listlistonly',
config:{
fullscreen: true,
title: 'Master barang',
items:[{
xtype : 'panel',
layout: {
type: 'fit',
align : 'stretch',
pack : 'start',
},
defaults: {
allowBlank: true,
msgTarget: 'side',
labelWidth: 60,
margin: '5 5 5 5',
},
items:[{
xtype:'list',
height: '100%',
masked: { xtype: 'loadmask',message: 'Loading...' },
scrollable: {
direction: 'vertical',
directionLock: true
},
store:{
fields: [{
name:'szName',
},{
name:'szProductID',
},{
name:'szBarcode',
}],
autoLoad: true,
pageSize: 20,
proxy: {
type: 'ajax',
url: 'store/product/loadData.php',
pageParam: 'param',
reader: {
type: 'json',
rootProperty: 'topics',
}
}
},
variableHeights: false,
useComponents: true,
itemTpl: '<div class="myButton">' +
'<input type="button" name="{szProductID}" value="Edit" ' +
'style="padding:3px;">' +
'</div>' +
'<div class="myContent">'+
'<div>PLU : <b>{szProductID}</b>, Barcode: <b>{szBarcode}</b></b></div>' +
'<div>Nama: <b>{szName}</b></div>' +
'</div>',
}]
}],
scrollable : false,
},
});
And this is what i get from json :
{"topics": [{
"szProductID": 1001,
"szBarcode": 002,
"szName": "STANDARD BLACK"
},{
"szProductID": 1100420020479,
"szBarcode": 1100420020479,
"szName": "STANDARD BLUE"
}],
"totalCount": 2}
As you can see, there is a '002' (szBarcode field), and this is my problem. The list only show '2' instead of '002'. This should show '002' as szBarcode but i dont know how to fix this.
Any help would appreciate
The problem is that barcode: 002 and barcode: 2 mean exactly the same in JSON format. Prepended zeros for numbers just don't count.
There are about four different things you can possibly do.
If you can access the server code, you can change it to send you the barcode field as a string (barcode:"002").
If your barcode ALWAYS has a certain length (say 13), you can work with the number you have, and pad it to the required length again. Please be aware that after a certain length, there are precision issues because numbers are stored in fixed-length memory, while a string's memory always is as long as needed. Sample conversion code:
name:'barcode',
convert:function(value) {
var str = value.toString(),
pad = "0000000000000"; // expand to length of your number
return pad.substring(0, pad.length - str.length) + str);
}
(Bonus: This code does not break when someone does (1) afterwards...)
If you have no other barcode fields in your JSON, you could use a regular expression to add the necessary quotes to the JSON client-side before deserialization.
You could override ExtJS's default JSON serialization/deserialization code. Please note that this is not as easy as it sounds and may have quite some side effects. This is the only suitable way if you want to send barcode as zero-padded JSON numbers back to the server as well.

Changing colors of slices depended on text in the name

I am using Highchart in my page and I wonder if I can make pie chart more dynamic. I want to make slices, where specific text in the name appears, to be shades of green.
Some code:
plotOptions: {
pie: {
allowPointSelect: true,
cursor: 'pointer',
dataLabels: {
enabled: true,
color: '#000000',
connectorColor: '#000000',
formatter: function() {
return '<b>'+ this.point.name +'</b>: '+ this.y;
}
},
showInLegend: true
}
},
colors:['#89ABD5','#3b73b9','#22436b','#08a5e1',
],
series: [{
color:'#89ABD5',
type: 'pie',
name: '',
data: []
},
{
color:'#3b73b9',
type: 'pie',
name: '',
data: []
},
{
color:'#22436b',
type: 'pie',
name: '',
data: []
},
{
color:'#08a5e1',
type: 'pie',
name: '',
data: []
},
]
I have names like: GOOD A, GOOD B, GOOD C, etc.., BAD A, BAD B, BAD C, etc.. and OTHER1, OTHER2, OTHER3, etc..
What I am trying to achieve is when, there is a text GOOD in the name, the slices should be in shades of green, while BAD -> shades of red. Other slices should be by default.
Data is get through getJSON.
This answer depends on how you are generating your series data to add to the chart. Why not put some logic in the series builder to change color based on text in string? Here is some psuedo-code:
//looping through your data elements that you want to be slices.
var sliceTitle;
var sliceColor;
var sliceData = [];
sliceTitle = anElement[i].name;
sliceColor = getColorMatch(sliceTitle);
sliceData = anElement[i].dataStuff;
series[i].name = sliceTitle;
series[i].color = sliceColor;
series[i].data = sliceData;
//continue loop.
...
function getColorMatch(titleText) {
if (titleText.indexOf("GOOD") !== -1) {
return "#somegreencolor"
}
if (titleText.indexOf("BAD") !== -1) {
return "#someredcolor"
}
if (titleText.indexOf("OTHER") !== -1) {
return "#someOthercolor"
}
}
Note that this assumes you do not have cases where the title contains both strings and is case sensitive.
Other cool stuff to do would be to get a palette of greens, reds, and other colors not red or green. Then when you return the color you need have it cycle through the list of available hues for that string title match. That way you wont get all the same depending on how bad/good the values are. For the "other" you can have a palette of blues/yellows. Again, picking one from the list and only repeating if you have more slices than you have colors in your list.

kendo-ui grid date format from MySQL sql query

I have looked here for similar queries, and none quite answer my question, either in its entirety, or in a fashion I can understand.
I retrieve a string value from a MySQL database representing a datetime, i.e. "03 Oct, 2013 05:30:45PM" is represented as "20131003173045" in the database. This value is presented in a "Last Login" column in a Kendo Grid as a date. This is all contained within a PHP-oriented webpage using the MVC framework.
Previously I applied a date format in the SQL query to change the string from "20131003173045" to "03 Oct, 2013 05:30:45PM", but this gets presented in the KendoGrid as a string, meaning November Dates can appear before October dates, April dates come up first etc. This understandably is not the desired function, especially when trying to sort by this column.
Sample Code for the page rendering the KendoGrid:
<div class="div1">
<div>
<table id="listGrid"></table>
</div>
</div>
<script>
$(function() {
$("#grid").kendoGrid({
scrollable: false,
groupable: false,
sortable: {
mode: "multiple"
},
resizable: true,
pageable: true,
dataSource:
{
transport:
{
read: {
url: "<?= $site_url ?>Settings/Users/List",
dataType: "json"
},
parameterMap: function (model, operation) {
if (operation == "read") {
return model;
}
else if(model) {
return { "json" : kendo.stringify(model) };
}
else
return "";
}
},
pageSize: 20,
serverPaging: true,
serverSorting: true,
sort: { field: "LastLogin", dir: "desc" },
serverGrouping: true,
serverAggregates: false,
schema: {
total: "total",
data: "data",
groups: "groups"
}
},
toolbar: [ { title: "", template:'<a class="k-button k-button-icontext k-grid-add" href="<?= $site_url ?>Settings/Users/Add/">Add New User</a>' }],
columns: [
//{field: "Id", width: "40px"},
{field: "UserName", title: "Alias", width: "160px"},
{field: "ForeName", title: "Forename", width: "100px"},
{field: "SurName", title: "Surname", width: "160px"},
{field: "Initials", width: "80px"},
{field: "CrmId", title: "CRM ID", width: "100px"},
{field: "Dept", title: "Department", width: "100px"},
{field: "Position"},
// Below is the field in question
{field: "LastLogin", title: "Last Login", width: "160px"},
{field: "BlockedStatus", title: "Status", width: "90px"},
{ title: "", template:'<a class="k-button k-button-icontext k-grid-edit" href="<?= $site_url ?>Settings/Users/Update/#: Id #">Edit</a>' }
]
});
});
</script>
I've looked at the kendo.parseDate and kendo.toString, and combining the two, but can't seem to get anything to work; I either get "null" or "20131003173045", or the page doesn't load.
I can't change the database data, I can only format it as part of the SQL query, which is what I was doing initially.
I need the whole "20131003173045" string to become "03 Oct, 2013 05:30:45PM", and still be ordered in proper chronological order - how can I do this, and if the kendo.parseDate and kendo.toString are the correct tools to use, what am I doing wrong?
What I suggest is implement a schema.parse function that converts that MySQL format to a Date object and then use columns.format for formatting it.
The Schema would be:
schema : {
data : "data",
total : "total",
groups: "groups",
parse : function (d) {
$.each(d.data, function (idx, elem) {
elem.LastLogin = kendo.parseDate(elem.LastLogin, "yyyyMMddHHmmss");
});
return d;
}
}
Now, the columns definition for printing the date would define a format that is the one that you want.
{field: "LastLogin", title: "Last Login", width: "160px", format: "{0:dd MMM, yyyy hh:mm:sstt}" }},

Javascript, using Highcharts to display a chart of rankings with JSON Data

I am trying to use javascript Highcharts to display a chart of rankings from JSON data. I can't seem to get the chart to display.
This is the javascript code:
$(document).ready(function() {
var options = {
chart: {
renderTo: 'drawing',
zoomType: 'x',
width: 900,
height: 222
},
exporting: {
enabled:true
},
title: {
text: url+' - '+keyword
},
credits: {
text: '****',
href: 'http://***/'
},
xAxis: {
type: 'datetime',
dateTimeLabelFormats: {
day: '%b %e '
}
},
yAxis: [{
//min: 1,
allowDecimals: false,
reversed: true,
///: .2,
//maxPadding: .2,
title: {
text: 'Rankings'
}
},],
tooltip: {
crosshairs: true,
shared: true
},
series: [{}]
};
var url = "http://*******/chart.php";
$.getJSON(url, function(data) {
$.each(data, function(arrayID,group) {
$.each(group.data, function(id,val) {
arg = val[0].replace(/Date.UTC\((.*?)\)/, '$1').split(',');
var timestamp = Date.UTC.apply( null , arg );
date=new Date(timestamp);
data[arrayID].data[id][0] = timestamp;
});
});
options.series[0].data = data;
var chart = new Highcharts.Chart(options);
});
});
Our PHP Script gives us this JSON:
[{"name":"Google Rank","data":[["Date.UTC(2013,04,05)","23"],["Date.UTC(2013,04,04)","23"],["Date.UTC(2013,04,03)","22"],["Date.UTC(2013,04,02)","24"],["Date.UTC(2013,04,01)","26"],["Date.UTC(2013,03,31)","24"],["Date.UTC(2013,03,30)","24"],["Date.UTC(2013,03,29)","25"],["Date.UTC(2013,03,28)","25"],["Date.UTC(2013,03,27)","25"],["Date.UTC(2013,03,26)","26"],["Date.UTC(2013,03,25)","25"],["Date.UTC(2013,03,24)","24"],["Date.UTC(2013,03,23)","-"],["Date.UTC(2013,03,22)","10"],["Date.UTC(2013,03,21)","10"],["Date.UTC(2013,03,20)","10"],["Date.UTC(2013,03,19)","10"],["Date.UTC(2013,03,18)","10"],["Date.UTC(2013,03,17)","10"],["Date.UTC(2013,03,16)","9"],["Date.UTC(2013,03,15)","9"],["Date.UTC(2013,03,14)","9"],["Date.UTC(2013,03,13)","9"],["Date.UTC(2013,03,12)","9"]],"visible":"true","pointInterval":"86400000","showInLegend":"false"},{"name":"Bing Rank","data":["Date.UTC(2013,2,9)",9],"visible":"true","pointInterval":"86400000","showInLegend":"false"}]
Note the JSON data represents numbers as strings which could be a problem.
PHP Code which generates the JSON data:
$googledata = array();
while($gkdata = mysql_fetch_assoc($keywordquery)){
$explodedate = explode("-", $gkdata['date']);
$year = $explodedate[0];
$month = $explodedate[1];
$day = $explodedate[2];
$googledata[] = array(
"".$year.",".$month.",".$day."",
$gkdata['grank'] //$gkdata['grank'] should be a number, but is sometimes a dash so it's cast to an accommodating datatype: string.
);
}
$chartdata = array(
array(
"name" => 'Google Rank',
"data" => $googledata,
"visible" => 'true',
"pointInterval" => '86400000',
"showInLegend" => 'false',
),
array(
"name" => 'Bing Rank',
"data" => array(
'Date.UTC(2013,2,9)',
9
),
"visible" => 'true',
"pointInterval" => '86400000',
"showInLegend" => 'false',
)
);
The Highcharts won't display anything other than the chart itself with no data. The Date.UTC(2013,03,12) is supposed to go on the X-Axis & the number next to it is supposed to be the rank number. Can anyone see what is wrong?
The chart takes data as [x,y]. You just need to reverse the order of your data to ['value',datestamp'] if you want the date to be on the y axis.
Edit:
I am not sure from the text what the problem you are having is, but one problem that will arise from your code is that your number data values are being returned as strings, in quotes.
You will need to cast them as integers in your php before json encoding in order for them to come through unquoted, as integers.
You should be seeing an error from this: http://www.highcharts.com/errors/14
You are expecting $gkdata['grank'] to always return a number, it sometimes returns a dash -. The Array Object is using the datatype which best represents the data, and it chooses string. If you want to force it as int, you'll have to use a data structure that only allows integers to be put in it. Then it will puke when you try to put in a dash, which it should be doing, because how do you plot a DASH on a chart?
Had you taken off your blindfold, and looked at the error HighCharts returned to you, you would see this:
Highcharts Error #14 String value sent to series.data, expected Number
This happens if you pass in a string as a data point, for example in a setup like this:
series: [{
data: ["3", "5", "1", "6"]
}]
Highcharts expects the data values to be numbers. The most common reason for this is that data is parsed from CSV or from a XML source, and the implementer forgot to run parseFloat on the parsed value.
For performance reasons internal type casting is not performed, and only the first value is checked (since 2.3).
So fix your code to make grank always a number. HighCharts won't plot strings for performance reasons.

Highcharts Issue - Labelling Y-Axis Based Series Data

I have an issue regarding highcharts...
Consider the example relation:
Data
-----
Id(pk)
Date date
Data varchar(50)
This relation contains data. It is important to note that the date is non-contiguous...i.e. data isn't entered everyday. An example table may be
Data
-----
Id Date Data
1 2011-08-22 SomeData
2 2011-08-29 MoreData
I present users with an HTML/jQuery interface, where data can be pulled from the database and graphed using highcharts. This works well:
http://dev.speechlink.co.uk/David/fifthiteration/dbgrapher.php
I use the following jQuery to label the x-axis:
xAxis: {
type: 'datetime',
maxZoom: 14 * 24 * 3600000, // fourteen days
lineWidth: 1,
lineColor: '#999999',
title: {
text: 'Date'
}
}
And this is for the series:
series: [{
type: 'spline',
name: data.questionTitle,
pointInterval: 24 * 3600 * 1000,
pointStart: Date.UTC(data.year, data.month, data.day),
data: cdata,
lineColor: '#f6a828',
color: '#418ed6'
}]
Now this works fine bar ONE problem -> all points are plotted as if they are done on successive days...This is not the case...For example, if in my table I have data submitted on the 24th and then no data until the 29th....the data on the 29th is incorrectly placed as data submitted the 25th...
This is obviously to do with this series argument:
**pointInterval: 24 * 3600 * 1000,**
My data comes in like this:
[23rd, 24th, 25th, 29th]
Whereas it should probably be something like:
[23rd, 24th, 25th, null, null, null, 29th]
I am not sure if the above is correct syntax..thats is why I am here...how do you tell highcharts to skip a point, but keep the same pointintervals....
EDIT:
I see on highcharts you can pass data like so:
var chart = new Highcharts.Chart({
chart: {
renderTo: 'container'
},
xAxis: {
type: 'datetime'
},
series: [{
data: [
[Date.UTC(2010, 0, 1), 29.9],
[Date.UTC(2010, 2, 1), 71.5],
[Date.UTC(2010, 3, 1), 106.4]
]
}]
});
Is there a way to pass a php array in the correct format to the series above (i.e. with a data and associated value)..
If you dont have data points for an interval then you can specify as null in the series. You can try [23rd, 24th, 25th, null, null, null, 29th] it will perfectly work.

Categories