There are many web calendars in the market but
some of them are quite complicated. If we are not able to understand
the code, it becomes harder for us to customise the calendar to fit
into our existing application.
Quick Calendar Using AJAX and PHP
Online calendars are often used in many web applications. Though
popular, the logic behind creating a calendar can be scary especially
for those who are new to programming. There are many web calendars in
the market but some of them are quite complicated. If we are not able
to understand the code, it becomes harder for us to customise the
calendar to fit into our existing application. As such, we need to
create a calendar that can plug itself into any system seamlessly
without problems. Whether we are using Wordpress, Mambo/Joomla or
Drupal, we should only need to insert one line into our code for the
calendar to work. ie something like this:
<?php
require_once('quick_calendar.php');
?>
If you are already bored at this point or not interested to know how
to create a web calendar. The installation procedures is in the source code.
Other than configuring the database access for the calendar, I do
not want to change other things. With AJAX, I could even make the page
static as I navigate between different months in the calendar. In this
tutorial, I would like to share with you a simple calendar I created
that fufills the objectives discussed above. The tutorial assumes that
you have basic knowledge of PHP and SQL but don't worry, the actual
code is minimal and you should be able to customise it easily by
reading at the comments. I used PHP 4 so that it is compatible with
most servers. You should also be able to re-create the calendar easily
in other programming languages using the same logic.
The First Step: Problem Identification
Perhaps the hardest part in creating a calendar is to come up with a
good solution to display the days of the month in the correct column,
ie Monday, Tuesday..etc.
| Apr 2006 |
| Sun | Mon | Tue | Wed | Thur | Fri | Sat |
| |
|
|
|
|
|
1 |
| 2 |
3 |
4 |
5 |
6 |
7 |
8 |
| 9 |
10 |
11 |
12 |
13 |
14 |
15 |
| 16 |
17 |
18 |
19 |
20 |
21 |
22 |
| 23 |
24 |
25 |
26 |
27 |
28 |
29 |
| 30 |
|
|
|
|
|
|
Let us take April 2006 for example. There are 30 days and 6 rows in
the calendar. If we are given a day in the month, say 15, we have to
know that it falls on a saturday and is in the third row (third week).
We cannot take for granted that the first day is always the first cell
in the table (top left cell). Sometimes, we get 4 or 5 weeks in a
month. Only if we know how many days are there in a certain month and
which day the first of the month falls in only can we construct the calender as shown above.
Getting Crucial information From The PHP Date function
PHP provides a date() function that gives us alot of useful
information about the days and months of the year. To built the
calendar for any month, We need 2 important pieces of information from
the Date function, ie the "number of days in the month" and a "numeric
representation of the first day of the month".
I can get today's date easily from the following code:
// get year, eg 2006
$year = date('Y');
// get month, eg 04
$month = date('n');
// get day, eg 3
$day = date('j');
To get the number of days in this month, I will use the both the date and mktime function like so:
// get number of days in month, eg 28
$daysInMonth = date("t",mktime(0,0,0,$month,1,$year));
The numeric representation of the day of the week ranges from 0 to
6. 0 is sunday and 6 is saturday. Again, to get the numeric first day
of this month, the function mktime comes in handy.
// get first day of the month, eg 4
$firstDay = date("w", mktime(0,0,0,$month,1,$year));
The Monthly Calendar As A 2-D Array
If we look at the calendar again for April 2006, we will see that it
is actually a table(grid) filled with values starting from 1 to x (no
of days in the month). The first day of the month is a variable
though... It can occur in any day of the week. In the table, imagine
each cell as having coordinates (x,y), starting from the top left
cell as (0,0) and the bottom right cell as (5,6). In the month of
April, the first day of the month is stored in coordinate (0,6). So,
the plan now is to store the days of the month in a 2-D Array.
Firstly, we want to know the number of cells needed.
// calculate total spaces needed in array
$tempDays = $firstDay + $daysInMonth;
Then we want to know the number of rows needed.
// calculate total rows needed
$weeksInMonth = ceil($tempDays/7);
Populating The 2-D Array
Knowing the number of rows and columns in the 2-D array, we can
now fill the arrays with values using 2 for-loops. The first cell will
start with a value of 1 and the subsequent cells will have their values
increased by 1 till it reaches the end of the array.
<?php
for($j=0;$j<$weeksInMonth;$j++) {
for($i=0;$i<7;$i++) {
$counter++;
$week[$j][$i] = $counter;
}
}
?>
For the month of April, the temporary array should be something like this:
| 1 |
2 |
3 |
4 |
5 |
6 |
7 |
| 8 |
9 |
10 |
11 |
12 |
13 |
14 |
| 15 |
16 |
17 |
18 |
19 |
20 |
21 |
| 22 |
23 |
24 |
25 |
26 |
27 |
28 |
| 29 |
30 |
31 |
32 |
33 |
34 |
35 |
| 36 |
37 |
38 |
39 |
40 |
41 |
42 |
The Magic Offset
As you can see, the array above is not correct. The first day of
April, ie value 1 should be in (0,6) instead of (0,0). Remeber the
variable $firstDay? It is the numeric representation of the first day
of month which happens to be 6 in April 2006. If we subtract $firstDay
from all the values in the array, we will get the array as follows:
| -5 |
-4 |
-3 |
-2 |
-1 |
0 |
1 |
| 2 |
3 |
4 |
5 |
6 |
7 |
8 |
| 9 |
10 |
11 |
12 |
13 |
14 |
15 |
| 16 |
17 |
18 |
19 |
20 |
21 |
22 |
| 23 |
24 |
25 |
26 |
27 |
28 |
29 |
| 30 |
31 |
32 |
33 |
34 |
35 |
36 |
You should now be able to guess what we are going to do next.
Looking at the array above, you see that we already got the values we
want but we also have some unwanted values. Any number less than 1 or
more than $daysInMonth (number of days in a month) should be ignored.
<?php
function fillArray() {
// create a 2-d array
for($j=0;$j<$this->weeksInMonth;$j++) {
for($i=0;$i<7;$i++) {
$counter++;
$this->week[$j][$i] = $counter;
// offset the days
$this->week[$j][$i] -= $this->firstDay;
if (($this->week[$j][$i] < 1) || ($this->week[$j][$i] > $this->daysInMonth)) {
$this->week[$j][$i] = "";
}
}
}
}
?>
This is the core function in the entire calendar generation algorithm.
Displaying The Calendar
Getting the values right in the 2-D array, we are now ready to
display them. Now, we will create a table and start looping again using
the foreach function.
<table width="400" border="1" cellpadding="2" cellspacing="2">
<tr>
<th colspan='7'><?= date('M', mktime(0,0,0,$month,1,$year)).' '.$year; ?></th>
</tr>
<tr>
<th>Sun</th>
<th>Mon</th>
<th>Tue</th>
<th>Wed</th>
<th>Thur</th>
<th>Fri</th>
<th>Sat</th>
</tr>
<?php
foreach ($week as $key => $val) {
echo "<tr>";
for ($i=0;$i<7;$i++) {
echo "<td align='center'>$date</td>";
}
echo "</tr>";
}
?>
</table>
The final display will be like this:
| Apr 2006 |
| Sun |
Mon |
Tue |
Wed |
Thur |
Fri |
Sat |
| |
|
|
|
|
|
1 |
| 2 |
3 |
4 |
5 |
6 |
7 |
8 |
| 9 |
10 |
11 |
12 |
13 |
14 |
15 |
| 16 |
17 |
18 |
19 |
20 |
21 |
22 |
| 23 |
24 |
25 |
26 |
27 |
28 |
29 |
| 30 |
|
|
|
|
|
|
We now have a plain calendar.
Adding Special Dates To The Calendar
This calendar only tells you "the days of a week" at the moment and
is not very useful. Most online calendar will have reminders as well.
Say for example, if my birthday falls on the 4th of April, I want the
number 4 in the calendar be displayed differently, possible with a
hyperlink in which upon clicking on it, will perform some task like
redirecting me to a certain page or displaying more information about
myself in a popup windows..etc. To do that, we need to a table in the
database with at least 6 columns: id, day, month, year, link, desc.
CREATE TABLE calendar (
id INT NOT NULL AUTO_INCREMENT ,
day VARCHAR( 2 ) NOT NULL ,
month VARCHAR( 2 ) NOT NULL ,
year VARCHAR( 4 ) NOT NULL ,
link VARCHAR( 255 ) NOT NULL ,
desc TEXT NOT NULL ,
PRIMARY KEY ( id )
);
We then need to insert some data into the table for testing:
INSERT INTO calendar ( id , day , month , year , link , desc )
VALUES (
'', '24', '*', '2006', 'http://www.sitecritic.net', 'Check your web cccount on the 24th of every month. 2006 only!'
), (
'', '5', '11', '2006', 'some_javascript_funtion', 'Olympics, remember to buy ticket from alice.'
),(
'', '2', '1', '2007', 'some_javascript_funtion', 'early 2007. Any new plans for the year?'
), (
'', '9', '*', '*', 'http://www.evolt.org', 'Remember to check updates from evolt.org every month.'
);
The * under the month or year column means every month or year.
Next, we do a query and extract the important dates for a certain month and store it in an array.
<?php
$sql = "SELECT
* FROM calendar WHERE (month='$month' AND year='$year') || (month='*'
AND year='$year') || (month='$month' AND year='*') || (month='*' AND
year='*')";
$rs = $db->query($sql);
while ($rw = $rs->fetchRow()) {
extract($rw);
$links[] = array('day'=>$day', 'month'=>$month, 'year'=>$year, 'link'=>$link, 'desc'=>$desc);
}
?>
If we create a class to generate the calendar, we need to pass the $links array into the class like so:
<?php
$cal = &new Calendar($cArray, $today, $links, $css);
$cal->render();
?>
The $cArray is a class containing the array for the plain calendar as shown in step 6. The $today variable is today's date. The $links variable contains the important dates in this month. With the $css variable, we can decorate the calendar table and make it look nicer.
Adding AJAX Capability
To make the calendar more user friendly, we want to be able to
navigate easily between the months or years without refreshing the
page. Thanks to AJAX, we can now do that easily. If the user clicks on
"next month" for example, we need to call the AJAX function to refresh
the calendar without refreshing the page. We do that using
XMLHttpRequest. This is the main code that does the trick.
http.open('get', 'quick_calendar.php?m='+m+&y='+y+'&ran='+ran_no);
After
I get a response from the AJAX function, i need to update the calender.
The calendar is wrapped around with the div tag called 'quickCalender'.
I just need to rewrite the contents of the tag on the fly.
document.getElementById("quickCalender").innerHTML = http.responseText;
Conclusion and Future Improvements
In this tutorial, we went through the concept of how to create a web
calendar using AJAX and PHP. I left the details in the code to prevent
the tutorial becoming too long and indigestable. If you look at the
code hard enough, you will notice that I packed alot of codes in one
file. As a good programming practice, I should have broken them down
into smaller parts/files. Because the objective of this project is to
create a quick "plug and forget" calendar system, I did that on purpose.
Also, the object oriented approach I used in the code may not be
flexible enough if I want to have different layouts for the calendar.
The problem can be easily fixed by using inheritance, ie creating a
superclass for the QuickCalendar class. We can then have BrownCalendar,
SpecialCalendar ...etc.
Hope you enjoy reading this tutorial
|