Alter highchart output to display start - end date - php

I currently have the following highchart which display a start date and outputs the values for the next 31 days of data. Does anyone know how I may improve on this to include and end date so that I can filter the data by smaller specific amounts? On the x-axis I am also trying to only display labels that have data attached to them and hide any others. Any help is appreciated.
My code is as follows:
<script type="text/javascript">
var chart;
$(document).ready(function () {
chart = new Highcharts.Chart({
chart: {
renderTo: 'container',
type: 'line',
marginRight: 130,
marginBottom: 25
},
title: {
text: '<?php echo $type ?>',
x: -20 //center
},
xAxis: {
categories: [ <? php
$start = $_POST["dateStart"];
$dates = array();
for ($i = 0, $days = date('t', strtotime($start)); $i < $days; ++$i) {
$dates[] = date('Y-m-d', strtotime($start.' + '.$i.' day'));
}
echo "'".implode("', '", $dates)."'"; ?> ]
},
yAxis: {
title: {
text: 'Total Amount'
},
plotLines: [{
value: 0,
width: 1,
color: '#808080'
}]
},
tooltip: {
formatter: function () {
return '<b>' + this.series.name + '</b><br/>' + this.x + ': ' + this.y;
}
},
legend: {
layout: 'vertical',
align: 'right',
verticalAlign: 'top',
x: -10,
y: 100,
borderWidth: 0
},
series: [ <? php
foreach($array as $legend = > $data) {
echo '{';
echo "name: '".$legend."',";
$values = array();
for ($i = 0; $i < $days; ++$i) {
$date = date('Y-m-d', strtotime($start.' + '.$i.' day'));
$values[] = isset($data[$date]) ? $data[$date] : 0;
}
echo 'data: ['.implode(', ', $values).'],';
echo '},';
} ?> ]
});
});
Thanks

Please note that the following IS NOT secure. You should ALWAYS run a sanity check on data submitted by the user.
xAxis: {
categories: [ <? php
$start = $_POST["dateStart"];
$end = $_POST["dateEnd"];
$dates = array();
$current=$start;
while($current<=$end){
$dates[]=$current;
$current=date('Y-m-d', strtotime($current.' + 1 day'));
}
echo "'".implode("', '", $dates)."'"; ?> ]
},

Related

Plotting multiple series from JSON php import to Highcharts

because I'm pretty new to JS, I can't understand how to implement multiple data series into my code
Here is my php page that I use as data grabber:
getTrendData-TIMEREQUESTED-hms.php
<?php
//Define possible Argument request
$format = $_GET['format'];
if($format=='json') {
header("Content-type: text/json");
}
//Define database credential
$servername = "localhost";
$username = "test";
$password = "test";
$dbname = "test";
try {
//Open connection to mysql_db from defined Database credentials
$connection = mysqli_connect($servername, $username, $password, $dbname) or die ("Error " . mysqli_error($connection));
$sql = "select TIMEREQUESTED,TS FROM TIMEREQUESTED ORDER BY TS;";
$result = mysqli_query($connection, $sql) or die ("Error in Selecting " . mysqli_error($connection));
//create an array
$data = array();
while($row = mysqli_fetch_assoc($result)) {
$TIMEREQUESTED = strtotime($row['TIMEREQUESTED'])*1000;
$TS = strtotime($row['TS'])*1000;
$data[] = array($TS, $TIMEREQUESTED);
}
echo json_encode($data);
//close the db connection
mysqli_close($connection);
}
catch(PDOException $e) {
echo $e->getMessage();
}
?>
Than I include in HighCharts with an Ajax call, that call himselfs each 2500 miliseconds,
getTrendData-TIMEREQUESTED-hms.php
[[1461241983000,5.67,0],[1461242015000,16.67,0],[1461242164000,16.67,0],[1461242303000,26.25,0],[1461242835000,-2.5,0],[1461242869000,-2.5,0],[1461242991000,1.5,0],[1461243034000,3.14,0],[1461243374000,-14.22,0],[1461243456000,-11.92,0],[1461244995000,0,0],[1461245036000,-3.6,140],[1461245208000,-3,140],[1461245260000,3.56,140],[1461245312000,2.1,140],[1461245346000,2.1,140],[1461245411000,3.5,140],[1461245442000,3.5,140],[1461245479000,-1,140],[1461245757000,-0.8,140],[1461245809000,-0.69,140]]
TIMEREQUESTED-hms.html
function buildTIMEREQUESTED() {
var chart;
var dataSource = 'getTrendData-TIMEREQUESTED-hms.php?format=json';
var ChartHeight = window.innerHeight;
function requestData() {
$.ajax({
url: dataSource,
success: function(points) {
chart.series[0].setData(points, true);
setTimeout(requestData, 2500);
},
cache: false
});
}
$(document).ready(function() {
//add our div for the chart
$("#container").append("<div id=chart-laptime style='width:100%''></div>");
chart = new Highcharts.Chart({
chart: {
height: ChartHeight,
renderTo: 'chart-laptime',
defaultSeriesType: 'line',
events: {
load: function() {
requestData();
}
},
},
tooltip: {
enabled: true,
formatter: function() {
s = (this.y / 1000);
m = Math.floor(s / 60);
h = Math.floor(m / 60);
s = s % 60;
m = m % 60;
h = h % 24;
if (h < 9) h = "0" + h;
if (m < 9) m = "0" + m;
if (s < 9) s = "0" + s;
return '<span style="color:black">Time Zero - </span>' + [m, s].join(':');
}
},
title: {
text: 'TIMEREQUESTED'
},
subtitle: {
text: 'BEST 5 CAR AVEREGE LAPTIME IN LAST 10 MINUTES'
},
xAxis: {
type: 'datetime',
title: {
text: 'RACE TIME'
}
},
yAxis: {
type: 'datetime',
dateTimeLabelFormats: {
millisecond: '%H:%M:%S',
},
//dateFormat: {"%H:%M:%S.%L"}
title: {
text: 'TIMEREQUESTED'
}
},
series: [{
name: 'TIMEREQUESTED',
showInLegend: false,
//tooltip: {type: 'datetime',},
data: [],
}]
}); //end chart
}); //end document.ready
}
In that way I can get the single series proper displayed, but with the MySQL query I'm able to get more columns from the database, and parsing in each rows of the json file,(As is showed in the JSON file from php request, there is a third values for each array) but I'm not able to understand how to display multiple data series, with on the xAxis always the first column of the JSON file, and on the yAxis each time a different columns.
Could you please give me some suggestions on how to display multi series on the same graph? It would be so much appreciated,
Best regards.
var dataForTwoSeries = [[1461241983000,5.67,0],[1461242015000,16.67,0],[1461242164000,16.67,0]]; //your data, just took 3 elements. Should work for any number of elements.
var seriesOne = [];
var seriesTwo = [];
$.each(dataForTwoSeries, function(index, dataPoints){
var seriesOneDataPoint = [dataPoints[0], dataPoints[1]];
var seriesTwoDataPoint = [dataPoints[0], dataPoints[2]];
seriesOne.push(seriesOneDataPoint);
seriesTwo.push(seriesTwoDataPoint);
});
And then you'll have to create 2 series in your chart object like
series: [{
name: 'seriesName1',
showInLegend: false,
data: [],
},{
name: 'seriesName2',
showInLegend: false,
data: [],
}]
And in your requestData method, set the data for both like
chart.series[0].setData(seriesOne, false); //redraw after setting data for second series
chart.series[1].setData(seriesTwo); //boolean redraw is true by default, don't need to pass it
EDIT : After your updated code, these are the changes you further need to make.
$.ajax({url: dataSource, success: function(dataForTwoSeries) //dataForTwoSeries is the data you get from the request
{
//var dataForTwoSeries = []; you don't need this.
var seriesOne = []; //these two don't have to be global.
var seriesTwo = [];
$.each(dataForTwoSeries, function(index, dataPoints){
var seriesOneDataPoint = [dataPoints[1], dataPoints[0]];
var seriesTwoDataPoint = [dataPoints[2], dataPoints[0]];
seriesOne.push(seriesOneDataPoint);
seriesTwo.push(seriesTwoDataPoint);
}); // draw chart after iteration and not during each interation
chart.series[0].setData(seriesOne, false); //redraw after setting data for second series
chart.series[1].setData(seriesTwo); //boolean redraw is true by default, don't need to pass it
setTimeout(requestData, 2500);
},
cache: false
});
I've update the code and now is free from syntax error, but I have no data displayed. I'm going to put some windows.allert() tu understand where the data flow is broken.
Here's the updated code:
<!DOCTYPE html>
<html>
<head>
<title>Strategy - Time Zero</title>
<script src="js/jquery/jquery-1.12.3.js"></script>
<link href="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet">
<script src="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
<script src="js/Highcharts/Highcharts-4.2.3/highcharts.js"></script>
<script src="js/Highcharts/Highcharts-4.2.3/modules/exporting.js"></script>
<script>
var chart;
var dataSource = 'getTrendData-TimeZero.php?format=json';
var ChartHeight = window.innerHeight;
var dataForTwoSeries = [];
var seriesOne = [];
var seriesTwo = [];
function requestData() {
$.ajax({url: dataSource, success: function(dataPoints)
{
$.each(dataForTwoSeries, function(index, dataPoints){
var seriesOneDataPoint = [dataPoints[1], dataPoints[0]];
var seriesTwoDataPoint = [dataPoints[2], dataPoints[0]];
window.alert(seriesOneDataPoint)
seriesOne.push(seriesOneDataPoint);
seriesTwo.push(seriesTwoDataPoint);
chart.series[0].setData(seriesOne, false); //redraw after setting data for second series
chart.series[1].setData(seriesTwo); //boolean redraw is true by default, don't need to pass it
setTimeout(requestData, 2500);
});
},
cache: false
});
}
$(document).ready(function() {
//add our div for the chart
$("#container").append("<div id=chart-TimeZero style='width:100%''></div>");
//StockChart
//Chart
chart = new Highcharts.Chart({
chart: {
height: ChartHeight,
renderTo: 'chart-TimeZero',
defaultSeriesType: 'line',
events: {
load: function() {
requestData();
}
},
},
tooltip: {
enabled: true,
formatter: function() {
if (this.y < 0)
{
h = Math.ceil(this.y / 3600);
m = Math.ceil(this.y / 60);
s = Math.ceil(this.y % 60);
h = Math.abs(h);
m = Math.abs(m);
s = Math.abs(s);
s = s % 60;
m = m % 60;
h = h % 24;
if (h < 9) h = "-0" + h;
if (m < 9) m = "0" + m;
if (s < 9) s = "0" + s;
}
else
{
h = Math.floor(this.y / 3600);
m = Math.floor(this.y / 60);
s = Math.floor(this.y % 60);
h = Math.abs(h);
m = Math.abs(m);
s = Math.abs(s);
s = s % 60;
m = m % 60;
h = h % 24;
if (h < 9) h = "0" + h;
if (m < 9) m = "0" + m;
if (s < 9) s = "0" + s;
}
return '<span style="color:black">Time Zero</span> ' + [h, m, s].join(':');
}
},
title: {
text: 'TIME ZERO'
},
subtitle: {
text: 'BEST 5 CAR AVEREGE LAPTIME IN LAST 10 MINUTES'
},
xAxis: {
type: 'datetime',
title: {text: 'DAY TIME'}
},
yAxis: {
title: {text: 'TIME ZERO'},
labels: {
formatter: function() {
if (this.value < 0)
{
h = Math.ceil(this.value / 3600);
m = Math.ceil(this.value / 60);
s = Math.ceil(this.value % 60);
h = Math.abs(h);
m = Math.abs(m);
s = Math.abs(s);
s = s % 60;
m = m % 60;
h = h % 24;
if (h < 9) h = "-0" + h;
if (m < 9) m = "0" + m;
if (s < 9) s = "0" + s;
}
else
{
h = Math.floor(this.value / 3600);
m = Math.floor(this.value / 60);
s = Math.floor(this.value % 60);
h = Math.abs(h);
m = Math.abs(m);
s = Math.abs(s);
s = s % 60;
m = m % 60;
h = h % 24;
if (h < 9) h = "0" + h;
if (m < 9) m = "0" + m;
if (s < 9) s = "0" + s;
}
return [h, m, s].join(':');
}
}
},
series: [{
name: 'seriesName1',
showInLegend: true,
data: [],
},{
name: 'seriesName2',
showInLegend: true,
data: [],
}]
}); //end chart
}); //end document.ready
</script>
</head>
<body>
<div id="container"></div>
</body>
</html>

Highcharts with data from mysql database

I'm using highcharts plugin to print stats in a codeigniter site.
Now I get the data from my database I manage it but when I print it inside highcharts nothing is printed.
This is my php code:
$arr_point = array();
$check_price = array();
for($i = 1; $i <= 12; $i++){
$sum = 0;
$this->load->model('backend/Notification_model');
$this->db->select('*,');
$this->db->from('booking');
$query = $this->db->get();
foreach ($query->result() as $row){
$sum+=(float)$row->total_with_markup;
}
$arr_point[] = str_replace(',', '.', $sum);
}
$result = array();
array_push($result,$arr_point);
return(json_encode($result));
and this is my highchart configuration:
$('#container').highcharts({
chart: {
type: 'column'
},
title: {
text: $('#riepilogo option:selected').text()
},
subtitle: {
text: ''
},
xAxis: {
categories: [
'Jan',
'Feb',
'Mar',
'Apr',
'May',
'Jun',
'Jul',
'Aug',
'Sep',
'Oct',
'Nov',
'Dec'
]
},
yAxis: {
min: 0,
title: {
text: 'Euro'
}
},
tooltip: {
headerFormat: '<span style="font-size:10px">{point.key}</span><table>',
pointFormat: '<tr><td style="color:{series.color};padding:0">{series.name}: </td>' +
'<td style="padding:0"><b>{point.y:.2f} euro</b></td></tr>',
footerFormat: '</table>',
shared: true,
useHTML: true
},
plotOptions: {
column: {
pointPadding: 0.2,
borderWidth: 0
}
},
series: [ {
name: $('#riepilogo options:selected').text(),
data: "<?php echo json_decode($data_chart); ?>"
}]
});
});
if I print json_decode($data_chart) I get this:
Array
if I print ($data_chart I get this:
[["0","297.23","74.41","65.57","2167.32","7649.77","2058.05","146.95","92.55","0","1754.72","0"]]
I have try to not use json_encode, to use json_decode, nothing. Can someone help me? Thanks
The problem is that you create an array in your script:
$arr_point = array();
Try returning just the array and delete:
$result = array();
array_push($result,$arr_point);
and return $array_point;
Or try:
$arr_point = "";
$check_price = array();
for ($i = 1; $i <= 12; $i++) {
$sum = 0;
$this->load->model('backend/Notification_model');
$this->db->select('*,');
$this->db->from('booking');
$query = $this->db->get();
foreach ($query->result() as $row) {
$sum+=(float) $row->total_with_markup;
}
if($arr_point == ""){
$arr_point .= "[";
}
if($arr_point != ""){
$arr_poin .= ",";
}
$arr_point .= str_replace(',', '.', $sum);
}
$arr_point .= "]";
return $arr_point;
Your code contains many injections, so I advice to print json inside your php file like:
echo json_encode($arr, JSON_NUMERIC_CHECK);
Then in javascript call $.getJSON() function and use it in highcahrts, skipping decoding / missing types of data.

Highcharts data from MySQL / PHP

I am trying to build the data for my Highcharts chart but I'm having trouble when a certain day has no rows.
I.e. I want a chart to show enquiries per day for the current week. If no enquiries were received on Wednesday, then that day is missing from my chart or the data from Thursday falls into Wednesday which is wrong, depending on what I do.
SQL I have:
$W = date('W');
$Y = date('Y');
$SQL = "SELECT DATE_FORMAT(enquiries.dateCreated, '%a') AS name, COUNT(*) AS y
FROM enquiries
WHERE WEEK(enquiries.dateCreated, 1) = $W
AND YEAR(enquiries.dateCreated) = $Y
GROUP BY DAY(enquiries.dateCreated)";
$result = $this->db->prepare($SQL);
$result->execute();
return $result->fetchAll(PDO::FETCH_ASSOC);
And my current attempt to put it into an array which doesn't work:
$enquiries = $this->model->enquiriesTime();
$dayData = array();
for ($i = 0; $i != 5; $i++) {
if ($enquiries[$i]['name'] == 'Mon' || $enquiries[$i]['name'] == 'Tue' || $enquiries[$i]['name'] == 'Wed' || $enquiries[$i]['name'] == 'Thu' || $enquiries[$i]['name'] == 'Fri') {
$dayData[$i] = $enquiries[$i]['y'];
} else {
$dayData[$i] = '0';
}
}
When a day doesn't exist the 0 gets added to the end of the array and not index 2 (Wednesday) like it should, so Wednesday's results are actually Thursdays.
How can I get this to work properly?
Here is the JS:
function createActivityChart() {
$.ajax({
url: ROOT + 'Ajax',
data: {
call: 'lists->enquiriesTime'
},
dataType: 'json',
type: 'POST',
async: true,
success: function(returned) {
$('#enquiriesChart').highcharts({
chart: {
type: 'column'
},
title: {
text: 'Weekly activity chart'
},
xAxis: {
categories: [
'Mon',
'Tue',
'Wed',
'Thu',
'Fri'
]
},
yAxis: {
min: 0,
title: null,
stackLabels: {
enabled: true,
style: {
fontWeight: 'bold',
color: (Highcharts.theme && Highcharts.theme.textColor) || 'gray'
}
}
},
tooltip: {
headerFormat: '<span style="font-size:10px">{point.key}</span><table>',
pointFormat: '<tr><td style="color:{series.color};padding:0">{series.name}: </td>' +
'<td style="padding:0"><b>{point.y:.0f}</b></td></tr>',
footerFormat: '</table>',
shared: true,
useHTML: true
},
plotOptions: {
column: {
stacking: 'normal',
dataLabels: {
enabled: false,
color: (Highcharts.theme && Highcharts.theme.dataLabelsColor) || 'white',
style: {
textShadow: '0 0 3px black, 0 0 3px black'
}
}
}
},
series: returned
});
}
})
}
And the HTML container:
<div class="row-fluid">
<div class="span12">
<div class="gridData">
<div id="activityChart" style="min-width: 200px; height: 200px; margin: 0 auto"></div>
</div>
</div>
</div>
What I use to do to avoid your problem is create the highchart array with all 0 values, and then overwrite them. This way you make sure no data is left behind.
I appear to have done it using this horrendous logic ladder:
for ($i = 0; $i != 5; $i++) {
if ($i == 0) {
if ($enquiries[$i]['name'] == 'Mon') {
$dayData[$i] = $enquiries[$i]['y'];
} else {
$enquiriesI = array(array('name' => 'Mon', 'y' => 0));
array_splice($enquiries, 0, 0, $enquiriesI);
$dayData[$i] = 0;
}
}
if ($i == 1) {
if ($enquiries[$i]['name'] == 'Tue') {
$dayData[$i] = $enquiries[$i]['y'];
} else {
$enquiriesI = array(array('name' => 'Tue', 'y' => 0));
array_splice($enquiries, 1, 0, $enquiriesI);
$dayData[$i] = 0;
}
}
if ($i == 2) {
if ($enquiries[$i]['name'] == 'Wed') {
$dayData[$i] = $enquiries[$i]['y'];
} else {
$enquiriesI = array(array('name' => 'Wed', 'y' => 0));
array_splice($enquiries, 2, 0, $enquiriesI);
$dayData[$i] = 0;
}
}
if ($i == 3) {
if ($enquiries[$i]['name'] == 'Thu') {
$dayData[$i] = $enquiries[$i]['y'];
} else {
$enquiriesI = array(array('name' => 'Thu', 'y' => 0));
array_splice($enquiries, 3, 0, $enquiriesI);
$dayData[$i] = 0;
}
}
if ($i == 4) {
if ($enquiries[$i]['name'] == 'Fri') {
$dayData[$i] = $enquiries[$i]['y'];
} else {
$enquiriesI = array(array('name' => 'Fri', 'y' => 0));
array_splice($enquiries, 4, 0, $enquiriesI);
$dayData[$i] = 0;
}
}
}
There must be a better way?
I have found that the above method works well for week days and the following method for days of the month:
public function parseMonthlyGraph($SQLResults) { // For days
$dayData = array();
$startDate = date('Y-m').'-01';
$lastDay = date("t", strtotime($startDate));
for ($i = 0; $i != 31; $i++) {
if($i == $lastDay)
{
break;
}
$dayName = date('jS', strtotime($startDate . ' + '.$i.' days'));
if ($SQLResults[$i]['name'] == $dayName) {
$dayData[$i] = $SQLResults[$i]['y'];
if (empty($SQLResults[$i + 1])) {
$SQLResults[$i + 1]['name'] = date('jS', strtotime($startDate . ' + ' . $i+1 . +' days'));
$SQLResults[$i + 1]['y'] = 0;
}
} else {
$enquiriesI = array(array('name' => $dayName, 'y' => 0));
array_splice($SQLResults, $i, 0, $enquiriesI);
$dayData[$i] = 0;
}
}
return $dayData;
}

position absolute doesn't work

position absolute doesn't work in mozilla. For jquery calender I used position:absolute for a div it seems to work all except mozilla in windows. When I remove the position:absolute it will work in windows firefox but only showing alternate months in all other browsers
jquery is
var CalendarEightysix = new Class({
Implements: Options,
options: {
'slideDuration': 500,
'fadeDuration': 200,
'toggleDuration': 200,
'fadeTransition': Fx.Transitions.linear,
'slideTransition': Fx.Transitions.Quart.easeOut,
'prefill': true,
'defaultDate': null,
'linkWithInput': true,
'theme': 'default',
'defaultView': 'month',
'startMonday': false,
'alwaysShow': false,
'injectInsideTarget': false,
'format': '%n/%d/%Y',
'alignX': 'right',
'alignY': 'ceiling',
'offsetX': 0,
'offsetY': 0,
'draggable': false,
'pickable': true,
'toggler': null,
'pickFunction': $empty,
'disallowUserInput': false,
'minDate': null,
'maxDate': null,
'excludedWeekdays': null,
'excludedDates': null,
'createHiddenInput': false,
'hiddenInputName': 'date',
'hiddenInputFormat': '%t'
},
initialize: function(target, options) {
this.setOptions(options);
this.target = $(target);
this.transitioning = false;
//Extend Date with unix timestamp parser
Date.defineParser({
re: /^[0-9]{10}$/,
handler: function(bits) { return new Date.parse('Jan 01 1970').set('seconds', bits[0]); }
});
//Selected date
if($defined(this.options.defaultDate)) this.selectedDate = new Date().parse(this.options.defaultDate).clearTime();
else if(this.options.linkWithInput && $chk(this.target.get('value'))) this.selectedDate = new Date().parse(this.target.get('value')).clearTime();
if(!$defined(this.selectedDate) || !this.selectedDate.isValid()) this.selectedDate = new Date();
this.viewDate = this.selectedDate.clone().set('date', 1).clearTime();
//Base
var innerHtml = '<div class="wrapper"><div class="header"><div class="arrow-left"></div><div class="arrow-right"></div><div class="label clickable"></div></div>'+
'<div class="body"><div class="inner"><div class="container a"></div><div class="container b"></div></div></div><div class="footer"></div></div>';
this.element = new Element('div', { 'class': 'calendar-eightysix', 'html': innerHtml, 'style': 'display: '+ (this.options.alwaysShow ? 'block' : 'none') }).addClass(this.options.theme);
if(this.options.injectInsideTarget) this.element.injectBottom(this.target);
else {
this.element.injectBottom($(document.body));
this.position();
window.addEvent('resize', this.position.bind(this));
}
this.currentContainer = this.element.getElement('.container.a').setStyle('z-index', 999);
this.tempContainer = this.element.getElement('.container.b').setStyle('z-index', 998);
//Header
this.header = this.element.getElement('.header');
this.label = this.header.getElement('.label');
this.arrowLeft = this.header.getElement('.arrow-left');
this.arrowRight = this.header.getElement('.arrow-right');
this.label.addEvent('click', this.levelUp.bind(this));
this.arrowLeft.addEvent('click', this.slideLeft.bind(this));
this.arrowRight.addEvent('click', this.slideRight.bind(this));
//Date range
if($defined(this.options.minDate)) {
this.options.minDate = Date.parse(this.options.minDate).clearTime();
if(!this.options.minDate.isValid()) this.options.minDate = null;
}
if($defined(this.options.maxDate)) {
this.options.maxDate = Date.parse(this.options.maxDate).clearTime();
if(!this.options.maxDate.isValid()) this.options.maxDate = null;
}
//Excluded dates
if($defined(this.options.excludedDates)) {
var excludedDates = [];
this.options.excludedDates.each(function(date) {
excludedDates.include(this.format(new Date().parse(date).clearTime(), '%t'));
}.bind(this));
this.options.excludedDates = excludedDates;
}
//Dragger
if(this.options.draggable && !this.options.injectInsideTarget) {
this.header.addClass('dragger');
new Drag(this.element, { 'handle': this.header });
}
//Hidden input
if(this.options.createHiddenInput) {
this.hiddenInput = new Element('input', { 'type': 'hidden', 'name': this.options.hiddenInputName }).injectAfter(this.target);
}
//Prefill date
if(this.options.prefill) this.pick();
//Link with input
if(!this.options.disallowUserInput && this.options.linkWithInput && this.target.get('tag') == 'input') {
this.target.addEvent('keyup', function() {
this.setDate(this.target.get('value'), false);
}.bind(this));
}
//Disallow input
if(this.options.disallowUserInput && this.target.get('tag') == 'input')
this.target.addEvents({ 'keydown': ($lambda(false)), 'contextmenu': ($lambda(false)) });
//Toggler
if($defined(this.options.toggler)) this.options.toggler = $(this.options.toggler);
//Show / hide events
($defined(this.options.toggler) ? this.options.toggler : this.target).addEvents({
'focus': this.show.bind(this), 'click': this.show.bind(this)
});
if(!this.options.alwaysShow) document.addEvent('mousedown', this.outsideClick.bind(this));
MooTools.lang.addEvent('langChange', function() { this.render(); this.pick(); }.bind(this));
//View
this.view = this.options.defaultView;
this.render();
},
render: function() {
this.currentContainer.empty();
switch(this.view) {
case 'decade': this.renderDecade(); break;
case 'year': this.renderYear(); break;
default: this.renderMonth();
}
},
renderMonth: function() {
this.view = 'month';
this.currentContainer.empty().addClass('month');
if(this.options.pickable) this.currentContainer.addClass('pickable');
var lang = MooTools.lang.get('Date'), weekdaysCount = this.viewDate.format('%w') - (this.options.startMonday ? 1 : 0);
if(weekdaysCount == -1) weekdaysCount = 6;
var today = new Date();
//Label
this.label.set('html', lang.months[this.viewDate.get('month')] +' '+ this.viewDate.format('%Y'));
//Day label row
var row = new Element('div', { 'class': 'row' }).injectBottom(this.currentContainer);
for(var i = (this.options.startMonday ? 1 : 0); i < (this.options.startMonday ? 8 : 7); i++) {
var day = new Element('div', { 'html': lang.days[this.options.startMonday && i == 7 ? 0 : i] }).injectBottom(row);
day.set('html', day.get('html').substr(0, 2));
}
//Add days for the beginning non-month days
row = new Element('div', { 'class': 'row' }).injectBottom(this.currentContainer);
y = this.viewDate.clone().decrement('month').getLastDayOfMonth();
for(var i = 0; i < weekdaysCount; i++) {
this.injectDay(row, this.viewDate.clone().decrement('month').set('date', y - (weekdaysCount - i) + 1), true);
}
//Add month days
for(var i = 1; i <= this.viewDate.getLastDayOfMonth(); i++) {
this.injectDay(row, this.viewDate.clone().set('date', i));
if(row.getChildren().length == 7) {
row = new Element('div', { 'class': 'row' }).injectBottom(this.currentContainer);
}
}
//Add outside days
var y = 8 - row.getChildren().length, startDate = this.viewDate.clone().increment('month').set('date', 1);
for(var i = 1; i < y; i++) {
this.injectDay(row, startDate.clone().set('date', i), true);
}
//Always have six rows
for(var y = this.currentContainer.getElements('.row').length; y < 7; y++) {
row = new Element('div', { 'class': 'row' }).injectBottom(this.currentContainer);
for(var z = 0; z < 7; z++) {
this.injectDay(row, startDate.clone().set('date', i), true);
i++;
}
}
this.renderAfter();
},
//Used by renderMonth
injectDay: function(row, date, outside) {
today = new Date();
var day = new Element('div', { 'html': date.get('date') }).injectBottom(row);
day.date = date;
if(outside) day.addClass('outside');
if(($defined(this.options.minDate) && this.format(this.options.minDate, '%t') > this.format(date, '%t')) ||
($defined(this.options.maxDate) && this.format(this.options.maxDate, '%t') < this.format(date, '%t')) ||
($defined(this.options.excludedWeekdays) && this.options.excludedWeekdays.contains(date.format('%w').toInt())) ||
($defined(this.options.excludedDates) && this.options.excludedDates.contains(this.format(date, '%t'))))
day.addClass('non-selectable');
else if(this.options.pickable) day.addEvent('click', this.pick.bind(this));
if(date.format('%x') == today.format('%x')) day.addClass('today');
if(date.format('%x') == this.selectedDate.format('%x')) day.addClass('selected');
},
renderYear: function() {
this.view = 'year';
this.currentContainer.addClass('year-decade');
var today = new Date(), lang = MooTools.lang.get('Date').months;
//Label
this.label.set('html', this.viewDate.format('%Y'));
var row = new Element('div', { 'class': 'row' }).injectBottom(this.currentContainer);
for(var i = 1; i < 13; i++) {
var month = new Element('div', { 'html': lang[i - 1] }).injectBottom(row);
month.set('html', month.get('html').substr(0, 3)); //Setting and getting the innerHTML takes care of html entity problems (e.g. [M&a]uml;r => [Mär]z)
var iMonth = this.viewDate.clone().set('month', i - 1);
month.date = iMonth;
if(($defined(this.options.minDate) && this.format(this.options.minDate.clone().set('date', 1), '%t') > this.format(iMonth, '%t')) ||
($defined(this.options.maxDate) && this.format(this.options.maxDate.clone().set('date', 1), '%t') < this.format(iMonth, '%t')))
month.addClass('non-selectable');
else month.addEvent('click', this.levelDown.bind(this));
if(i - 1 == today.get('month') && this.viewDate.get('year') == today.get('year')) month.addClass('today');
if(i - 1 == this.selectedDate.get('month') && this.viewDate.get('year') == this.selectedDate.get('year')) month.addClass('selected');
if(!(i % 4) && i != 12) row = new Element('div', { 'class': 'row' }).injectBottom(this.currentContainer);
}
this.renderAfter();
},
renderDecade: function() {
this.label.removeClass('clickable');
this.view = 'decade';
this.currentContainer.addClass('year-decade');
var today = new Date();
var viewYear, startYear;
viewYear = startYear = this.viewDate.format('%Y').toInt();
while(startYear % 12) startYear--;
//Label
this.label.set('html', startYear +' – '+ (startYear + 11));
var row = new Element('div', { 'class': 'row' }).injectBottom(this.currentContainer);
for(var i = startYear; i < startYear + 12; i++) {
var year = new Element('div', { 'html': i }).injectBottom(row);
var iYear = this.viewDate.clone().set('year', i);
year.date = iYear;
if(($defined(this.options.minDate) && this.options.minDate.get('year') > i) ||
($defined(this.options.maxDate) && this.options.maxDate.get('year') < i)) year.addClass('non-selectable');
else year.addEvent('click', this.levelDown.bind(this));
if(i == today.get('year')) year.addClass('today');
if(i == this.selectedDate.get('year')) year.addClass('selected');
if(!((i + 1) % 4) && i != startYear + 11) row = new Element('div', { 'class': 'row' }).injectBottom(this.currentContainer);
}
this.renderAfter();
},
renderAfter: function() {
//Iterate rows and add classes and remove navigation if nessesary
var rows = this.currentContainer.getElements('.row');
for(var i = 0; i < rows.length; i++) {
rows[i].set('class', 'row '+ ['a', 'b', 'c', 'd', 'e', 'f', 'g'][i] +' '+ (i % 2 ? 'even' : 'odd')).getFirst().addClass('first');
rows[i].getLast().addClass('last');
if(i == (this.view == 'month' ? 1 : 0) && $defined(this.options.minDate) && this.format(this.options.minDate, '%t') >= this.format(rows[i].getFirst().date, '%t'))
this.arrowLeft.setStyle('visibility', 'hidden');
if(i == rows.length - 1 && $defined(this.options.maxDate)) {
if((this.view == 'month' && this.format(this.options.maxDate, '%t') <= this.format(rows[i].getLast().date, '%t')) ||
(this.view == 'year' && this.format(this.options.maxDate, '%t') <= this.format(rows[i].getLast().date.clone().increment('month'), '%t')) ||
(this.view == 'decade' && this.format(this.options.maxDate, '%t') <= this.format(rows[i].getLast().date.clone().increment('year'), '%t')))
this.arrowRight.setStyle('visibility', 'hidden');
}
};
},
slideLeft: function() {
this.switchContainers();
//Render new view
switch(this.view) {
case 'month': this.viewDate.decrement('month'); break;
case 'year': this.viewDate.decrement('year'); break;
case 'decade': this.viewDate.set('year', this.viewDate.get('year') - 12); break;
}
this.render();
//Tween the new view in and old view out
this.currentContainer.set('tween', { 'duration': this.options.slideDuration, 'transition': this.options.slideTransition }).tween('left', [-this.currentContainer.getWidth(), 0]);
this.tempContainer.set('tween', { 'duration': this.options.slideDuration, 'transition': this.options.slideTransition }).tween('left', [0, this.tempContainer.getWidth()]);
},
slideRight: function() {
this.switchContainers();
//Render new view
switch(this.view) {
case 'month': this.viewDate.increment('month'); break;
case 'year': this.viewDate.increment('year'); break;
case 'decade': this.viewDate.set('year', this.viewDate.get('year') + 12); break;
}
this.render();
//Tween the new view in and old view out
this.currentContainer.set('tween', { 'duration': this.options.slideDuration, 'transition': this.options.slideTransition }).tween('left', [this.currentContainer.getWidth(), 0]);
this.tempContainer.set('tween', { 'duration': this.options.slideDuration, 'transition': this.options.slideTransition }).tween('left', [0, -this.currentContainer.getWidth()]);
},
levelDown: function(e) {
if(this.transitioning) return;
this.switchContainers();
this.viewDate = e.target.date;
//Render new view
switch(this.view) {
case 'year': this.renderMonth(); break;
case 'decade': this.renderYear(); break;
}
//Tween the new view in and old view out
this.transitioning = true;
this.currentContainer.set('tween', { 'duration': this.options.fadeDuration, 'transition': this.options.fadeTransition,
'onComplete': function() { this.transitioning = false }.bind(this) }).setStyles({'opacity': 0, 'left': 0}).fade('in');
this.tempContainer.set('tween', { 'duration': this.options.fadeDuration, 'transition': this.options.fadeTransition }).fade('out');
},
levelUp: function() {
if(this.view == 'decade' || this.transitioning) return;
this.switchContainers();
//Set viewdates and render
switch(this.view) {
case 'month': this.renderYear(); break;
case 'year': this.renderDecade(); break;
}
//Tween the new view in and old view out
this.transitioning = true;
this.currentContainer.set('tween', { 'duration': this.options.fadeDuration, 'transition': this.options.fadeTransition,
'onComplete': function() { this.transitioning = false }.bind(this) }).setStyles({'opacity': 0, 'left': 0}).fade('in');
this.tempContainer.set('tween', { 'duration': this.options.fadeDuration, 'transition': this.options.fadeTransition }).fade('out');
},
switchContainers: function() {
this.currentContainer = this.currentContainer.hasClass('a') ? this.element.getElement('.container.b') : this.element.getElement('.container.a');
this.tempContainer = this.tempContainer.hasClass('a') ? this.element.getElement('.container.b') : this.element.getElement('.container.a');
this.currentContainer.empty().removeClass('month').removeClass('year-decade').setStyles({ 'opacity': 1, 'display': 'block', 'z-index': 999 });
this.tempContainer.setStyle('z-index', 998);
this.label.addClass('clickable');
this.arrowLeft.setStyle('visibility', 'visible');
this.arrowRight.setStyle('visibility', 'visible');
},
pick: function(e) {
if($defined(e)) {
this.selectedDate = e.target.date;
this.element.getElements('.selected').removeClass('selected');
e.target.addClass('selected');
}
var value = this.format(this.selectedDate);
if(!this.options.injectInsideTarget) {
switch(this.target.get('tag')) {
case 'input': this.target.set('value', value); break;
default: this.target.set('html', value);
}
(this.hide.bind(this)).delay(150);
}
if($defined(this.hiddenInput)) this.hiddenInput.set('value', this.format(this.selectedDate, this.options.hiddenInputFormat));
this.options.pickFunction(this.selectedDate);
},
position: function() {
var top, left;
var coordinates = this.target.getCoordinates();
switch(this.options.alignX) {
case 'left':
left = coordinates.left;
break;
case 'middle':
left = coordinates.left + (coordinates.width / 2) - (this.element.getWidth() / 2);
break;
case 'right': default:
left = coordinates.left + coordinates.width;
}
switch(this.options.alignY) {
case 'bottom':
top = coordinates.top + coordinates.height;
break;
case 'top':
top = coordinates.top - this.element.getHeight();
break;
case 'ceiling': default:
top = coordinates.top;
}
left += this.options.offsetX.toInt();
top += this.options.offsetY.toInt();
this.element.setStyles({ 'top': top, 'left': left });
},
show: function() {
if(!this.visible & !this.options.alwaysShow) {
this.visible = true;
if(!Browser.Engine.trident) {
this.element.setStyles({ 'opacity': 0, 'display': 'block' });
if(!this.options.injectInsideTarget) this.position();
this.element.set('tween', { 'duration': this.options.toggleDuration, 'transition': this.options.fadeTransition }).fade('in');
} else {
this.element.setStyles({ 'opacity': 1, 'display': 'block' });
if(!this.options.injectInsideTarget) this.position();
}
}
},
hide: function() {
if(this.visible & !this.options.alwaysShow) {
this.visible = false;
if(!Browser.Engine.trident) {
this.element.set('tween', { 'duration': this.options.toggleDuration, 'transition': this.options.fadeTransition,
'onComplete': function() { this.element.setStyle('display', 'none') }.bind(this) }).fade('out');
} else this.element.setStyle('display', 'none');
}
},
toggle: function() {
if(this.visible) this.hide();
else this.show();
},
format: function(date, format) {
if(!$defined(format)) format = this.options.format;
if(!$defined(date)) return;
format = format.replace(/%([a-z%])/gi,
function($1, $2) {
switch($2) {
case 'D': return date.get('date');
case 'n': return date.get('mo') + 1;
case 't': return (date.getTime() / 1000).toInt();
}
return '%'+ $2;
}
);
return date.format(format);
},
outsideClick: function(e) {
if(this.visible) {
var elementCoords = this.element.getCoordinates();
var targetCoords = this.target.getCoordinates();
if(((e.page.x < elementCoords.left || e.page.x > (elementCoords.left + elementCoords.width)) ||
(e.page.y < elementCoords.top || e.page.y > (elementCoords.top + elementCoords.height))) &&
((e.page.x < targetCoords.left || e.page.x > (targetCoords.left + targetCoords.width)) ||
(e.page.y < targetCoords.top || e.page.y > (targetCoords.top + targetCoords.height))) ) this.hide();
}
},
//Version 1.0.1 addition, can easily be called from outside
setDate: function(value, pick) {
if(!$defined(pick)) pick = true;
if($type(value) == 'date') {
var date = value.clearTime();
} else {
var date = $chk(value) ? new Date().parse(this.target.get('value')).clearTime() : new Date().clearTime();
}
if(date.isValid()) {
this.selectedDate = date.clone();
this.viewDate = this.selectedDate.clone().set('date', 1);
this.render();
if(pick) this.pick();
}
}
});
Style.css is
.calendar-eightysix .body {
position: relative;
}
.calendar-eightysix .body .inner .container {
position: absolute;
left: 0;
}
In jquery replace the switchContainers: function() with
switchContainers: function() {
this.currentContainer = this.currentContainer.hasClass('a') ? this.element.getElement('.container.b') : this.element.getElement('.container.a');
this.tempContainer = this.tempContainer.hasClass('a') ? this.element.getElement('.container.b') : this.element.getElement('.container.a');
this.currentContainer.empty().removeClass('month').removeClass('year-decade').setStyles({ 'opacity': 1, 'display': 'block', 'z-index': 999 });
this.tempContainer.setStyles({ 'display': 'none', 'z-index': 998 });
this.currentContainer.hasClass('a') ? this.currentContainer.setStyles({ 'opacity': 1, 'display': 'block', 'z-index': 999 }) : '';
this.label.addClass('clickable');
this.arrowLeft.setStyle('visibility', 'visible');
this.arrowRight.setStyle('visibility', 'visible');
},
In style.css
Replace the .calendar-eightysix .body .inner .container with
.calendar-eightysix .body .inner .container {
left: 0;
}

Displaying dates in Flot from timestamps

I am trying to get my graph to display dates on the x axis instead of the timestamps. I've searched and read other posts and still can't get it to budge. Here's my code:
for($i = 0; $i < 3; $i++)
{
$j = $i + 1;
$query = "SELECT UNIX_TIMESTAMP(date_added)*1000, COUNT(id)
FROM likes
WHERE date_added BETWEEN
DATE_SUB(CURDATE(), INTERVAL $j MONTH)
AND DATE_SUB(CURDATE(), INTERVAL $i MONTH)";
$result = mysql_query($query);
echo mysql_error();
$date = mysql_result($result, 0, 0);
$count = mysql_result($result, 0, 1);
$pair = array( (string)$date, (int)$count );
array_push($data_series1, $pair);
}
$.ajax({
url: 'graph_likes.php?get_data=month',
dataType: 'json',
success: function(returned) {
$.plot($('#container'),
[{
data: returned,
points:
{
show: true
},
lines:
{
show: true
},
color: '#00d6e2',
xaxis:
{
mode: 'time'
}
}]);
}
});
If you want flot to display your timestamps nicely formatted, you can try using the timestamp format option (called timeformat):
...
xaxis:
{
mode: 'time',
timeformat: "%y/%m/%d"
}
...
You find the option explained in this document: http://people.iola.dk/olau/flot/API.txt , look for the section called Time series data.

Categories