Articles: 843 | Categories: 148   
   
   
Home Articles Contact Us
 
 
 
 
Create a Calendar (0 Comments)
Admin: Posted Date: March 3, 2010

This tutorial came in order to give a response to the different email asking me how to create a calendar similar to the one in my home page. Many of you probably have a blog in your sites, and this tutorial will show you how to make a calendar.

Create a calendar for your blog archive

1. Introduction

This tutorial came in order to give a response to the different email asking me how to create a calendar similar to the one in my home page.
Many of you probably have a blog in your sites, and this tutorial will show you how to make a calendar which will show to the users which dates have a post available.

Attention: Because all the different blog system works in different ways for the file organization you may need to change many parts of the PHP code in order to see it work. I'm actually useing the blogger service for my home page blog, so please refer to that system.

 

1.1 What I need ?

  • PHP 4.3.x
  • AMFPHP installed on your server
  • Flash MX 2004
  • An account on blogger.com

 

2. Blog installation and customization

First thing you need to have a blogger.com account. Once created the account you can set up your server settings for the file publishing policy.
Go into Settings->Archiving as shown in the image below:

settings - archiving

Now, make this changes:
blogger settings

In this way every time you create a new blog post a new file on your server will be created with a name similar to "2004_11_04_weekly.html"
All the system we are going to create will be centered on the file names!
Pay attention on the folder path where these files will be created.

 

3. The AMFPHP class

Ok, now it's time to pass to the AMFPHP class installation. It will be a very simple class with just one method for retrieving the avaialble dates.

I don't show you the gateway.php installation because there is already tutorial on this.
You need just to know that the gateway path is set to:
$gateway->setBaseClassPath(realpath("services/") . "/");

and this is my folder organization:
siteroot/flashservices/gateway.php
siteroot/flashservices/services/DateChooser.php
siteroot/blog/{weekly_files.html}

Ok, so create in your services default path a new PHP file DateChooser.php which will be our remoting service:


<?php
    class DateChooser {
        // ---------------------------------------------------------------
        // First I set the Folder where all the blog html pages are stored
        // Pasy attention with this. It's fundamental
        // ---------------------------------------------------------------
        var $base_path "./../../blog";
        // constructor
        function DateChooser() {
            $this->methodTable = array(
                "findBlogByDatePK" => array(
                    "description" => "Returns list of images in album",
                    "access" => "remote",
                    "arguments" => array ("month","year")
                )
            );
        }
        // -------------------------------------
        // public method
        // month and year are required arguments
        // -------------------------------------
        function findBlogByDatePK($month,$year)
        {
            // create the array for avail dates
            $availDate = array();
            // $availDate = new myDate();
            // check arguments
            if(empty($month) || !is_dir($this->base_path) || empty($year)){
                // return an error message
                return array("error" => $_SERVER['PATH_TRANSLATED'] . $name "is not a valid directory");
            }
            // open the default dir
            $dir = @opendir($this->base_path);
            if(!$dir){
                // return error on fails
                return array("error" => $_SERVER['PATH_TRANSLATED'] . $name " cannot open selected directory");                
            }
            while($file readdir($dir))
            {
                // get month value from file name
                $_month substr($file,5,2);
                // get year value from file name
                $_year  substr($file,0,4);
                // compare to arguments passed
                if(number_format($_month,0) == number_format($month,0) && number_format($year,0) == number_format($_year,0))
                {
                    $_date number_format(substr($file,8,2),0);
                    array_push($availDate$_date);
                }
            }
            return $availDate;
        }
    }
?>

First:

<?php class DateChooser { // First I set the Folder where all the blog html pages are stored // Pasy attention with this. It's fundamental var $base_path = "./../../blog";

Remember that always your class name must be the same as your php file name!
Then var $base_path must point to the correct path of your blog html file!

You can see in this picture how are organized my directories :

folders

In fact my service php file DateChooser has to go to twice to parent folder, then into blog folder.

function DateChooser() { $this->methodTable = array( "findBlogByDatePK" => array(

Inside the DateChooser constructor there is the methodtable array in which we just need to define 1 method "findBlogByDatePK" .
So, let's analyze the code of that method:

 

function findBlogByDatePK($month,$year) { // create the array for avail dates $availDate = array(); // check arguments if(empty($month) || !is_dir($this->base_path) ||empty($year)){ // return an error message return array("error" => $_SERVER['PATH_TRANSLATED'] . $name . "is not a valid directory"); }

Ok, first consideration. In order to work correctly flash must pass as arguments month and year in numberic formart (remember that in flash month value starts from '0' to '11').
If these arguments are empty or if the base_path directory assigned is not a valid dir, then return an error message.

// open the default dir $dir = @opendir($this->base_path); if(!$dir){ // return error on fails return array("error" => $_SERVER['PATH_TRANSLATED'] . $name . " cannot open selected directory"); }

try to open the directory for reading, otherwise return an error message again.

while($file = readdir($dir)) { // get month value from file name $_month = substr($file,5,2); // get year value from file name $_year =substr($file,0,4); // compare to arguments passed if(number format($_month,0) ==number format($month,0) && number format($year,0) ==number format($_year,0)) { $_date = number format(substr($file,8,2),0); array push($availDate, $_date); } } return $availDate; }

Now, the core of this method.
With the opened directory make a while loop and read all the files into that path. Retrive the file name and compare it with the arguments passed by flash
2004_11_01_weekly.html will be processed as this:
- $_month = "11"
- $_year = "2004"

then is both month and year are the same as the arguments ($month, $year) this means that this file is what we're looking for!
Then add the date substring of this filename to the array to be returned to flash. (We don't need to give back month and year values, but only the date value)

In this way, an example debug withing flash should return something similar to these pictures:

remoting call

remoting result

In the params given to PHP: 2 means "february" and 2004 is the year.
PHP has returned an array of 2 elements: 4 and 9. This means that we should activate only these two dates in our calendar.

4. Using the DateChooser component in Flash MX 2004

We just need the pre-installed DateChooser component in our flash movie. Nothing more.
So, drag the DateChooser component from the UI component of your Flash mx 2004 program and give it the instancename of "calendar" .

Now create 3 layers above the current: "AMFPHP","syles" and "listener". I prefer to separate the different actions in different layers.

4.1 Customize the Component

In the "styles" layer just put some code for customize the component:


this.calendar.setStyle("fontSize", "10")
this.calendar.setStyle("embedFonts", false)
this.calendar.setStyle("fontFamily", "Georgia")
this.calendar.setStyle("fontWeight ", "bold")
this.calendar.setStyle("borderColor ", 0xFFFFFF)
this.calendar.setStyle("borderStyle", "none")
this.calendar.setStyle("themeColor", "haloBlue")
this.calendar.setStyle("disabledColor", 0x999999)
this.calendar.setStyle("color", 0x000000)

4.2 Add a Event Listener to the Calendar


// -----------------------
// Calendar EVENT Listener
// -----------------------
objInit = new Object();
// When month cnages
objInit.scroll = function(obj){
    callServ(obj.target.displayedMonth,obj.target.displayedYear);
}
// click on a date item
objInit.change = function(obj){
    var d:Date = obj.target.selectedDate
    var mm = d.getMonth() + 1
    mm = mm < 10 ? "0" add mm : mm
    var yy = d.getFullYear()
    var dd = d.getDate()
    dd = dd < 10 ? "0" add dd : dd
    // open the browser passing the selected date as GET param
    getURL("/index.php?blogId=" add yy add "_" add mm add "_" add dd add "_weekly.html")
}
// ---------------------------------
// Make the remoting call
// ---------------------------------
function callServ(m,y){    
    serv.findBlogByDatePK(m + 1, y);
    this.calendar.enabled = false    
}
// ---------------------------
// call the service first time
// ---------------------------
callServ(this.calendar.displayedMonth, this.calendar.displayedYear);
// ----------------------
// add the event listener
// ----------------------
this.calendar.addEventListener("scroll", objInit);
this.calendar.addEventListener("change", objInit);

-------
So first we've created an Object listener "objInit" for the DateChooser Component events, and at the end we've assigned to the component itself with the command addEvetListener.
This object event has 2 methods:

  • scroll: this make an action when user click on the arrows for change the month displayed. This just call the remoting service passing as params the month and year to be displayed
  • change: a day in the compoonent has been selected. This check the date selected and compose an URL string to be passed as GetURL

The callServ function make calls the findBlogByDatePK on the remoting service and makes the calendar disabled in the meantime. We increase the month param by one because flash starts from '0' to calculate month values, while the files saved in our blog directory has the standard month values, starting fom 1 to 12.

4.3 AMFPHP services

#include "NetServices.as"
#include "NetDebug.as"
// -----------------------
// AMFPHP Object Responder
// -----------------------
myDC = {};
myDC.scope = this
// listener for findBlogByDatePK service call
myDC.findBlogByDatePK_Result = function(data){
    // enable the calendar again
    this.scope.calendar.enabled = true
    // disabled dates array
    var dRanges = new Array();
    // enabled dates array - lenght 31
    var eRanges = new Array(31);
    for(var a in data){
        // put the date available as key in the enabled dates array
        eRanges[int(data[a])] = true;
    }
    // walk in the enabled array
    for(var a = 1; a <= eRanges.length; a++){
        // format a new date
        var sDate = new Date(this.scope.calendar.displayedYear, this.scope.calendar.displayedMonth, int(a));
        // if value is not true this date is not available
        if(eRanges[a] != true){
            dRanges.push({rangeStart: sDate, rangeEnd: sDate});
        }
    }
    // apply disabled dates
    this.scope.calendar.disabledRanges = dRanges;
}
// ----------------------------
// Make the Remoting Connection
// ----------------------------
if(gatewayURL == undefined){
    gatewayURL = "http://localhost/flashservices/gateway.php";
}
NetServices.setDefaultGatewayUrl (gatewayURL);
conn = NetServices.createGatewayConnection ();
// select the service to be consumed
serv = conn.getService ("DateChooser", myDC);

Ok, analyze it now!

First create a default responder for any remoting call "myDC" and assign it the current scope with myDC.scope = this .
In fact we will assign this responder to the current remoting service at the end: serv = conn. getService (" DateChooser ", myDC);
This means that all the response request to the DateChooser.php file will be redirected to the myDC functions.

This function :
myDC.findBlogByDatePK_Result = function ( data ){

will be called when the server get a result response due to a call to the remote method findBlogByDatePK. and it's in this function that we will enable/disable certain dates in our calendar.
In fact:
first create two different arrays:
var dRanges = new Array ();
the array containing all the disabled dates

var eRanges = new Array (31);
the array (lenght = 31) of all the enabled dates

Now, get all the data argument passed values and assign them as key of our eRanges array (giving them the value true)
for ( var a in data ){
         eRanges[ int ( data [a])] = true ;
     }


For every element of the eRanges array (31 elements... max length of a month days), create a new Date variable and set its value corrsponding to the key number of the current eRanges array. This means: for every key of the eRanges arra (from 1 to 31) create a Date variables with the data value from 1 to 31.
if the current key element, in the eRanges array (we populated it in the previoius for loop, remember?) is not true, we append this value in the dRanges array:

for ( var a = 1; a <= eRanges. length ; a++){
var sDate = new Date ( this .scope.calendar.displayedYear, this .scope.calendar.displayedMonth, int (a));
if (eRanges[a] != true ){
dRanges. push ({rangeStart: sDate, rangeEnd: sDate});
}
}

So, finally we can assign to the component the disabled dates, using a property of the component itself:

this .scope.calendar.disabledRanges = dRanges;

 

 

 
 

 

 

 
 
Add a Comment:
 
(You must be signed in to comment on an article. Not a member? Click here to register)
   
Title:

Comments: