I am using PHP and MySQL to get total amount of orders made on each day during a selected time period and then save them in a *.csv file using PHP. I generate the chart from csv file and everything is ok but I would need to include days with no orders made as well. *.csv file content is something like that:
1,05-01
1,05-02
2,05-04
1,05-06
So on the chart they appear as 1 order made on 1st of May, 1 order made on 2nd of May and then 3rd of May is skipped- I need to show it on the chart with value 0. Can it be done with jQuery/highcharts (I don't have much experience with javascript) or should I edit the PHP to create file with those values, like this:
1,05-01
1,05-02
0,05-03
2,05-04
0,05-05
1,05-06
I use the following PHP code to save the file:
$result = mysqli_query($con,"$query");
$fp = fopen('data/temp.csv', 'w');
if ($fp && $result) {
while ($row = $result->fetch_array(MYSQLI_NUM)) {
fputcsv($fp, array_values($row));
}
}
And the following script to generate the chart:
var myCategories = [];
var myData = [];
var myChart;
$(document).ready(function() {
var options = {
chart: {
renderTo: 'chart-container',
defaultSeriesType: 'column'
},
title: {
text: 'Orders received in selected days'
},
xAxis: {
title: {text: 'Date'},
categories: []
},
yAxis: {
title: {
text: 'Orders'
}
},
series: []
};
$.get('data/temp.csv', function(data) {
var lines = data.split('\n').slice(0, -1); //generated csv file has \n after last entry so there is always an empty line I have to delete
$.each(lines, function(lineNo, line) {
var items = line.split(',');
myCategories.push(items[1]);
myData.push(parseInt(items[0]));
});
options.xAxis.categories = myCategories;
options.series = [{ data: myData }];
myChart = new Highcharts.Chart(options);
});
});
Only solution I found was to create some crazy query on MySQL side (I preffer to handle that logic in PHP) it seems this cannot be done with HighCharts, so in the end I modified my PHP code a little bit to add some extra loops. If someone is interested it now looks like this:
$result2 = mysqli_query($con,"$query2");
$fp = fopen('data/temp.csv', 'w');
$dayCompare=date("n-d", strtotime($theDay)); //I know which day is the first one selected so I save it as variable #theDay
while ($row = mysqli_fetch_array($result2)) {
if ($row['Date'] !== $dayCompare){
while ($row['Date'] !== $dayCompare){ //This "while" keeps on looping till the date from database matches the day
fputcsv($fp, array('0,'.$dayCompare));
$theDay= date("Y/m/d", strtotime($theDay . "+1 day"));
$dayCompare=date("n-d", strtotime($theDay));
}
} //Rest of the code is to be executed when dates match
fputcsv($fp, array($row['Orders'].",".$row['Date']));
$theDay= date("Y/m/d", strtotime($theDay . "+1 day"));
$dayCompare=date("n-d", strtotime($theDay));
}
for ($theDay; $theDay <= $lastDay; strtotime($theDay . "+1 day")) { //I added a "for" loop to fill in the empty days if the day of last order is earlier than the last day selected/current day.
fputcsv($fp, array('0,'.$dayCompare));
$theDay= date("Y/m/d", strtotime($theDay . "+1 day"));
$dayCompare=date("n-d", strtotime($theDay));
}
This produces sample output:
"1,5-01"
"1,5-02"
"0,5-03"
"2,5-04"
"0,5-05"
"1,5-06"
The only problem that it gives me now the data is saved in the *.csv file with quotes, but I solved it by modifying the *.js file with my script changing this part:
$.each(lines, function(lineNo, line) {
var items = line.split(',');
myCategories.push(items[1]);
myData.push(parseInt(items[0]));
});
To this:
$.each(lines, function(lineNo, line) {
var items = line.split(',');
myCategories.push(items[1].replace(/"/g,""));
myData.push(parseInt(items[0].replace(/"/g,"")));
});
Thanks to trimming the quote marks the output is as expected. Variables with dates are still quite elaborated but it seems it has to be like that since PHP has problems recognizing short dates when it is about doing math equations, and I also hope to modify that triple loop someday but this will have to wait at least till next deployment.
In the end I added one more loop to loop through the empty days when the last day selected is later than the day of last order, for example if 9th of May was selected and last order was on 7th there will be 2 lines added with 0 values for 8th and 9th.
Related
I have a table and some <td> have a data, but not all of them. On a button click I run jQuery function which checks each <td> and where the data is present, grabs the data.
After that the data is being passed to php file and inserted into my DB. Everything works great.
function insert_data() {
if(confirm("\nAre you sure?.\n")) {
$("#myTable td").each( function() {
var worker = $(this).attr("id");
var quarter = $(this).attr("title");
var station = $(this).attr("name");
var type = $(this).attr("class");
$.post({ url: "insert_data.php", data: {worker:worker, quarter:quarter, station:station, type:type} });
});
}
else { return false; }
}
I am wondering if instead of calling the php with ajax for every <td>, maybe there is a way to pass the data like one package? I checked at least couple dozen different articles here and on other websites and it seems that very often JSON is used for that purpose.
I've never worked with JSON and after several days of trying different approaches, still can't figure out what I am doing wrong. I will appreciate any help.
All I need is to pass data from my table into php file (and unpack it in there). I do not need to display it simultaneously on the html page.
Here is one of the versions which doesn't work:
JS:
function insert_data() {
if(confirm("\nAre you sure?.\n")) {
var myArray = []; // var to store all records for json data transfer
$("#myTable td").each( function() {
var worker = $(this).attr("id");
var quarter = $(this).attr("title");
var station = $(this).attr("name");
var type = $(this).attr("class");
var record = {worker:worker, quarter:quarter, station:station, type:type}; // sd - short for schedule data
myArray.push(record); // add every record to same array
});
console.log(myArray);
$.post({ url: "insert_data.php", data: {myArray: myArray }, success: function(data){ alert('Items added'); }, error: function(e){ console.log(e.message); } });
}
else { return false; }
}
In console I see following data (it looks like the data is being added to the array without issues):
(4) [{...}, {...}, {...}, {...}]
0: {worker: "556", quarter: "1", station: "abc_15", type: "rework"}
1: {worker: "147", quarter: "2", station: "abc_37", type: "rework"}
2: {worker: "345", quarter: "3", station: "abc_15", type: "rework"}
3: {worker: "12", quarter: "4", station: "abc_15", type: "rework"}
PHP:
$mySchedule = array();
$mySchedule[] = $_POST["myArray"]; // get the json array
var_dump($mySchedule);
foreach ($mySchedule as $sched) {
$worker = $sched['worker']; // or: $sched->worker; - doesn't change the result
$quarter = $sched['quarter'];
$station = $sched['station'];
$type = $sched['type'];
// code to insert data into my DB - works fine when I pass data one by one instead of array
}
HTML:
I also added this script to the page with my table:
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-json/2.6.0/jquery.json.min.js"></script>
I am not sure if it is needed or not.
--
It feels that the problem is in the way how I "unpack" the array. But I am not sure... I tried to follow all advises I could find here, but maybe I just miss something really important.
I tried:
$mySchedule[] = json_decode($_POST["myArray"]); // in insert_data.php
data: { json: JSON.stringify(myArray) } // in jQuery function
and some other advises...
update
I got some help from one of my colleges. So, the jQuery code stayed without changes. PHP code had couple minor changes and it works fine now. The changes in PHP:
$mySchedule = $_POST["myArray"]; // get the json array
instead of:
$mySchedule = array();
$mySchedule[] = $_POST["myArray"]; // get the json array
That is it. Thank you very much for help and advises. I hope this example will be helpful to others.
Hi I am trying to get data from MySql table and show the data in Highcharts by using PHP and Json
I have try the example from internet and it is working fine but when I try to get data from my file it show nothing.
What I am trying to do:
I am creating table of office attendance system and trying to show record day by day. So at y axis I want to count names of employees and x axis the date of attendance.
Problem: Nothing Is show from mu json.
Here is what my Json looks like:
[["Hamza","07\/04\/2014"],
["Junaid","07\/04\/2014"],
["Usman","07\/04\/2014"],
["Rajab","07\/04\/2014"],
["Hamza","08\/04\/2014"],
["Junaid","08\/04\/2014"],
["Usman","08\/04\/2014"],
["Rajab","08\/04\/2014"]]
I am having to value names and dates.
My PHP which is creating my Json code:
// Set the JSON header
header("Content-type: text/json");
$result = mysqli_query($con,"SELECT * FROM attendence");
$a=array();
while($row = mysqli_fetch_array($result)) {
$row['name'] . "\t" . $row['date']. "\n";
$b=array();
array_push($b,$row['name']);
array_push($b,$row['date']);
array_push($a,$b);
}
echo json_encode($a);
and this is my Jquery code:
$(function() {
$.getJSON('highchart.php', function(data) {
// Create the chart
$('#chart').highcharts('StockChart', {
rangeSelector : {
selected : 1,
inputEnabled: $('#chart').width() > 480
},
title : {
text : 'Attendence'
},
series : [{
name : 'Empolyees',
data : data,
tooltip: {
valueDecimals: 2
}
}]
});
});
});
In the json_encode() you need to use JSON_NUMERIC_CHECK flag to avoid use string in your JSON
In the highstock you need to have timestamps and value, not name and date.
Dates should be timestamp, and as first element in array, not second as you have.
If you want to get a count of all people on a given day, you need to write a SQL query that returns that information. Assuming that date field is a datetime type and name is of varchar type:
SELECT COUNT(name) FROM attendence GROUP BY DATE(date);
perhaps you need to define what kind of data your x-axis will have
take a look at this fiddle (taken from highcharts website)
$(function () {
$('#container').highcharts({
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]
]
}]
});
});
I've set setInterval to update my scheduler. I'm getting data from server in JSON format. But Scheduler is not getting update if I used json data, But if I put static values it works fine. Following is my code.
// It doesn't work
setInterval(function() {
$.post('ajax_comet.php',{sectionIds:sectionIds},function (data){
if(data.processing.length>0)
{
for(var i=0;i<data.processing.length;i++)
{
var startdt=data.processing[i].start_interval.split(",");
var endt=data.processing[i].end_interval.split(",");
var month=parseInt(startdt[1])-1;
var start=startdt[0]+","+month+","+startdt[2]+","+startdt[3]+","+startdt[4];
var end=endt[0]+","+month+","+endt[2]+","+endt[3]+","+endt[4];
var section="'"+data.processing[i].section_id+"'";
console.log(start);
console.log(end);
scheduler.addMarkedTimespan({
start_date: new Date(start),
end_date: new Date(end),
css: "inprocess",
sections: {
unit: section
}
});
scheduler.updateView();
}
Same TimeInterval with static data works fine.
// This works properly.
setInterval(function() {
$.post('ajax_comet.php',{sectionIds:sectionIds},function (data){
if(data.processing.length>0)
{
for(var i=0;i<data.processing.length;i++)
{
var startdt=data.processing[i].start_interval.split(",");
var endt=data.processing[i].end_interval.split(",");
var month=parseInt(startdt[1])-1;
var start=startdt[0]+","+month+","+startdt[2]+","+startdt[3]+","+startdt[4];
var end=endt[0]+","+month+","+endt[2]+","+endt[3]+","+endt[4];
var section="'"+data.processing[i].section_id+"'";
console.log(start);
console.log(end);
scheduler.addMarkedTimespan({
start_date: new Date(2013,11,29,01,00),
end_date: new Date(2013,11,29,01,30),
css: "inprocess",
sections: {
unit: 'a7b6e635-f62f-6f12-020f-52a959d1ca47'
}
});
scheduler.updateView();
}
}
},'json');
}, 5000);
}
},'json');
}, 5000);
If it works with the static data, that means that dynamic data either comes wrong or is parsed wrong on the client.
Make sure that dates and section are correct.
For example, in this code, where you collect a date string from the ajax values and check this string in console:
var start=startdt[0]+","+month+","+startdt[2]+","+startdt[3]+","+startdt[4];
var end=endt[0]+","+month+","+endt[2]+","+endt[3]+","+endt[4];
console.log(start);
console.log(end);
It would be more informative if you check the resulting date, that is passed to the scheduler API.
console.log(new Date(start));
console.log(new Date(end));
Date string might have some non-obvious error which results in invalid date object.
Secondly, the code that collects the dates is rather complex. I'd suggest to use a simplier format for transfering dates from the server(for example use unix timestamp), or to define some helper function for parsing them.
FYI, scheduler library includes scheduler.date object that defines methods for working with dates.
So you can define parse function like following. That leaves much less space for typos and accidental errors. Not quite sure that I've specified the correct date format, but you can change it if it's necessary
var parseDate = scheduler.date.str_to_date("%Y, %m, %d, %H, %i");
var start = parseDate(data.processing[i].start_interval),
end = parseDate(data.processing[i].end_interval);
One particularly suspicious line is where you retreive id of the section:
var section="'"+data.processing[i].section_id+"'";
I think you add extra quotes to the section id here. I mean var section will be equal to
"'a7b6e635-f62f-6f12-020f-52a959d1ca47'" , while in your static code you use "a7b6e635-f62f-6f12-020f-52a959d1ca47" - without extra quotes
One more thing. You call scheduler.updateView() each time timespan is added. Since this command triggers complete redraw of the calendar, it's better to call it only once when the loop is finished.
UPDATE:
here is the code sample. Didn't actually run it, but i hope it clarifies the text above
setInterval(function() {
var parseDate = scheduler.date.str_to_date("%Y, %m, %d, %H, %i");// parse string of specified format into date object
$.post('ajax_comet.php',{sectionIds:sectionIds},function (data){
if(data.processing.length>0)
{
for(var i=0;i<data.processing.length;i++)
{
var timespan = data.processing[i];
var start = parseDate(timespan.start_interval),
end = parseDate(timespan.end_interval),
section = timespan.section_id;
console.log(start);
console.log(end);
scheduler.addMarkedTimespan({
start_date: start,
end_date: end,
css: "inprocess",
sections: {
unit: section
}
});
}
//update calendar after loop is finished
scheduler.updateView();
}
},'json');
}, 5000);
Background Info
I'm fiddling around with some PHP and AJAX at the moment, to try and get the code working for an auto refreshing div (every 10 seconds), that contains comments.
Here is javascript code I am using to refresh the div..
<script type="text/javascript">// <![CDATA[
$(document).ready(function() {
$.ajaxSetup({ cache: false });
setInterval(function() {
$('#content_main').load('/feed_main.php');
}, 5000);
});
// ]]></script>
The code that will populate the div called "content_main", which is in feed_main.php, essentially accesses the database and echo's out the latest comments ...
Question
Is it possible, to only load the div "content_main" if the data inside of it, hasn't changed since the last time it was loaded?
My logic
Because I'm relatively new to javascript and AJAX I don't quite know how to do this, but my logic is:
For the first time it is run..
load data from feed_main.php file
Create a unique value (perhaps a hash value? ) to identify say 3 unique comments
Every other time it is run...
load the data from feed_main.php file
create a NEW unique value
check this value with the previous one
if they're the same, don't refresh the div, just leave things as they are, but if they're different then refresh..
The reason why I want to do this is because the comments usually have pictures attached, and it is quite annoying to see the image reload every time.
Any help with this would be greatly appreciated.
I've faced similar problem not too long ago, i assume that you using mysql or something for your comments storage serverside ?
I solved my problem by first adding timestamp integer column to my mysql table, then when i added a new row, i'd just simply use time() to save the current time.
mysql row insert example:
$query = "INSERT INTO comments (name, text, timestamp) VALUES ('". $name ."', '". $text ."',". time() .");";
step two would be to json_encode the data you sending from serverside:
$output = array();
if ($html && $html !== '') { // do we have any script output ?
$output['payload'] = $html; // your current script output would go in this variable
}
$output['time'] = time(); // so we know when did we last check for payload update
$json = json_encode($output, ((int)JSON_NUMERIC_CHECK)); // jsonify the array
echo $json; // send it to the client
So, now instead of pure html, your serverside script returns something like this:
{
"payload":"<div class=\"name\">Derpin<\/div><div class=\"msg\">Foo Bar!<\/div>",
"time":1354167493
}
You can grab the data in javascript simply enough:
<script type="text/javascript"> // <![CDATA[
var lastcheck;
var content_main = $('#content_main');
pollTimer = setInterval(function() {
updateJson();
}, 10000);
function updateJson() {
var request = '/feed_main.php?timestamp='+ (lastcheck ? lastcheck : 0);
$.ajax({
url: request,
dataType: 'json',
async: false,
cache: false,
success: function(result) {
if (result.payload) { // new data
lastcheck = result.time; // update stored timestamp
content_main.html(result.payload + content_main.html()); // update html element
} else { // no new data, update only timestamp
lastcheck = result.time;
}
}
});
}
// ]]> </script>
that pretty much takes care of communication between server and client, now you just query your database something like this:
$timestamp = 0;
$where = '';
if (isset($_GET['timestamp'])) {
$timestamp = your_arg_sanitizer($_GET['timestamp']);
}
if ($timestamp) {
$where = ' WHERE timestamp >= '.$timestamp;
}
$query = 'SELECT * FROM comments'. $where .' ORDER BY timestamp DESC;';
The timestamps get passed back and forth, client always sending the timestamp returned by the server in previous query.
Your server only sends comments that were submitted since you checked last time, and you can prepend them to the end of the html like i did. (warning: i have not added any kind of sanity control to that, your comments could get extremely long)
Since you poll for new data every 10 seconds you might want to consider sending pure data across the ajax call to save substantial chunk bandwidth (json string with just timestamp in it, is only around 20 bytes).
You can then use javascript to generate the html, it also has the advantage of offloading lot of the work from your server to the client :). You will also get much finer control over how many comments you want to display at once.
I've made some fairly large assumptions, you will have to modify the code to suit your needs. If you use my code, and your cat|computer|house happens to explode, you get to keep all the pieces :)
How about this:
<script type="text/javascript">
// <![CDATA[
$(function () {
function reload (elem, interval) {
var $elem = $(elem);
// grab the original html
var $original = $elem.html();
$.ajax({
cache : false,
url : '/feed_main.php',
type : 'get',
success : function (data) {
// compare the result to the original
if ($original == data) {
// just start the timer if the data is the same
setTimeout(function () {
reload(elem, interval)
}, interval);
return;
}
// or update the html with new data
$elem.html(data);
// and start the timer
setTimeout(function () {
reload(elem, interval)
}, interval);
}
});
}
// call it the first time
reload('#content_main', 10000);
});
// ]]>
</script>
This is just an idea to get you going it doesn't deal with errors or timeouts.
Best And Easy Code
setInterval(function()
{
$.ajax({
type:"post",
url:"uourpage.php",
datatype:"html",
success:function(data)
{
$("#div").html(data);
}
});
}, 5000);//time in milliseconds
I hope this problem is very simple, I can't figure out the solution myself it seems. Been trying and googling for hours, driving me nuts :) Ok, so I have a drag'n'drop + sortable (using scriptaculous and prototype for your information) on my index.php. I use this code to send the items dropped in a div using this code:
<script type="text/javascript">
//<![CDATA[
document.observe('dom:loaded', function() {
var changeEffect;
Sortable.create("selectedSetupTop", {containment: ['listStr', 'selectedSetupTop'], tag:'img', overlap:'vertical', constraint:false, dropOnEmpty: true,
onChange: function(item) {
var list = Sortable.options(item).element;
$('changeNotification').update(Sortable.serialize(list).escapeHTML());
if(changeEffect) changeEffect.cancel();
changeEffect = new Effect.Highlight('changeNotification', {restoreColor:"transparent" });
},
onUpdate: function(list) {
new Ajax.Request("script.php", {
method: "post",
parameters: { data: Sortable.serialize(list), container: list.id }
onLoading: function(){$('activityIndicator').show(), $('activityIndicator2').hide()},
onLoaded: function(){$('activityIndicator').hide(), $('activityIndicator2').show()},
});
}
});
});
// ]]>
</script>
I've been using this code before so I "kind of know" it will send me data to my script.php page. selectedSetupTop is my div containing the elements. Don't mind about the notification and the activityIndicator thingy. My script.php page looks like this for the moment:
parse_str($_POST['data']);
for ($i = 0; $i < count($selectedSetupTop); $i++) {
$test .= $selectedSetupTop[$i];
}
echo "<script>alert('$test');</script>";
I can't seem to get any output in the alert message, it's just blank. The purpose of the script.php is to update a row in a database and it will look kind of like this:
$sql = mysql_query("UPDATE table SET row = '$arrayInStringFormat' WHERE id = '1'") or die(mysql_error());
where the $arrayInStringFormat is a conversion of the array $selectedSetupTop to the format (1, 2, 3, 4). I guess I'll solve that using implode or something, but the problem is parsing the array $selectedSetupTop. I'm not it passes between the pages at all, really appreciate help! Tell me if I need to explain further.
Thanks in advance!
''''''
EDIT 1
If it will help, I used this code before that I know will send me the data and use it. Notice I don't wanna do my task like the way I do below:
$querySetup = $_GET["s"];
parse_str($_POST['data']);
for ($i = 0; $i < count($selectedSetupTop); $i++) {
$sql = mysql_query("UPDATE " . $querySetup . " SET orderId = $i, hero_selected = 'n' WHERE imageId = $selectedSetupTop[$i]") or die(mysql_error());
}
''''''
EDIT 2
So it does parse, but I still have the problem I can't print it. I wanna implode the array somehow.
Not sure how AJAX works in Scriptalicious/Prototype, but you don't seem to be getting the data from the AJAX call. In jQuery it would be something like this where the data you receive from the script is returned as the argument of the function.
onLoaded: function(msg){
$('activityIndicator').hide(),
$('activityIndicator2').show(),
alert(msg)
}
Secondly, you can't echo a PHP array, you have to encode it to JSON:
echo json_encode($test);