Second revised edition of creating a calendar with the Datechooser (12-20-2007)
This tutorial shows you how to create an xml-driven calendar using the calendar component. You need to be a bit familiar with flash-xml and of course you need to have some actionscript knowledge.
The final product
After you have tested this file we will discuss how to make it.
Setting up the Stage
We need the following items for this file:
- Two instances of an empty movieclip named hilight and model
- One instance of the datechooser component named myDateChooser
- 13 movieclips highlighting the dates information is available named: jancal,febcal etc. and one empty clip named default all exported in frame 1
- three instances of the textarea component named dateField, eventField and today
- 1 movieclip named mask
- 1 movieclip named window, which contains a button and the textarea instance eventField
- a frame and some text as shown in the movie.
Create a movieclip named calendar and place all the objects into that clip. By this way we have a confined movieclip, which we can use anywhere we want and load also as a separate movie. This is a bit similar to a component. Make one frame and call it actions, where we place all the actionscript, which we discuss now.
The Actionscript
First we confine the movieclip and create its own root.
//closing up the clip
this._lockroot = true;
Next we define and set all our objects and datatype them. We also create a function for opening the mask. Do not forget that this is AS2 syntax.
//setting textfields
var dateField:TextField; dateField.html = true; var today:TextField; today._alpha = 0; today.html = true; var window:MovieClip; window.eventField.html = true; var mask:MovieClip; window.setMask(mask); function scalein() { var n_inTimer:Number = setInterval(scalin, 10); function scalin() { if (mask._xscale<100) { mask._xscale += 1; } else { mask._xscale = 100; clearInterval(n_inTimer); } } } window.eventField._alpha = 70;
//setting empty movieclips: loads pics
var model:MovieClip;
//loads schablone
var hilight:MovieClip;
//setting stylesheet for textfields
var xmlCss:TextField.StyleSheet = new TextField.StyleSheet(); xmlCss.load("flashbody.css"); dateField.styleSheet = xmlCss; eventField.styleSheet = xmlCss; today.styleSheet = xmlCss;
//reducing alpha for datechooser component
var myDateChooser:MovieClip; myDateChooser._alpha = 30;
//arrays for xml data
var itlist:Array = new Array(); var itName:Array = new Array(); var itDescription:Array = new Array(); var itMonth:Array = new Array();
//var to change display
var s:Number = 0;
//var to determine the month
var arrayMonth:Number;
//var to get the full date
var myDate:Date = new Date(); var thDate:Number = myDate.getDate(); var thMonth:Number = myDate.getMonth()+1; var thYear:Number = myDate.getFullYear();
//the displayed year when the movie opens
if (s == 0) { var theSelYear:Number = myDateChooser.displayedYear; }
Now we are creating a listener object to change the months. The event handler for the month buttons is scroll. Inside we first need to empty 4 arrays, which we have created earlier and get filled when the xml files are parsed. We use the splice method for that within a for loop. Then we increment s to change the var settings for the full year and we remove the text from all the textfields. Finally, we use a switch function for the current year and default for any other year. When any month of the current year is selected execute the selMenu() function, which has 2 arguments for the displayed month and the displayed year.
//creating the listener object
var mymonthListener:Object = new Object(); mymonthListener.scroll = function(eventObj) {
//we first empty all arrays
for (var count12 = 1; count12<=itlist.length; count12++) { itlist.splice(0, count12); itName.splice(0, count12); itDescription.splice(0, count12); itMonth.splice(0, count12); }
//increment s
s++;
//remove all text
dateField.text = ""; window.eventField.text = ""; today.text = "";
//defining all the displayed dates data
var eventSource:Object = eventObj.target; var theSelYear:Number = eventSource.displayedYear; var theSelectedMonth:Number = eventSource.displayedMonth; var theSelectedDay:Number = eventSource.selectedDate;
//switch function to show individual monthly data
switch (theSelYear) { case 2005 : selMenu(theSelectedMonth, theSelYear); break; default : dateField.text = " <h4>"+theSelYear+"</h4> "; window.eventField.text = " <h3>Sorry, no information available</h3> "; hilight.attachMovie("default", "cal", 1); scalein(); model.loadMovie("images/dec.jpg"); } }; myDateChooser.addEventListener("scroll", mymonthListener);
The next function is the function to load the xml files. We create a new array to hold all the xml files covering the whole year. Next we load the corresponding xml file using a switch function with the sected year as argument, since we want to load those months only when 2005 is displayed. As default we define the var arrayMonth as undefined to unload any xml file. In the following if statement we will get the current month for the initial display or when we choose the month it will be the selected month. Then we just load and parse the xml file.
//function for loading the xml of the current and selected month
function selMenu(selMonth:Number, theSelYear:Number) { var monthArray:Array = new Array(); switch (theSelYear) { case 2005 : monthArray = ["xml/jan.xml", "xml/feb.xml", "xml/mar.xml", "xml/apr.xml", "xml/may.xml", "xml/jun.xml", "xml/jul.xml", "xml/aug.xml", "xml/sep.xml", "xml/oct.xml", "xml/nov.xml", "xml/dec.xml"]; break; default : arrayMonth = undefined; } var seMonth:Date = new Date(); if (s == 0) { arrayMonth = seMonth.getMonth(); } else { arrayMonth = selMonth; } var myMenu:XML = new XML(); myMenu.ignoreWhite = true; myMenu.onLoad = searchItems;
//we get the current month and load the corresponding xml
myMenu.load(monthArray[arrayMonth]); }
//executing the function, initially we set the sel month to null
selMenu(null, theSelYear);
//parsing xml
function searchItems(success:Boolean) { if (success) { traceSearch(this); } }
//search for attribute matches
function traceSearch(myItem10) { myPic = myItem10.attributes.pic; mySel = myItem10.attributes.sel;
//loading the empty clips with the background pic and the schablone as defined in the xml
if (myPic != undefined) { model.loadMovie(myPic); hilight.attachMovie(mySel, "higLight", 1); }
//looping through the file
for (var iii in myItem10.attributes) {
//searching for id attribute, all nodes have an attribute
if (iii == "id") {
//defining all variables for attributes and child nodes
//id number, essential has to equal the date
var idlist:String = myItem10.attributes.id;
//for displaying
var itemName:String = myItem10.attributes.name; var itemMonth:String = myItem10.attributes.month; var itemDescription:String = myItem10.firstChild.toString();
//here we pass on individual vars
chooseItem(idlist, itemName, itemDescription, itemMonth); } }
//recursive function
for (var search01 in myItem10.childNodes) { if (myItem10.childNodes[search01].nodeType != 3) { traceSearch(myItem10.childNodes[search01]); } } }
Next we create a function with all the attribute names as argument. In this function we now create arrays storing all the data. Then we ask if any of the data fit to the current date, if so display if not show a message. However, here we put another if statement in, since we want this to be executed only once in the beginning when s = 0.
//function to create arrays and show result for data of todays date
function chooseItem(idlist:String, itemName:String, itemDescription:String, itemMonth:String) { itlist.push(idlist); itName.push(itemName); itDescription.push(itemDescription); itMonth.push(itemMonth); if (idlist == thDate && itemMonth == thMonth) { dateField.text = "<h4>"+itemName+"</h4>"; window.eventField.text = itemDescription; scalein(); today.text = "<h2>Today</h2>"; } else {
//this will be shown only once
if (s == 0) { dateField.text = "<h4>"+thMonth+"-"+thDate+"-"+thYear+"</h4>"; today.text = "<h2>Today</h2>"; } } }
Now we have to create the eventhandler when any date is chosen. First we have to create a number similar to s, which increments to prevent all statements from being executed. Then we create the var for the selected date. We now loop through all the arrays and display the result, if a match was found and increment m. If there is no match show a certain message otherwise, meaning if m = 0.
We need to declare several variables first. The reason is that the DateChooser component has a bug. Clicking twice on one date will give undefined for the second time. This bug is fixed by adding some lines as shown below using variables, which remember the previous values, which were defined.
//eventhandler for choosing a particular date
var rememberDate:Number; var rememberMonth:Number; var rememberYear:Number; var theDate:Number; var theMonth:Number; var theYear:Number; // var myDateListener:Object = new Object (); myDateListener.change = function (eventObj) { //This is part of the bugfix if (theDate != undefined) { rememberDate = theDate; rememberMonth = theMonth; rememberYear = theYear; } var m:Number = 0;
//datachooser is eventobj.
var eventSource:Object = eventObj.target;
//selected date
var theSelectedDate:Date = eventSource.selectedDate;
// format the date and further another part of the bugfix
theDate = theSelectedDate.getDate (); theMonth = theSelectedDate.getMonth () + 1; theYear = theSelectedDate.getFullYear (); if (theDate == undefined) { theDate = rememberDate; theMonth = rememberMonth; theYear = rememberYear; }
//we loop through the array to find a match
for (count11=0; count11 < itlist.length; count11++) { if (itlist[count11] == theDate) { //when found we increment m m++; //and list the reults dateField.text = "<h4>"+itName[count11]+"</h4>"; window.eventField.text = itDescription[count11]; scalein(); today.text = "";
//if it matches today
if (itlist[count11] == thDate) { today.text = "<h2>Today</h2>"; }
//if there is no match we show only the date
} else if (m == 0) { dateField.text = "<h4>"+theMonth+"-"+theDate+"-"+theYear+"</h4>"; } } }; myDateChooser.addEventListener("change", myDateListener);
Now finally we will have a look at the xml file. For more details on text formatting check my tutorial. The xml file determines which pic will be loaded and which schablone. The most important message here is that the id has to be equal to the days date. here is an example for july.
<?xml version="1.0"?> <schedule> <pic pic="images/jul.jpg" sel="julcal"/> <day id="4" name="7 - 4 - 2005" month="7"> <p> <h1>Monday</h1><br/> <ul> <li>Independence Day</li> </ul> </p> </day> </schedule>
And that is all.