| |
Create a Dynamic Event Calendar in Flex Builder 3 with Actionscript 3.0 |
|
This tutorial will allow readers to create an Event Calendar application using Flex. The final user will be able to plan over a daily, weekly or monthly plan.
You will learn on this step by step Flex tutorial, to create from scratch those Graphic User Interfaces, integrate them, and create a complete Rich Internet Application with a professional look.
Requirements
Flex Builder Try/Buy
Pre-Requisites
This tutorial assumes that you have fair knowledge of OOPs, Flex framework, AIR and Actionscript 3.0
You know basic concept of writing a Class file which could use inheritance, polymorphism etc.
Step1: Getting Started
Before starting with the tutorial have a look what we are going to achieve from this tutorial, click on the View Demo button.
Firstly lets setup a AIR project in Flex Builder, you need to follow below steps to start with:-
- Open Flex Builder.
- Select File > New > Flex Project drop down menu.
- Type “Project name” as “Flex Event Calendar “.
- Choose “Application type” as “Desktop application(runs in Adobe Air)” .
- Click Next.
- Ensure Output folder should be bin-debug.
- Click Next.
- Ensure Main application file is “main.mxml”.
- Click Finish
Graphical walk through of above steps is as follows:

Figure 1.1

Figure 1.2

Figure 1.3
Step 2: Define application settings
Before starting with actual code lets do some basic settings which will allow our application to give a define look and feel. So first of all open code view of main.mxml file and write below MXML code in it.
<?xml version="1.0" encoding="utf-8"?> <mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" width="1000" height="620" horizontalScrollPolicy="off" verticalScrollPolicy="off"> </mx:WindowedApplication>
Now open main-app.xml file to define some settings for AIR application. In this file majority we would define application name and dimension related settings. Below is the code of my main-app.xml which you could simple copy and paste in your xml file.
<?xml version="1.0" encoding="UTF-8"?> <application xmlns="http://ns.adobe.com/air/application/1.0"> <!-- Adobe AIR Application Descriptor File Template. Specifies parameters for identifying, installing, and launching AIR applications. xmlns - The Adobe AIR namespace: http://ns.adobe.com/air/application/1.1 The last segment of the namespace specifies the version of the AIR runtime required for this application to run. minimumPatchLevel - The minimum patch level of the AIR runtime required to run the application. Optional. --> <!-- The application identifier string, unique to this application. Required. --> <id>main</id> <!-- Used as the filename for the application. Required. --> <filename>main</filename> <!-- The name that is displayed in the AIR application installer. May have multiple values for each language. See samples or xsd schema file. Optional. --> <name>Event Calendar</name> <!-- An application version designator (such as "v1", "2.5", or "Alpha 1"). Required. --> <version>v1</version> <!-- Description, displayed in the AIR application installer. May have multiple values for each language. See samples or xsd schema file. Optional. --> <description>Add multiple events in a day.</description> <!-- Copyright information. Optional --> <!-- <copyright></copyright> --> <!-- Settings for the application's initial window. Required. --> <initialWindow> <!-- The main SWF or HTML file of the application. Required. --> <!-- Note: In Flex Builder, the SWF reference is set automatically. --> <content>[This value will be overwritten by Flex Builder in the output app.xml]</content> <!-- The title of the main window. Optional. --> <!-- <title></title> --> <!-- The type of system chrome to use (either "standard" or "none"). Optional. Default standard. --> <!-- <systemChrome></systemChrome> --> <!-- Whether the window is transparent. Only applicable when systemChrome is none. Optional. Default false. --> <!-- <transparent></transparent> --> <!-- Whether the window is initially visible. Optional. Default false. --> <!-- <visible></visible> --> <!-- Whether the user can minimize the window. Optional. Default true. --> <!-- <minimizable></minimizable> --> <!-- Whether the user can maximize the window. Optional. Default true. --> <maximizable>false</maximizable> <!-- Whether the user can resize the window. Optional. Default true. --> <!-- <resizable></resizable> --> <!-- The window's initial width. Optional. --> <!-- <width></width> --> <!-- The window's initial height. Optional. --> <!-- <height></height> --> <!-- The window's initial x position. Optional. --> <!-- <x></x> --> <!-- The window's initial y position. Optional. --> <!-- <y></y> --> <!-- The window's minimum size, specified as a width/height pair, such as "400 200". Optional. --> <!-- <minSize></minSize> --> <!-- The window's initial maximum size, specified as a width/height pair, such as "1600 1200". Optional. --> <!-- <maxSize></maxSize> --> </initialWindow> <!-- The subpath of the standard default installation location to use. Optional. --> <!-- <installFolder></installFolder> --> <!-- The subpath of the Windows Start/Programs menu to use. Optional. --> <!-- <programMenuFolder></programMenuFolder> --> <!-- The icon the system uses for the application. For at least one resolution, specify the path to a PNG file included in the AIR package. Optional. --> <!-- <icon> <image16x16></image16x16> <image32x32></image32x32> <image48x48></image48x48> <image128x128></image128x128> </icon> --> <!-- Whether the application handles the update when a user double-clicks an update version of the AIR file (true), or the default AIR application installer handles the update (false). Optional. Default false. --> <!-- <customUpdateUI></customUpdateUI> --> <!-- Whether the application can be launched when the user clicks a link in a web browser. Optional. Default false. --> <!-- <allowBrowserInvocation></allowBrowserInvocation> --> <!-- Listing of file types for which the application can register. Optional. --> <!-- <fileTypes> --> <!-- Defines one file type. Optional. --> <!-- <fileType> --> <!-- The name that the system displays for the registered file type. Required. --> <!-- <name></name> --> <!-- The extension to register. Required. --> <!-- <extension></extension> --> <!-- The description of the file type. Optional. --> <!-- <description></description> --> <!-- The MIME type. Optional. --> <!-- <contentType></contentType> --> <!-- The icon to display for the file type. Optional. --> <!-- <icon> <image16x16></image16x16> <image32x32></image32x32> <image48x48></image48x48> <image128x128></image128x128> </icon> --> <!-- </fileType> --> <!-- </fileTypes> --> </application>
Step 3: Place required components in main.mxml
Before starting with the core logic of the code we need to place various buttons and other flex components which will allow us to give a feel of first page of our application. To do so we need to write following set of code in main.mxml file.
<mx:Script>
<![CDATA[
/* Current date will be bound all views */
[Bindable]
private var m_intCurrentDate:Date;
/* Function will execute on creation complete of main.mxml */
private function onApplicationStart():void
{
var objDate:Date = new Date();
dtPicker.selectedDate = objDate;
onDateChange();
}
/* Custom Events */
private function onDateScroll():void
{
onDateChange();
}
private function onDateChange():void
{
m_intCurrentDate = new Date(dtPicker.displayedYear, dtPicker.displayedMonth, dtPicker.selectedDate.date);
}
private function onDayClick():void
{
stackViews.selectedIndex = 0;
}
private function onWeekClick():void
{
stackViews.selectedIndex = 1;
}
private function onMonthClick():void
{
stackViews.selectedIndex = 2;
}
]]>
</mx:Script>
<mx:Button x="9" y="10" label="Day" click="onDayClick()"/>
<mx:Button x="62" y="10" label="Week" click="onWeekClick()"/>
<mx:Button x="52" y="251" label="Add Event" />
<mx:Button x="124" y="10" label="Month" click="onMonthClick()"/>
<mx:DateChooser x="7" y="39" id="dtPicker" scroll="onDateScroll()" change="onDateChange()" showToday="true" yearNavigationEnabled="true"/>
<mx:ViewStack x="200" y="0" id="stackViews" width="100%" height="100%">
</mx:ViewStack>
<mx:TextArea x="10" y="336" height="104" fontWeight="normal" textAlign="center" borderStyle="none" backgroundAlpha="0.0" selectable="false" editable="false" color="#0367FC" fontSize="12">
<mx:htmlText><![CDATA[Click on a button in <b>Day or Week</b> view and then click <b>Add Event</b> button to add an event on particular date and time.]]></mx:htmlText>
</mx:TextArea>
Lets have a look on the output to understand what we achieve till now.
Step 4: Creating different views & mxml components
In this step we will create different views and other mxml components which will be used by these views. These views consist following items:
- Day View
- Week View
- Month View
- Event Form
Day view will further use “hourCell.mxml” and “hourCellLeftStrip.mxml”. Week view will use “hourCell.mxml”, “hourCellLeftStrip.mxml” and “weekCell.mxml”. Whereas Month view will use “monthCell.mxml”. In addition all these views are using “skin.css” file to use various colors and styles. Lets start with creating folders for these files then we will create mxml file and thereafter we would writing code for above views.
To create various folders just open “Flex Navigator” pane do right click on “src” folder and select “New > folder” from the drop down, refer to below Figure 4.1.

Figure 4.1
Once New Folder window is shown follow below points to create different folders:-
- type “styles” in Folder name and click Finish.
- Again open New folder window and type “mxml_views” in Folder name and click Finish.
- Again open New folder window and type “classes/views” in Folder name and click Finish.
- Again open New folder window and type “classes/utils” in Folder name and click Finish.
- Again open New folder window and type “classes/skins” in Folder name and click Finish.
- Again open New folder window and type “classes/model” in Folder name and click Finish.
- Again open New folder window and type “classes/events” in Folder name and click Finish.
We are now through with folder creation. If I say you to show screen-shot of Flex Navigator at the moment it should be look like below Figure 4.2.

Figure 4.2
Very first class file which we needs to create is ButtonSkin.as. We will use this class in css file of the application, this class allows to create a skin for Flex button component.We will create this class under classes/skins folder, to create it do right click on skins folder and select New > ActionScript Class. Type class name as “ButtonSkin” and Superclass as “mx.skins.ProgrammaticSkin”. Click Finish. Refer to below Figure 4.3 for creating this class.

Figure 4.3
ButtonSkin.as: A very small yet useful class which defines the Skin of Flex Button component. This class is being used by “btnDayItems” style defined in skin.css file. Below is the code for the same.
package classes.skins { // Use unnamed package if this skin is not in its own package.
// Import necessary classes here.
import flash.display.GradientType;
import flash.display.Graphics;
import flash.display.SpreadMethod;
import flash.geom.Matrix;
import mx.skins.ProgrammaticSkin;
public class ButtonSkin extends ProgrammaticSkin {
public var backgroundFillColor:Number;
// Constructor.
public function ButtonSkin() {
// Set default values.
backgroundFillColor = 0xFFFFFF;
}
override protected function updateDisplayList(w:Number, h:Number):void {
// Depending on the skin's current name, set values for this skin.
switch (name) {
case "upSkin":
backgroundFillColor = 0xFFFFFF;
break;
case "overSkin":
backgroundFillColor = 0x7fc4ff;
break;
case "downSkin":
backgroundFillColor = 0x7fc4ff;
break;
case "disabledSkin":
backgroundFillColor = 0xCCCCCC;
break;
}
var g:Graphics = graphics;
g.clear();
g.beginFill(backgroundFillColor);
g.drawRect(0, 0, w, h);
g.endFill();
}
}
} // Close unnamed package.
The second file which we needs to create is “skin.css”. To create it right click on styles folder and select New > CSS File from the dropdown menu. Type file name as “skin” and write below code in this file.
skin.css: skin.css defines all styles that are used in Event Calendar application. Copy below code in your skin.css file.
/* CSS file */
/* Textarea used in month view to display event description */
TextArea.txtArea
{
borderStyle: none;
}
/* Skins for buttons used in week and day view */
Button.btnDayItems
{
upSkin:ClassReference('classes.skins.ButtonSkin');
overSkin:ClassReference('classes.skins.ButtonSkin');
downSkin:ClassReference('classes.skins.ButtonSkin');
disabledSkin:ClassReference('classes.skins.ButtonSkin');
selectedUpSkin:ClassReference('classes.skins.ButtonSkin');
selectedOverSkin:ClassReference('classes.skins.ButtonSkin');
selectedDownSkin:ClassReference('classes.skins.ButtonSkin');
selectedDisabledSkin:ClassReference('classes.skins.ButtonSkin');
textAlign: left;
paddingBottom: 0;
}
/* title for showing date used in day and week view */
Label.lblViewTitle
{
fontWeight: bold;
textAlign: left;
color: #FFFFFF;
}
/* global button styles */
Button
{
fillAlphas: 0.6, 0.6, 0.6, 0.6;
fillColors: #FFFFFF, #CCCCCC;
}
/* Grid styles, used in month view */
Grid.grdMonthView
{
horizontalGap: 0;
verticalGap: 0;
}
/*used for showing day's name in week view */
Label.lblDaysNames
{
fontWeight: bold;
color: #FFFFFF;
}
/* Global HRule style */
HRule
{
shadowColor: #004C7C;
}
/* Application controlbar style, used in all 3 views */
ApplicationControlBar.appBarDayCell
{
fillAlphas: 1.0, 1.0;
fillColors: #7FC4FF, #52AACA;
cornerRadius: 0;
paddingTop: 2;
}
/* Canvas used as base of month cell */
Canvas.canDayCellBase
{
backgroundColor: #FFFFFF;
borderStyle: solid;
borderColor: #88C4EE;
}
/* hours label used in day and week view */
Label.lblHours
{
color: #FFFFFF;
fontFamily: Verdana;
fontSize: 12;
}
/* mins label used in day and week view */
Label.lblMins
{
color: #FFFFFF;
fontFamily: Verdana;
fontSize: 10;
}
/* Embed Verdana font in application */
@font-face
{
fontFamily: Verdana;
fontWeight: normal;
fontStyle: normal;
src: local("Verdana");
}
@font-face
{
fontFamily: Verdana;
fontWeight: Bold;
fontStyle: normal;
src: local("Verdana");
}
Now we need to create various MXML components which will be used by different views or by the application. All these MXML files needs to be created in mxml_views folder to do that right click on mxml_views folder and select New > MXML Component.
EventForm.mxml: EventForm defines looks of event form which allow to save an event on the basis of certain parameters like date and time. These values are passed by CommonUtils class which we discuss later in this tutorial. To create do right click on mxml_views folder and select New > MXML Component and then copy below code in the file.
<?xml version="1.0" encoding="utf-8"?>
<mx:Panel xmlns:mx="http://www.adobe.com/2006/mxml"
horizontalScrollPolicy="off"
verticalScrollPolicy="off"
layout="absolute"
width="200"
height="318" title="Choose Time & write details">
<mx:Script>
<![CDATA[
import classes.model.DataHolder;
/* selected index of hour drop down menu */
[Bindable]
public var hour:int;
/* selected index of meridiem drop down menu */
[Bindable]
public var meridiem:int;
/* selected index of minutes drop down menu */
[Bindable]
public var mins:int;
/* current selected date in any of the views */
[Bindable]
public var currentDate:Date;
/* description of the event */
[Bindable]
public var description:String = "";
/* Event for Save button */
private function onSaveButtonClick():void
{
var obj:Object = new Object();
obj.date = currentDate;
obj.hour = cmbHours.selectedItem.data;
obj.meridiem = cmbMeridiem.selectedItem.data;
obj.mins = cmbMins.selectedItem.data;
obj.desc = txtDescription.text;
DataHolder.getInstance().addEvent(obj);
}
]]>
</mx:Script>
<mx:Canvas height="119" width="100%" y="7" x="9">
<mx:Label text="Hours" />
<mx:ComboBox id="cmbHours" selectedIndex="{hour}" y="19">
<mx:dataProvider>
<mx:Array>
<mx:Object label="12" data="12" />
<mx:Object label="1" data="1" />
<mx:Object label="2" data="2" />
<mx:Object label="3" data="3" />
<mx:Object label="4" data="4" />
<mx:Object label="5" data="5" />
<mx:Object label="6" data="6" />
<mx:Object label="7" data="7" />
<mx:Object label="8" data="8" />
<mx:Object label="9" data="9" />
<mx:Object label="10" data="10" />
<mx:Object label="11" data="11" />
</mx:Array>
</mx:dataProvider>
</mx:ComboBox>
<mx:Label text="AM/PM" y="57"/>
<mx:ComboBox id="cmbMeridiem" selectedIndex="{meridiem}" y="78">
<mx:dataProvider>
<mx:Array>
<mx:Object label="AM" data="am" />
<mx:Object label="PM" data="pm" />
</mx:Array>
</mx:dataProvider>
</mx:ComboBox>
<mx:Label text="Mins" x="70" width="47"/>
<mx:ComboBox id="cmbMins" selectedIndex="{mins}" y="19" x="70">
<mx:dataProvider>
<mx:Array>
<mx:Object label="00" data="0" />
<mx:Object label="30" data="30" />
</mx:Array>
</mx:dataProvider>
</mx:ComboBox>
</mx:Canvas>
<mx:FormItem y="124" label="Description" />
<mx:TextArea id="txtDescription" width="100%" height="89" y="146" x="9" text="{description}"/>
<mx:HBox width="100%" horizontalAlign="center" y="243">
<mx:Button id="btnSave" label="Save" click="onSaveButtonClick()" />
<mx:Button id="btnClose" label="Close" click="{this.visible=false;}" />
</mx:HBox>
</mx:Panel>
hourCell.mxml: hourCell.mxml file allows to show two buttons i.e. first and second half of an hour. This mxml is being used in a loop while generating day and week view. To create do right click on mxml_views folder and select New > MXML Component and then copy below code in the file.
<?xml version="1.0" encoding="utf-8"?> <!-- Buttons/Child view for showing hour strip used in day view and month view --> <mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml" width="720" height="50" backgroundColor="#FFFFFF" xmlns:mxmlViews="mxml_views.*"> <mx:Button x="0" y="0" width="100%" height="50%" styleName="btnDayItems" id="btnFirstHalf"/> <mx:Button x="0" width="100%" styleName="btnDayItems" bottom="0" height="25" id="btnSecondHalf"/> <mx:HRule x="0" top="25" strokeWidth="1" width="100%" strokeColor="#ECECEC"/> <mx:HRule x="0" width="100%" strokeColor="#88C4EE" bottom="0" strokeWidth="1"/> </mx:Canvas>
hourCellLeftStrip.mxml: This file is also used in day and week view but to show a blue colored strip which shows hour numbers. To create do right click on mxml_views folder and select New > MXML Component and then copy below code in the file.
<?xml version="1.0" encoding="utf-8"?> <!-- LEFT BKUE SIDE OF DAY AND WEEK VIEW. SHOWS HOURS --> <mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml" x="0" y="0" width="70" height="50" backgroundColor="#7FC4FF"> <mx:Label x="7" y="15" text="24" width="57" height="30" styleName="lblHours" id="lblHours"/> <mx:Label x="26" y="6" text="00" width="37" height="30" styleName="lblMins" id="lblMins"/> <mx:HRule bottom="0" width="62" strokeColor="#FFFFFF" left="4" strokeWidth="1"/> <mx:VRule x="68" y="0" height="100%" strokeColor="#004C7C"/> </mx:Canvas>
monthCell.mxml: This file is being used in Month view and show square boxes which further allow Month view to show description of an event if exist on a particular day in that month.To create do right click on mxml_views folder and select New > MXML Component and then copy below code in the file.
<?xml version="1.0" encoding="utf-8"?> <!-- MONTH CELL IS USED IN MONTH VIEW TO SHOW SQUARE BOXES DESCRIPTION TEXT IS USED TO SHOW EVENT'S DESCRIPTION --> <mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml" width="115" height="112" styleName="canDayCellBase"> <mx:ApplicationControlBar id="canHeader" x="0" y="-3" height="22" width="100%" styleName="appBarDayCell"> <mx:Label width="90" height="16" id="lblDate" color="#FFFFFF" fontWeight="bold" styleName="lblHours"/> </mx:ApplicationControlBar> <mx:TextArea x="3" y="28" width="95%" height="70%" editable="false" selectable="false" id="txtDesc" styleName="txtArea"/> </mx:Canvas>
weekCell.mxml: weekCell is basically header file for week view which shows day names. It also contains an empty Canvas container which used by Week view to add hour items. To create do right click on mxml_views folder and select New > MXML Component and then copy below code in the file.
<?xml version="1.0" encoding="utf-8"?> <!-- WEEK CELL IS USED TO DISPLAY BLUE BOXES IN WEEK VIEW, THESE BLUE BOXES CONTAINS HOUR STRIP JUST LIKE DAY VIEW SHOWS --> <mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml" width="103" horizontalScrollPolicy="off" verticalScrollPolicy="off" backgroundColor="#7FC4FF"> <mx:ApplicationControlBar id="canHeader" y="0" height="22" width="100" styleName="appBarDayCell"> <mx:Label id="lblDate" width="100%" text="asd" styleName="lblViewTitle" textAlign="center"/> </mx:ApplicationControlBar> <mx:Canvas id="canDayView" width="100" verticalScrollPolicy="off" horizontalScrollPolicy="off" y="22" /> </mx:Canvas>
So, We are gone through all mxml files and now we are left with writing the core classes but before proceeding with those lets have a look at Flex Navigator screen-shot so we stand on a same plain. Please refer to Figure 4.4

Figure 4.4
Step 5: Writing Core Classes
Lets start writing core classes which will allow to generate actual views. These classes will use above MXML files as well. we will go one by one and create these classes. Very first class which we need to start with is “DataHolder.as”.
DataHolder.as: This class is used as database for Event Calendar application. All views if needs to store any kind of data they will use this class and not for only storing in case they need to check any stored data they only get that data from this class and then uses accordingly. DataHolder resides under classes/model folder. This class also uses EventDispatcher class to dispatch event to Main application file whenever a new Event is added by any of the views. To create this class do right click on model folder and select New > ActionScript Class, use below code to populate this class.
package classes.model
{
import classes.events.CustomEvents;
import flash.events.EventDispatcher;
/**
* DataHolder class represent all data which needs to be stored
* or needs to be used by any of the classes.
* It also dispatches events on adding a new event from any of the views.
* It is a singletone class so only single instance will be created through out the application cycle.
*/
public class DataHolder extends EventDispatcher
{
import flash.events.EventDispatcher;
public static var objDataHolder:DataHolder;
private var m_arrEvents:Array;
public function DataHolder()
{
m_arrEvents = new Array();
}
// return class instance and if it is not created then create it first and the return.
public static function getInstance():DataHolder
{
if(objDataHolder == null)
{
objDataHolder = new DataHolder;
}
return objDataHolder;
}
// will add any event. used by day view and week view to do so.
public function addEvent(_obj:Object):void
{
m_arrEvents.push(_obj);
updateViews();
}
// dispatch event to main.mxml to update views as per new event added
private function updateViews():void
{
dispatchEvent(new CustomEvents(CustomEvents.ADD_NEW_EVENT));
}
// currently not being used but could be used when we need to add a functionality of removing an event
public function removeEventAt(index:int):void
{
m_arrEvents.splice(index, 1);
}
// set and get dataprovider, which store all event related data
public function set dataProvider(_arrEvents:Array):void
{
m_arrEvents = _arrEvents;
}
public function get dataProvider():Array
{
return m_arrEvents;
}
}
}
CustomEvents.as: This class is extended to Event class and used to dispatch any event from any of the classes, additionally this class allows to send a object while listening to the event. So in case there is a requirement to send specific data to the listener then this class a great help to do so. To create this class do right click on events folder and select New > ActionScript Class, use below code to populate this class.
package classes.events
{
import flash.events.Event;
/**
* CUSTOM EVENTS CLASS WILL ALLOWS TO DISPATCH EVENTS
* ALONG WITH A OBJECT WHICH SHOULD BE PASSED WHILE DISPATCHING THE EVENT
* THIS OBJECT COULD STORE ANY THING AND CAN BE USED WHILE LISTENING TO THE EVENT
*
* EXTENDS TO EVENT CLASS
*/
public class CustomEvents extends Event
{
public static const MONTH_VIEW_CLICK:String = "monthViewClick";
public static const ADD_NEW_EVENT:String = "addNewEvent";
public var object:Object;
public function CustomEvents(type:String, obj:Object = null, bubbles:Boolean=false, cancelable:Boolean=false)
{
object = obj;
super(type, bubbles, cancelable);
}
}
}
CommonUtils.as: This class resides under classes/utils folder. As per the name it is a common class which is being used by other classes. All functions are public so any class could use that as per the requirement. This class also fire events for buttons in day and week view which allows Event Form to fetch the required data. To create this class do right click on utils folder and select New > ActionScript Class, use below code to populate this class.
package classes.utils
{
import classes.model.DataHolder;
import flash.events.MouseEvent;
import mx.containers.Canvas;
import mx.controls.Button;
import mx.utils.ObjectUtil;
import mxml_views.hourCell;
import mxml_views.hourCellLeftStrip;
/**
* COMMON UTILS CLASS CONATINS ALL COMMON FUNCTIONS/VARIABLES
* WHICH COULD BE USED BY DIFFERENT CLASSES OR VIEWS
*/
public class CommonUtils
{
// used to send values to Event Form
[Bindable]
public static var hour:int
// used to send values to Event Form
[Bindable]
public static var meridiem:int;
// used to send values to Event Form
[Bindable]
public static var mins:int;
// used to send values to Event Form
[Bindable]
public static var description:String;
// used to send values to Event Form
[Bindable]
public static var currentDate:Date;
// Constructor
public function CommonUtils()
{
}
/**
* returns day name for a particular day number in a week
*/
public static function getDayName(_intDayNumber:int):String
{
_intDayNumber++;
switch (_intDayNumber)
{
case 1:
return "Sunday";
break;
case 2:
return "Monday";
break;
case 3:
return "Tuesday";
break;
case 4:
return "Wednesday";
break;
case 5:
return "Thursday";
break;
case 6:
return "Friday";
break;
case 7:
return "Saturday";
break;
default:
return "no day";
}
}
/**
* returns day count for a month
*/
public static function getDaysCount(_intMonth:int, _intYear:int):int
{
_intMonth ++;
switch (_intMonth)
{
case 1:
case 3:
case 5:
case 7:
case 8:
case 10:
case 12:
return 31;
break;
case 4:
case 6:
case 9:
case 11:
return 30;
break;
case 2:
if((_intYear % 4 == 0 && _intYear % 100 != 0) || _intYear % 400 ==0)
{
return 29;
}
else
{
return 28;
}
break;
default:
return -1;
}
}
/**
* creates blue color strip which shows hours in week and day view
*/
public static function createLeftHourStrip(_parent:Canvas):void
{
for(var i:int=0; i<24; i++)
{
var strLabel:String = "";
var objLeftStrip:hourCellLeftStrip = new hourCellLeftStrip();
objLeftStrip.y = objLeftStrip.height * i;
_parent.addChild(objLeftStrip);
if(i == 0)
{
objLeftStrip.lblMins.text = "am";
}
else if(i == 12)
{
objLeftStrip.lblMins.text = "pm";
}
else
{
objLeftStrip.lblMins.text = "00";
}
if(i == 0)
{
strLabel = "12";
}
else if(i>12)
{
strLabel = String(i-12);
}
else
{
strLabel = String(i);
}
strLabel = (strLabel.length < 2) ? ("0" + strLabel) : strLabel;
objLeftStrip.lblHours.text = strLabel;
}
}
/**
* creates right strip which shows buttons in week and day view. which allow user to set
* some new events on a particular time.
*/
public static function createRightHourStrip(_parent:Canvas, _savedDate:Date = null):void
{
for(var i:int=0; i<24; i++)
{
var strLabel:String;
var objHourCell:hourCell = new hourCell();
objHourCell.y = objHourCell.height * i;
_parent.addChild(objHourCell);
if(i == 0)
{
strLabel = "12";
}
else if(i>12)
{
strLabel = String(i-12);
}
else
{
strLabel = String(i);
}
strLabel = (strLabel.length < 2) ? ("0" + strLabel) : strLabel;
var dt:* = _savedDate != null ? new Date(_savedDate.getFullYear(), _savedDate.month, _savedDate.date) : null;
objHourCell.data = {date: dt, time: strLabel, meridiem: (i < 12? "am" : "pm")};
// check if event already saved for current time then show its description
for(var j:int=0; j<DataHolder.getInstance().dataProvider.length; j++)
{
var obj:Object = DataHolder.getInstance().dataProvider[j];
if(ObjectUtil.dateCompare(obj.date, _savedDate) == 0)
{
if(obj.hour == strLabel && obj.meridiem == objHourCell.data.meridiem)
{
if(obj.mins == 0)
{
objHourCell.btnFirstHalf.label = obj.desc;
}
else
{
objHourCell.btnSecondHalf.label = obj.desc;
}
}
}
}
// click event for buttons of first and second half
objHourCell.btnFirstHalf.addEventListener(MouseEvent.CLICK, onDayViewClick);
objHourCell.btnSecondHalf.addEventListener(MouseEvent.CLICK, onDayViewClick);
}
}
/**
* Click event of buttons of First and Second half of a hour
* set various values like hour, meridiem, date
* these values are used by Event Form
*/
private static function onDayViewClick(event:MouseEvent):void
{
var btn:Button = Button(event.target);
var objHourCell:hourCell = hourCell(btn.parent);
if(event.target.toString().indexOf("btnFirstHalf") != -1)
{
hour = objHourCell.data.time == "12" ? 0 : int(objHourCell.data.time);
meridiem = objHourCell.data.meridiem == "am"? 0 : 1;
mins = 0;
}
else if(event.target.toString().indexOf("btnSecondHalf") != -1)
{
hour = objHourCell.data.time == "12" ? .5 : int(objHourCell.data.time) + .5;
meridiem = objHourCell.data.meridiem == "am"? 0 : 1;
mins = 1;
}
currentDate = objHourCell.data.date;
description = btn.label;
}
}
}
DayView.as: Out of three important view classes this is the very first view which is responsible for generating Day View in Event Calendar. This class is extended to Canvas class so it could be used in MXML files as well by using mxml tags. This class uses CommonUtils and DataHolder classes for generating view and data reading respectively. To create this class do right click on views folder and select New > ActionScript Class, use below code to populate this class.
package classes.views
{
import classes.utils.CommonUtils;
import mx.containers.ApplicationControlBar;
import mx.containers.Canvas;
import mx.controls.Label;
/**
* THIS CLASS WILL ALLOW TO GENERATE A LIST OF HOUR CELLS
* WHICH WILL BE FROM 00hr. TO 24hr.
*
* THIS CLASS USES hourCell TO GENERATE THE LIST. IT READ CURRENT DATE TO GENERATE
* THE VIEW FOR THAT PARTICULAR DATE.
*
* ADDITIONALLY IT CONNECTS WITH DATA HOLDER AND CHECK FOR EVENT EXISTENSE FOR A PARTICULAR
* DATE AND GENERATE THE VIEW ACCORDINGLY.
*
* THIS CLASS IS EXTENDED TO CANVAS SO IT COULD BE USED A DISPLAY OBJECT IN MXML FILES AS WELL.
*/
public class DayView extends Canvas
{
private var m_currentDate:Date;
public function DayView()
{
super();
}
// function will generate required view
private function createIntialChildren():void
{
this.removeAllChildren();
var objAppCtrlBar:ApplicationControlBar = new ApplicationControlBar();
var objDateDisplayer:Label = new Label();
var objHourContainer:Canvas = new Canvas();
var objButtonContainer:Canvas = new Canvas();
objHourContainer.horizontalScrollPolicy = "off";
objHourContainer.verticalScrollPolicy = "off";
objButtonContainer.horizontalScrollPolicy = "off";
objButtonContainer.verticalScrollPolicy = "off";
this.addChild(objAppCtrlBar);
objAppCtrlBar.height = 22;
objAppCtrlBar.width = this.width;
objAppCtrlBar.styleName = "appBarDayCell";
objAppCtrlBar.addChild(objDateDisplayer);
this.addChild(objHourContainer);
this.addChild(objButtonContainer);
objDateDisplayer.text = currentDate.toDateString();
objDateDisplayer.styleName = "lblViewTitle";
objDateDisplayer.height = 20;
objHourContainer.y = objDateDisplayer.height;
objButtonContainer.y = objDateDisplayer.height;
// common functions which generate hourCell in a loop and present the required view
CommonUtils.createLeftHourStrip(objHourContainer);
CommonUtils.createRightHourStrip(objButtonContainer, currentDate);
objButtonContainer.x = objHourContainer.getChildAt(0).width;
}
// prorperty is being set by main.mxml which allow to generate this view as per received date
public function set currentDate(_currentDate:Date):void
{
if(_currentDate != null)
{
m_currentDate = new Date(_currentDate.getFullYear(), _currentDate.month, _currentDate.date);;
createIntialChildren();
}
}
public function get currentDate():Date
{
return m_currentDate;
}
}
}
Now lets try import this class and have a look on the output. To use and this class first of all we need to import it using bolded code:
<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" width="1000" height="620" horizontalScrollPolicy="off" verticalScrollPolicy="off" creationComplete="onApplicationStart()" xmlns:comViews="mxml_views.*" xmlns:views="classes.views.*">
In our application we need to write below code in the main.mxml file to use DayView.as while keeping in mind that below code has to be written with-in <mx:ViewStack> tag.
<mx:ViewStack x="200" y="0" id="stackViews" width="100%" height="100%">
<views:DayView id="dayView" label="Day View" width="100%" height="100%" horizontalScrollPolicy="off" currentDate="{m_intCurrentDate}" showEffect="WipeDown" hideEffect="WipeUp" />
</mx:ViewStack>
WeekView.as: This is second important view class which is responsible for generating Week View of Event Calendar. This class is also extended to Canvas class so it could be used in MXML files as well by using mxml tags. This class uses CommonUtils, DataHolder and weekCell classes for generating view. To create this class do right click on views folder and select New > ActionScript Class, use below code to populate this class.
package classes.views
{
import classes.utils.CommonUtils;
import mx.containers.Canvas;
import mxml_views.weekCell;
/**
* THIS CLASS WILL ALLOW TO GENERATE A LIST OF HOUR CELLS
* WHICH WILL BE FROM 00hr. TO 24hr. AND THIS LIST WILL BE GENERATED FOR 7 DAYS IN CURRENT WEEK
*
* THIS CLASS USES hourCell TO GENERATE THE LIST. IT READ CURRENT DATE TO GENERATE
* THE VIEW FOR THAT PARTICULAR WEEK.
*
* ADDITIONALLY IT CONNECTS WITH DATA HOLDER AND CHECK FOR EVENT EXISTENSE FOR A PARTICULAR
* DATE AND GENERATE THE VIEW ACCORDINGLY.
*
* THIS CLASS IS EXTENDED TO CANVAS SO IT COULD BE USED A DISPLAY OBJECT IN MXML FILES AS WELL.
*/
public class WeekView extends Canvas
{
private var m_objLastGeneratedDate:Date;
private var m_intTotalDays:int = 6;
private var m_currentDate:Date;
public function WeekView()
{
super();
}
private function createIntialChildren():void
{
var intStartDate:int;
var intEndDate:int;
var dt:Date = m_currentDate;
var dtStart:Date;
if(m_objLastGeneratedDate != dt && currentDate != null)
{
m_objLastGeneratedDate = dt;
// calculate start date of the current week
dt.setDate(dt.getDate() - dt.getDay());
intStartDate = dt.date;
dtStart = new Date(dt.getFullYear(), dt.month, dt.date);
// calculate end date of the current week
dt.setDate(dt.getDate() + (m_intTotalDays - dt.getDay()));
intEndDate = dt.date;
// now generate view as per week dates
this.removeAllChildren();
var objHourContainer:Canvas = new Canvas();
objHourContainer.horizontalScrollPolicy = "off";
objHourContainer.verticalScrollPolicy = "off";
this.addChild(objHourContainer);
objHourContainer.y = 22;
// create left stip which is blue colored strip
CommonUtils.createLeftHourStrip(objHourContainer);
var objWeekCellContainer:Canvas = new Canvas();
this.addChild(objWeekCellContainer);
objWeekCellContainer.x = objHourContainer.getChildAt(0).width;
objWeekCellContainer.width = 720;
objWeekCellContainer.verticalScrollPolicy = "off";
objWeekCellContainer.horizontalScrollPolicy = "off";
// generate hour strip for seven daya i.e. number of days in a week
for(var i:int=0; i<=m_intTotalDays; i++)
{
var objWeekCell:weekCell = new weekCell();
objWeekCellContainer.addChild(objWeekCell);
objWeekCell.x = objWeekCell.width * i;
objWeekCell.lblDate.text = String(dtStart.date) + " " + CommonUtils.getDayName(dtStart.day).substr(0, 3);
// generate hour strip from common functions
CommonUtils.createRightHourStrip(objWeekCell.canDayView, dtStart);
dtStart.date = dtStart.date + 1;
}
}
}
override protected function updateDisplayList(unscaledWidth:Number,
unscaledHeight:Number):void
{
super.updateDisplayList(unscaledWidth, unscaledHeight);
}
// set current date for week view and thereafter generate the view on the basis of this date
public function set currentDate(_currentDate:Date):void
{
m_currentDate = new Date(_currentDate.getFullYear(), _currentDate.month, _currentDate.date);
createIntialChildren();
}
public function get currentDate():Date
{
return m_currentDate;
}
}
}
In our application we need to write below code in the main.mxml file to use WeekView.as while keeping in mind that below code has to be written with-in <mx:ViewStack> tag.
<mx:ViewStack x="200" y="0" id="stackViews" width="100%" height="100%">
<views:DayView id="dayView" label="Day View" width="100%" height="100%" horizontalScrollPolicy="off" currentDate="{m_intCurrentDate}" showEffect="WipeDown" hideEffect="WipeUp" />
<views:WeekView id="weekView" label="Week View" x="0" y="0" currentDate="{m_intCurrentDate}" horizontalScrollPolicy="off" showEffect="WipeDown" hideEffect="WipeUp" />
</mx:ViewStack>
Now lets check the next demo to notice the changes. Be sure you click on Week button to check the output of WeekView.as.
MonthView.as: This is third & last important view class which is responsible for generating Month View of Event Calendar. This class is also extended to Canvas class so it could be used in MXML files as well by using mxml tags. This class uses CommonUtils, DataHolder and monthCell classes for generating view. To create this class do right click on views folder and select New > ActionScript Class, use below code to populate this class.
package classes.views
{
import classes.events.CustomEvents;
import classes.model.DataHolder;
import classes.utils.CommonUtils;
import flash.events.MouseEvent;
import mx.containers.ApplicationControlBar;
import mx.containers.Canvas;
import mx.containers.Grid;
import mx.containers.GridItem;
import mx.containers.GridRow;
import mx.controls.Label;
import mx.utils.ObjectUtil;
import mxml_views.monthCell;
/**
* THIS CLASS WILL ALLOW TO GENERATE A GRID OF CURRENT MONTH
*
* THIS CLASS USES monthCell TO REPRESENT A SINGLE DAY.
*
* ADDITIONALLY IT CONNECTS WITH DATA HOLDER AND CHECK FOR EVENT EXISTENSE FOR A PARTICULAR
* DATE AND GENERATE THE VIEW ACCORDINGLY.
*
* THIS CLASS IS EXTENDED TO CANVAS SO IT COULD BE USED A DISPLAY OBJECT IN MXML FILES AS WELL.
*/
public class MonthView extends Canvas
{
private var m_intCurrentMonth:int;
private var m_intCurrentYear:int;
private var m_monthViewGrid:Grid;
private var m_appBar:ApplicationControlBar
private var m_lblDaysNames:Label;
public function MonthView()
{
super();
createIntialChildren();
}
// function responsible for generating the view
private function createIntialChildren():void
{
// add a new grid
m_monthViewGrid = new Grid();
m_monthViewGrid.styleName = "grdMonthView";
m_monthViewGrid.y = 25;
// add application bar which will show days name on the top of the view
m_appBar = new ApplicationControlBar();
m_appBar.width = 800;
m_appBar.height = 22;
m_appBar.styleName = "appBarDayCell";
m_lblDaysNames = new Label();
m_lblDaysNames.width = 775;
m_lblDaysNames.height = 16;
m_lblDaysNames.styleName = "lblDaysNames";
m_lblDaysNames.text = " Sunday Monday Tuesday Wednesday Thursday Friday Saturday";
this.addChild(m_appBar);
m_appBar.addChild(m_lblDaysNames);
this.addChild(m_monthViewGrid);
}
override protected function updateDisplayList(unscaledWidth:Number,
unscaledHeight:Number):void
{
super.updateDisplayList(unscaledWidth, unscaledHeight);
}
// create grid of days in current month as per current date provided
private function createDaysGrid():void
{
// always assume that first day of a month will have date as 1
// currentMonth and currentYear are supplied by main.mxml file
var objDate:Date = new Date(currentYear, currentMonth, 1);
// get total days count for currentMonth in currentYear
var intTotalDaysInMonth:int = CommonUtils.getDaysCount(currentMonth, currentYear);
var i:int;
/**
* Add Total number of Grid items in a Array
*
**/
// add empty items in case first day is not Sunday
// i.e. MonthView always shows 7 coloumns starting from Sunday and ending to Saturday
// so if it suppose Wednesday is the date 1 of this month that means we need to
// add 3 empty cells at start
var arrDays:Array = new Array();
for(i=0; i<objDate.getDay(); i++)
{
arrDays.push(-1);
}
// now loop through total number of days in this month and save values in array
for(i=0; i<intTotalDaysInMonth; i++)
{
var objDate1:Date = new Date(currentYear, currentMonth, (i+1));
var strStartDayName:String = CommonUtils.getDayName(objDate1.getDay());
arrDays.push({data:i+1, label:strStartDayName});
}
// if first day of the month is Friday and it is not a leap year then we need to show 7 rows
// there could be max 42 items in a calendar grid for a month with 6 rows
// so add blank values in case still some cells are pending as per count of 7 cols x 6 rows = 42
if(objDate.getDay() >= 5 && arrDays.length <= 32)
{
for(i=arrDays.length; i<42; i++)
{
arrDays.push(-1);
}
}
else
{
for(i=arrDays.length; i<35; i++)
{
arrDays.push(-1);
}
}
m_monthViewGrid.removeAllChildren();
var objGridRow:GridRow;
// once array is created now loop through the array and generate the Grid
for(i=0; i<arrDays.length; i++)
{
if(i % 7 == 0)
{
objGridRow = new GridRow();
m_monthViewGrid.addChild(objGridRow);
}
var objGridItem:GridItem = new GridItem();
var objDayCell:monthCell = new monthCell();
objGridItem.addChild(objDayCell);
objGridRow.addChild(objGridItem);
objDayCell.txtDesc.visible = false;
if(arrDays[i] == -1)
{
objDayCell.canHeader.visible = false;
}
else
{
objDayCell.lblDate.text = arrDays[i].data;
objDayCell.addEventListener(MouseEvent.CLICK, onDayCellClick);
objDayCell.data = {date: new Date(currentYear, currentMonth, arrDays[i].data) };
// check if current date has some event stored in DataHolder
// if YES then display event description
for(var j:int=0; j<DataHolder.getInstance().dataProvider.length; j++)
{
var obj:Object = DataHolder.getInstance().dataProvider[j];
if(ObjectUtil.dateCompare(obj.date, objDayCell.data.date) == 0)
{
objDayCell.txtDesc.text = obj.desc;
objDayCell.txtDesc.visible = true;
break;
}
}
}
}
}
public function redraw():void
{
createDaysGrid();
}
// click event for a day cell
// will change the view to Day View and set current date as per cell clicked in the Grid
private function onDayCellClick(_event:MouseEvent):void
{
var objDayCell:monthCell
if(_event.target.toString().indexOf("txtDesc") == -1)
{
objDayCell = monthCell(_event.target);
}
else
{
objDayCell = monthCell(_event.target.parent.parent);
}
dispatchEvent(new CustomEvents(CustomEvents.MONTH_VIEW_CLICK, objDayCell.data));
}
/**
* Custom Properties
*
**/
public function set currentMonth(_intCurrentMonth:int):void
{
m_intCurrentMonth = _intCurrentMonth;
}
public function get currentMonth():int
{
return m_intCurrentMonth;
}
public function set currentYear(_intCurrentYear:int):void
{
m_intCurrentYear = _intCurrentYear;
createDaysGrid();
}
public function get currentYear():int
{
return m_intCurrentYear;
}
}
}
In our application we need to write below code in the main.mxml file to use MonthView.as while keeping in mind that below code has to be written with-in <mx:ViewStack> tag.
<mx:ViewStack x="200" y="0" id="stackViews" width="100%" height="100%">
<views:DayView id="dayView" label="Day View" width="100%" height="100%" horizontalScrollPolicy="off" currentDate="{m_intCurrentDate}" showEffect="WipeDown" hideEffect="WipeUp" />
<views:WeekView id="weekView" label="Week View" x="0" y="0" currentDate="{m_intCurrentDate}" horizontalScrollPolicy="off" showEffect="WipeDown" hideEffect="WipeUp" />
<views:MonthView id="monthView" label="Month View" x="0" y="0" horizontalScrollPolicy="off" currentMonth="{dtPicker.displayedMonth}" currentYear="{dtPicker.displayedYear}" showEffect="WipeDown" hideEffect="WipeUp" />
</mx:ViewStack>
Let’s check once more the next demo. Be sure you click on Month button to check the output of MonthView.as.
So, we are through with this step as well. All above classes are very well commented so in case you need to understand any calculation logic just read those comments even then if there is some confusion please send me a comment I’ll try to respond on that soon. Just to cross check please have a look at Figure 5.1 to see whether you have all the required classes in place.

Figure 5.1
I hope all is well till now, take a deep breath as we are through with the crucial part of the application and now we just need to integrate above classes in our final step of Creating Flex Calendar.
Step 6: Integrating all these classes and generating the final output
We have already created main.mxml file which is being used as our main application file. Now what we need to add to our previous version of file is:-
- Import CSS file in MXML.
- Call events on Add Event button.
- Import all views i.e. Day, Week and Month inside ViewStack.
- Import EventForm view.
- Add Events Listeners for these views.
- Bind m_intCurrentDate variable to all views including EventForm.
- Dispatch an Event to update views when a request for adding a new event is received.
Before going further lets ensure that we have imported packages in <mx:WindowedApplication> tag. Import statements are highlighted in bold
<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" width="1000" height="620" horizontalScrollPolicy="off" verticalScrollPolicy="off" creationComplete="onApplicationStart()" xmlns:comViews="mxml_views.*" xmlns:views="classes.views.*">
Write following code to import CSS file in our main application file and to call events on Add Event button add bolded code to its tag.
<mx:Style source="styles/skin.css"/>
<mx:Button x="52" y="251" label="Add Event" click="{eventForm.visible=true;}" enabled="{eventForm.currentDate != null}" />
Now lets ensure again that following code with-in the <mx:ViewStack> tag to import all calendar views is there.
<mx:ViewStack x="200" y="0" id="stackViews" width="100%" height="100%">
<views:DayView id="dayView" label="Day View" width="100%" height="100%" horizontalScrollPolicy="off" currentDate="{m_intCurrentDate}" showEffect="WipeDown" hideEffect="WipeUp" />
<views:WeekView id="weekView" label="Week View" x="0" y="0" currentDate="{m_intCurrentDate}" horizontalScrollPolicy="off" showEffect="WipeDown" hideEffect="WipeUp" />
<views:MonthView id="monthView" label="Month View" x="0" y="0" horizontalScrollPolicy="off" currentMonth="{dtPicker.displayedMonth}" currentYear="{dtPicker.displayedYear}" showEffect="WipeDown" hideEffect="WipeUp" />
</mx:ViewStack>
Now add Event Form which allow us to save an event on a selected date. Before adding this tag you must import CommonUtils class in <ms:Script> tag using import classes.utils.CommonUtils; and then write following MXML code
<comViews:EventForm x="0" y="294" id="eventForm" hour="{CommonUtils.hour}" meridiem="{CommonUtils.meridiem}" mins="{CommonUtils.mins}" currentDate="{CommonUtils.currentDate}" description="{CommonUtils.description}" visible="false">
</comViews:EventForm>
To perform last three steps in above list copy below code and paste it in <mx:Script> tag:-
<mx:Script>
<![CDATA[
import classes.model.DataHolder;
import classes.events.CustomEvents;
import classes.views.MonthView;
import classes.utils.CommonUtils;
/* Current date will be bound all views */
[Bindable]
private var m_intCurrentDate:Date;
/* Function will execute on creation complete of main.mxml */
private function onApplicationStart():void
{
var objDate:Date = new Date();
dtPicker.selectedDate = objDate;
// create events
monthView.addEventListener(CustomEvents.MONTH_VIEW_CLICK, onMonthViewClick);
DataHolder.getInstance().addEventListener(CustomEvents.ADD_NEW_EVENT, onNewEventAdded);
onDateChange();
}
/* Custom Events */
private function onDateScroll():void
{
onDateChange();
}
private function onDateChange():void
{
m_intCurrentDate = new Date(dtPicker.displayedYear, dtPicker.displayedMonth, dtPicker.selectedDate.date);
}
private function onDayClick():void
{
stackViews.selectedIndex = 0;
}
private function onWeekClick():void
{
stackViews.selectedIndex = 1;
}
private function onMonthClick():void
{
stackViews.selectedIndex = 2;
}
// function fires when a cell is being clicked from the Month View
private function onMonthViewClick(_event:CustomEvents):void
{
dtPicker.selectedDate = _event.object.date;
onDateChange();
stackViews.selectedIndex = 0;
}
// function fires when Save button is clicked from Event From to save an event
private function onNewEventAdded(_event:CustomEvents):void
{
onDateChange();
monthView.redraw();
}
]]>
</mx:Script>
Conclusion
Now just compile and run your application. The final result should be similar to the final demo. You could also take it to further by saving event data in some database and then convert this application to a perfect desktop application including event alerts and other features which generally you see in other desktop applications. In case any help is required to do so or need help on this article feel free to drop a comment. And if you integrate new features on it, be sure to drop a comment showing it.
|
Share the love
|
Get free updates and win TTL prizes
|
Other Posts You Might Like
Hi
I was wondering how to add agenda feature to my rentalcar application and hopefully your tutorial comes in rescue. What i really want to do is to have vehiles on leftStrip intead of Hours and have a kind of layer crossdays showing details about client.
how should i preceed on basis of yours.
Regards
Hi Ankur, u have a great apps.
i know it have been a long time ago, but it still cool.
i have a question:
i did all codes, but can't get the event, no respons if i click it.
i think i got wrong on this side below:
Now add Event Form which allow us to save an event on a selected date. Before adding this tag you must import CommonUtils class in tag using import classes.utils.CommonUtils; and then write following MXML code
what's wrong with i did?
I just wanted to thank you for sharing this. I was able to customize it to fit my project's needs (as a web application in Flex 4.5--I'll try to post the code I customized once the project is fully finished).
Your efforts saved me a lot of time. Thanks!
hey damian im trying to convert to flex 4.5 can you offer some assistance. i would really appreciated.
I see there was a follow up on this article, with AMFPHP services even more awesome. Didn't see the link anywhere on this page so just posting it here:
http://www.thetechlabs.com/tech-tutorials/interfaces/connecting-flex-calendar-with-database-using-amf-php/
Really awesome tutorial, :) Exactly what I was looking for. If you have time can maybe convert it to flex 4, or flex 4.5 (using spark components instead of mx components). Anyway really nice tutorial.
hai,
when i copy main-app.xml code i got some erros
Process terminated unexpectedly.
error while loading initial content
Launch command details: “C:\Program Files\Adobe\Adobe Flash Builder 4\sdks\4.1.0\bin\adl.exe”
-runtime “C:\Program Files\Adobe\Adobe Flash Builder 4\sdks\4.1.0\runtimes\air\win”
D:\sampleApplication\bin-debug\Main-app.xml
D:\sampleApplication\bin-debug
Hi
when i am using this code i got some erros
Process terminated unexpectedly.
error while loading initial content
Launch command details: "C:\Program Files\Adobe\Adobe Flash Builder 4\sdks\4.1.0\bin\adl.exe"
-runtime "C:\Program Files\Adobe\Adobe Flash Builder 4\sdks\4.1.0\runtimes\air\win"
D:\sampleApplication\bin-debug\Main-app.xml
D:\sampleApplication\bin-debug
i am using Flex4.what to do any idea?
Can i make this calender as a web application instead of desktop, what all changes i have to make to do so.
Hi, i'm trying to modify it to adapt to the spanish calendar (weeks start on monday). On the side calendar it's easy but on the main table i don't find who to change it to display weeks and mounth data starting on monday and finishing on sunday. Any ideas?
Thanks a lot and best wishes
Premine
Great Wrok,
Is it possible to display events which are stored in a xml?, If that so, tell me where to load the xml.
Nice tutorial but maybe it would be easier to use some of the shelf flex calendar component like this one:
http://flex-calendar.com/demo
Hi Suraj,
You just need to embed Nepali fonts and use wherever required.
I hope that helps you.
Regards
Ankur Arora
I have one question ... i want to create something similar to this but not with english dates but with my country's .. that is nepali. how can i do it? any feedback is appreciated. thank you :D
Hi Ankur,
this tutorial is excellent but I was wondering if you could help me out with something. I am basically trying to set up this calendar with a month only option so that when I click on the day of the month it will let me pass in an event. Is this possible? What is the easiest way to do this? I am working on a massive project and this calendar would make it perfect if it works out. Thanks again for the tutorial, it's really thorough and well explained.
Conor
Hi,
Everyone on this post who were looking for Database driven Calendar. Please visit the Part II of this post at http://www.thetechlabs.com/tutorials/interfaces/connecting-flex-calendar-with-database-using-amf-php/
Thanks
Ankur Arora
Flash & Flex Expert
Here's what you need to do to compile this with flashbuilder 4.
Modify the main-app.xml:
change the application tag to the following:
There will be an error in the mail.mxml about an alpha... Search out taht line and remove the tag that is causing the issue.
Modify the skin.css to the following: (Keep in mind a few of the tags I had to comment out)
-----------------------------
/* CSS file */
/* Textarea used in month view to display event description */
@namespace spark "spark.skins.spark.*";@namespace@namespace
s "library://ns.adobe.com/flex/spark";
mx "library://ns.adobe.com/flex/mx";
spark|TextAreaSkin.txtArea
{
borderStyle: none;
}
/* Skins for buttons used in week and day view */
spark|ButtonSkin.btnDayItems
{
upSkin:ClassReference('classes.skins.ButtonSkin');
overSkin:ClassReference('classes.skins.ButtonSkin');
downSkin:ClassReference('classes.skins.ButtonSkin');
disabledSkin:ClassReference('classes.skins.ButtonSkin');
selectedUpSkin:ClassReference('classes.skins.ButtonSkin');
selectedOverSkin:ClassReference('classes.skins.ButtonSkin');
selectedDownSkin:ClassReference('classes.skins.ButtonSkin');
selectedDisabledSkin:ClassReference('classes.skins.ButtonSkin');
textAlign: left;
paddingBottom: 0;
}
/* title for showing date used in day and week view */
s|Label.lblViewTitle
{
fontWeight: bold;
textAlign: left;
color: #FFFFFF;
}
/* global button styles */
/*
mx|Button
{
fillAlphas: 0.6, 0.6, 0.6, 0.6;
fillColors: #FFFFFF, #CCCCCC;
}
*/
/* Grid styles, used in month view */
mx|Grid.grdMonthView
{
horizontalGap: 0;
verticalGap: 0;
}
/*used for showing day's name in week view */
s|Label.lblDaysNames
{
fontWeight: bold;
color: #FFFFFF;
}
/* Global HRule style */
mx|HRule
{
shadowColor: #004C7C;
}
/* Application controlbar style, used in all 3 views */
mx|ApplicationControlBar.appBarDayCell
{
fillAlphas: 1.0, 1.0;
fillColors: #7FC4FF, #52AACA;
cornerRadius: 0;
paddingTop: 2;
}
/* Canvas used as base of month cell */
mx|Canvas.canDayCellBase
/*Canvas.canDayCellBase*/
{
backgroundColor: #FFFFFF;
borderStyle: solid;
borderColor: #88C4EE;
}
/* hours label used in day and week view */
s|Label.lblHours
{
color: #FFFFFF;
fontFamily: Verdana;
fontSize: 12;
}
/* mins label used in day and week view */
s|Label.lblMins
{
color: #FFFFFF;
fontFamily: Verdana;
fontSize: 10;
}
/* Embed Verdana font in application
@font-face
{
/*fontFamily: Verdana;
fontWeight: normal;
fontStyle: normal;
src: local("Verdana");
}*/
------end file----------
It should now compile and run.
It runs a little slow on my computer. I'm thinking it's because of a hybred between spark and halo. Ankur; you rock! Thanks for this demo.
Hi Scott, thanks for posting this comment.
It looks like one of your paragraphs got cut off, where you say "Modify the main-app.xml:
change the application tag to the following:"... If you see this, that info might save me some time! Thanks.
Hi Ankur,
It is a great tutorial. When are you planning to release the database connectivity version?
Thank you,
Ananda
Thanks Products-Based,
comments like these boost me to write more tutorials for you guys.
Thanks
Ankur Arora
Flash & Flex Expert
Great article, though I only found it recently! Thank the author for a detailed description and explanation. Now I'll read the second part - I want to use it somewhere on their websites.
Hey there. Great tutorial
I have a question though, how can i modify the hour strip? i want it only to be working hours, but when i move the hour loop, the hours are limited to which i want, but the cells' space keeps appearing (empty space). Where can i disable the space where those lines appeared?
guys,
there are so many request to save event details in the database, give me couple of days I'll create that. I hope that would be fine with you guys. In case you need it urgently kindly send me a mail at ankur_arora123atyahoodotcom.
Regards
Ankur
Very usefull tutorial!
But I wish to save the data with PHP/MySQL, but my Flex knowledge is too few to pass this data to php handler. Could you tell how I can use dataProvider property to do that?
if this was deployed as an Air application, how would the DataHolder class be modified to work with a local database?
great tutorial! what specifically do I need to change in DataHolder to set the dataprovider to a local database using SQLite? could you please reply with some example code? thanks!
Ankur,
I'm somewhat of a newbie when it comes to flex. I have a fairly good understanding of how this tutorial works, but I'm having trouble linking it to a mysql database.
The first thing I did was change your m_arrEvents variable from an array to an array collection throughout the project and tested it to make sure everything was working as it was before.
Next I successfully added a call to a HTTPService inside the OnSaveButtonClick function in EventForm.mxml. This HTTPService calls a php file which writes the contents of "obj" to a MySQL database. I kept the "DataHolder.getInstance().addEvent(obj);" line of code as well.
I then added a public function style HTTPService to Dataholder.as that calls a second php file. This php file gets all of the events in the database and returns them as XML. The php file seems to be working correctly when I test it outside the project.
Finally, I tried to convert the events returned from the php file from XML into Objects and add them m_arrEvents (first I do a removeall from m_arrEvents). That's where everything goes wrong. I cannot get this section of code to work. I'm not even really sure it this is how I should be getting the data from the database.
Do you have any advice on how and when I should be getting the events from the database. Any advice would be appretiated. Thanks.
Hello.
Can you do this calendar of events for Adobe Flash Builder ...? You could also show how to make a database in ColdFusion.
Hi Ali & Mohammed,
To get events from the database you need to connect Flex either with some webservice or may be some server side script. However to populate content received from the database you can use dataProvider property which is there in Model class because all view get updates on the basis of that property.
Let me know if you need any other help.
Regards
Ankur
Very nice tutorial. Keep it up
I'd be glad if you could help me to know how to integrate this Event Calendar with Database(Sql Server).
Thanks
Regards
Nice Tutorial.
I've one query,
I'd want to use MS Sql Server, to display Events Name and Description from Database on specific dates. How Can I achieve this?
Thanks
Hi Ajay,
Thanks for your comments. Just wanted to inform you that this tutorial was done in Flex 3 and I did not checked it on Flash Builder 4. I think I need to spend time for that but the author of the tech labs has to give me that permission because I cannot publish the updated files by my own. I think this is a good forum if you guys can request them on my behalf.
For my website I'm working on that and creating a new one which might take sometime.
Regards
Ankur
Hey,
Great Tutorial !
But Your Source Has Some Issues in Flash Builder 4 (BETA)..
Its Basically a CSS Issue..
Im half Way in Integrating Your Calendar Component With Outlook.
If i get the Compatible Source Files That'l be Great in Help !
Keep Your Tutorials Going On !
Cheers,
Ajay
Note : Also Update www - dot - ankur-arora - dot - com :P
Marylka,
Yes why not, that is the flexibility of Flex which allows you to use same code for web & desktop applications both.
when i compile i found out an error which is
at the bottom there, it state that identifier 'stackviews used more than once....
can you please help me solve this problem??thanks
when i follow the steps that you taught me to do in this website, i face a problem when i compile and run it....which showing that like this...
VerifyError: Error #1014: Class flash.events::NativeWindowBoundsEvent could not be found.
at flash.display::MovieClip/nextFrame()
at mx.managers::SystemManager/deferredNextFrame()[C:\autobuild\3.2.0\frameworks\projects\framework\src\mx\managers\SystemManager.as:319]
at mx.managers::SystemManager/preloader_initProgressHandler()[C:\autobuild\3.2.0\frameworks\projects\framework\src\mx\managers\SystemManager.as:2945]
at flash.events::EventDispatcher/dispatchEventFunction()
at flash.events::EventDispatcher/dispatchEvent()
at mx.preloaders::Preloader/timerHandler()[C:\autobuild\3.2.0\frameworks\projects\framework\src\mx\preloaders\Preloader.as:398]
at flash.utils::Timer/_timerDispatch()
at flash.utils::Timer/tick()
I wonder how I would do this calendar for web? If you have an example for me could send I would be very grateful
Hi George,
currently this sample does not send any data outside to any kind of webservice or xml. However it can be done using DataHolder class becuase that class holds all the data. I can surely plan to create it in 2nd version. Kindly raise your voice for the same and send it to site admin because without their confirmation I cannot upload the 2nd version.
Regards
Ankur
Great sample. Im not sure how to... Once an event is added where does it get saved? How do I send these to a server? What fields are needed so the app can retrieve the events from the server? How about both, saving to xml on local device and to server? Do you have a sample or advice im using Flex 3 and ColdFusion 8. Thanks
George
This was a most beneficial post... really worth while, and learn't a lot from it. I have a suggestion for you however, when playing with your source code I noticed that if you double click each months entry heading it will throw an error, this is because the events target is not of the type monthCell... a simple fix for this is to modify the monthView.as by changing the private function onDayCellClick(e:event)... as shown
private function onDayCellClick(_event:MouseEvent):void
{
var objDayCell:monthCell;
if(_event.target.toString().indexOf("txtDesc") == -1)
{
if (_event.target.valueOf() is monthCell) {
objDayCell = monthCell(_event.target);
}
else {
return;
}
}
else
{
objDayCell = monthCell(_event.target.parent.parent);
}
dispatchEvent(new CustomEvents(CustomEvents.MONTH_VIEW_CLICK, objDayCell.data));
}
thanks again for the great work, a pleasure to see how it worked
cheers Beau
thank you
Is there anything that will prevent this from modular implementation? No matter, Tally-Ho!
i'm going to try it right now







Hello this code is very good but i need the same application but to be created as a web application in flex.Can someone help me please?
- spam
- offensive
- disagree
- off topic
Like