Thursday, November 4, 2010

How to create a calendar using only Actionscript 3 - Part 12

Today we will make a checkbox for our edit window that can be checked to make this day of this month highlighted every year.

First of all, we'll need another attribute in our XML file.

<highlightedDates>

<day day="26" month="6" year="2010" eYear="false">First post on kirill-poletaev.blogspot.com!</day>
<day day="21" month="12" year="2012" eYear="false">The end of the world!</day>
<day day="25" month="12" year="" eYear="true">Christmas!</day>

</highlightedDates>

Now, here are the changes I applied:

- Create a checkbox called everyYearCheck and place it on stage. Its visibility is managed by the visibleEditWindow method.

var everyYearCheck:CheckBox = new CheckBox();
addChild(everyYearCheck);
everyYearCheck.x = 10;
everyYearCheck.y = 180;
everyYearCheck.label = "Every year";

function visibleEditWindow(vis:Boolean):void
{
edit_desc_input.visible = vis;
edit_desc_clear.visible = vis;
edit_desc_apply.visible = vis;
edit_desc_text.visible = vis;
everyYearCheck.visible = vis;
}

- Check whether the day we selected has eYear set to 'true' when we open the window. If it is, then we already check the checkbox.

function editHighlight(evt:MouseEvent):void
{
if (evt.target.alpha == 1)
{
selectedDay = evt.target.text;
edit_desc_input.text = "";
currentDayHighlighted = false;
currentDayHighlightArrayID = NaN;
everyYearCheck.selected = false;
for (var cd:int=0; cd<highlightDates.length; cd++)
{
if (highlightDates[cd].day == evt.target.text && highlightDates[cd].month == firs.month + 1 && highlightDates[cd].year == firs.fullYear)
{
edit_desc_input.text = highlightDates[cd].desc;
currentDayHighlighted = true;
currentDayHighlightArrayID = cd;
if (highlightDates[cd].eYear)
{
everyYearCheck.selected = true;
}
}
}

visibleEditWindow(true);
visibleCalendar(false);
}
}

- Make changes to the appleCurrentDay function to update the element in array

function applyCurrentDay(MouseEvent):void
{
if (currentDayHighlighted)
{
highlightDates[currentDayHighlightArrayID].desc = edit_desc_input.text;
highlightDates[currentDayHighlightArrayID].eYear = everyYearCheck.selected;
}
if (! currentDayHighlighted)
{
highlightDates.push({day: selectedDay, month: firs.month+1, year: firs.fullYear, desc: edit_desc_input.text, eYear: everyYearCheck.selected});
}
visibleCalendar(true);
visibleEditWindow(false);
compute();
}

- I edied and moved the 'n' variable loop from the end of the compute() function to the middle of it, because it has to be commenced before the 'l' variable ('n' loop checks if there are any every year dates this month, if there are - set their year to current; the 'l' loop paints all the cells)

for (var n:int=0; n<highlightDates.length; n++)
{
if (highlightDates[n].day == now.date && highlightDates[n].year == now.fullYear && highlightDates[n].month - 1 == now.month && firs.fullYear == now.fullYear && firs.month == now.month)
{
dayDescription.text = "TODAY: " + highlightDates[n].desc;
}
if (highlightDates[n].eYear==true){
highlightDates[n].year = firs.fullYear;
}
}

So here is the full code:

var highlightDates:Array = [];

var _loader:URLLoader = new URLLoader();
var _data:XML = new XML();

_loader.addEventListener(Event.COMPLETE, readXML);

_loader.load(new URLRequest("highlightedDates.xml"));

function readXML(event:Event):void
{
_data = new XML(event.target.data);
parseXML(_data);
}
function parseXML(xmlData:XML):void
{
for each (var day in xmlData.day)
{
highlightDates.push({day: day.@day, month: day.@month, year: day.@year, desc: day, eYear: day.@eYear});
}
}


var now:Date = new Date();
var firs:Date = new Date(now.fullYear,now.month,1);
var maxdays;

var dayDescription:TextField = new TextField();
addChild(dayDescription);
dayDescription.width = 200;
dayDescription.height = 40;
dayDescription.wordWrap = true;
dayDescription.y = 260;
dayDescription.x = 10;

var cellformat:TextFormat = new TextFormat();
cellformat.color = 0x012943;
cellformat.size = 16;
cellformat.align = "right";

var cformat:TextFormat = new TextFormat();
cformat.color = 0x000000;
cformat.size = 14;
cformat.align = "center";

var weekdays:Array = new Array("Mon","Tue","Wed","Thu","Fri","Sat","Sun");
var dayArray:Array = [];

var u:uint;
// the first loop to add week day names

for (u=0; u<7; u++)
{
var c:TextField = new TextField();
c.selectable = false;
c.width = 30;
c.text = weekdays[u];
c.setTextFormat(cformat);

addChild(c);
c.x=10+(30*u);
c.y = 10;
dayArray.push(c);
}

var i:uint;
var allcells:Array = new Array();
// the second loop to create cells

for (i=0; i<42; i++)
{

var cell:TextField = new TextField();
cell.background = true;
cell.backgroundColor = 0x99CCFF;
cell.border = true;
cell.borderColor = 0x9999CC;
cell.selectable = false;
cell.width = cell.height = 24;
cell.setTextFormat(cellformat);

addChild(cell);
cell.x=10+(30*(i-(Math.floor(i/7)*7)));
cell.y=40+(30*Math.floor(i/7));

allcells.push(cell);
}

var days:Array = new Array(6,0,1,2,3,4,5);


import fl.controls.ComboBox;
import fl.data.DataProvider;
import fl.events.ComponentEvent;

var monthsdata:Array = [
{label:"January", data:0},
{label:"February", data:1},
{label:"March", data:2},
{label:"April", data:3},
{label:"May", data:4},
{label:"June", data:5},
{label:"July", data:6},
{label:"August", data:7},
{label:"September", data:8},
{label:"October", data:9},
{label:"November", data:10},
{label:"December", data:11},
];

var monthpicker = new ComboBox();
monthpicker.dataProvider = new DataProvider(monthsdata);
addChild(monthpicker);
monthpicker.x = 10;
monthpicker.y = 230;

monthpicker.addEventListener(Event.CHANGE, monthHandler);

function monthHandler(event:Event):void
{
firs.month = ComboBox(event.target).selectedItem.data;
compute();
}

monthpicker.selectedIndex = now.month;

import fl.controls.NumericStepper;
import flash.text.TextField;

var yearpicker = new NumericStepper();
yearpicker.maximum = now.fullYear + 30;
yearpicker.minimum = now.fullYear - 30;
yearpicker.value = now.fullYear;
addChild(yearpicker);
yearpicker.x = 130;
yearpicker.y = 230;

yearpicker.addEventListener(Event.CHANGE, yearHandler);
function yearHandler(event:Event):void
{
firs.fullYear = event.target.value;
compute();
}

function compute()
{
var d:Number;
for (d=0; d<42; d++)
{
allcells[d].text = "";
allcells[d].backgroundColor = 0x99CCFF;
}

allcells[days[firs.day]].text = 1;
allcells[days[firs.day]].setTextFormat(cellformat);
var leapyear:Number;

if (firs.fullYear % 4 == 0 && firs.fullYear % 100 != 0 || firs.fullYear % 400 == 0)
{
leapyear = 1;
}
else
{
leapyear = 0;
}

if (firs.month == 0 || firs.month == 2 || firs.month == 4 || firs.month == 6 || firs.month == 7 || firs.month == 9 || firs.month == 11)
{
maxdays = 31;
}
else if (firs.month==3 || firs.month==5 || firs.month==8 || firs.month==10)
{
maxdays = 30;
}
else if (firs.month==1 && leapyear==1)
{
maxdays = 29;
}
else
{
maxdays = 28;
}

var p:Number;
for (p=1; p<maxdays; p++)
{
allcells[days[firs.day] + p].text = p + 1;
allcells[days[firs.day] + p].setTextFormat(cellformat);
}

for (var n:int=0; n<highlightDates.length; n++)
{
if (highlightDates[n].day == now.date && highlightDates[n].year == now.fullYear && highlightDates[n].month - 1 == now.month && firs.fullYear == now.fullYear && firs.month == now.month)
{
dayDescription.text = "TODAY: " + highlightDates[n].desc;
}
if (highlightDates[n].eYear==true){
highlightDates[n].year = firs.fullYear;
}
}

var l:Number;
var h:Number;
for (l=41; l>=0; l--)
{
for (h=0; h<highlightDates.length; h++)
{
if (allcells[l].text == highlightDates[h].day && firs.fullYear == highlightDates[h].year && firs.month == (highlightDates[h].month-1))
{
allcells[l].backgroundColor = 0x00FF66;
}
}

allcells[l].alpha = 1;
if (allcells[l].text == now.date && firs.fullYear == now.fullYear && firs.month == now.month)
{
allcells[l].backgroundColor = 0x00FFCB;
}
}
var q:Number;
for (q=1; q<(42-maxdays-days[firs.day]+1); q++)
{
allcells[days[firs.day] + q + maxdays - 1].text = q;
allcells[days[firs.day] + q + maxdays - 1].setTextFormat(cellformat);
allcells[days[firs.day] + q + maxdays - 1].alpha = 0.5;
}
var f:Number;
var prefirst = new Date(firs.fullYear,firs.month,firs.date - 1);
for (f=days[firs.day]; f>0; f--)
{
allcells[days[f]].text=prefirst.date-(days[firs.day]-f);
allcells[days[f]].setTextFormat(cellformat);
allcells[days[f]].alpha = 0.5;
}
dayDescription.text = "";

}

compute();

for (var a:int=0; a<42; a++)
{
allcells[a].addEventListener(MouseEvent.CLICK, displayDescription);
allcells[a].doubleClickEnabled = true;
allcells[a].addEventListener(MouseEvent.DOUBLE_CLICK, editHighlight);
}

function displayDescription(evt:MouseEvent):void
{
if (evt.target.alpha == 1)
{
for (var s:int=0; s<highlightDates.length; s++)
{
if (evt.target.text == highlightDates[s].day && firs.fullYear == highlightDates[s].year && firs.month == (highlightDates[s].month-1))
{
dayDescription.text = highlightDates[s].day + "." + highlightDates[s].month + "." + highlightDates[s].year + " - " + highlightDates[s].desc;
}
}
}
}

import fl.controls.TextInput;
import fl.controls.Button;
import fl.controls.CheckBox;

var edit_desc_input:TextInput = new TextInput();
edit_desc_input.width = 205;
edit_desc_input.height = 50;
edit_desc_input.x = 10;
edit_desc_input.y = 80;
addChild(edit_desc_input);

var edit_desc_clear:Button = new Button();
edit_desc_clear.x = 10;
edit_desc_clear.y = 140;
edit_desc_clear.label = "Clear day";
addChild(edit_desc_clear);

var edit_desc_apply:Button = new Button();
edit_desc_apply.x = 115;
edit_desc_apply.y = 140;
edit_desc_apply.label = "Apply";
addChild(edit_desc_apply);

var edit_desc_text:TextField = new TextField();
edit_desc_text.x = 10;
edit_desc_text.y = 50;
edit_desc_text.width = 200;
edit_desc_text.height = 20;
edit_desc_text.selectable = false;
edit_desc_text.text = "Highlight this day with description:";
addChild(edit_desc_text);

var everyYearCheck:CheckBox = new CheckBox();
addChild(everyYearCheck);
everyYearCheck.x = 10;
everyYearCheck.y = 180;
everyYearCheck.label = "Every year";

visibleEditWindow(false);

var currentDayHighlighted:Boolean;
var currentDayHighlightArrayID:Number;
var selectedDay:Number;

function editHighlight(evt:MouseEvent):void
{
if (evt.target.alpha == 1)
{
selectedDay = evt.target.text;
edit_desc_input.text = "";
currentDayHighlighted = false;
currentDayHighlightArrayID = NaN;
everyYearCheck.selected = false;
for (var cd:int=0; cd<highlightDates.length; cd++)
{
if (highlightDates[cd].day == evt.target.text && highlightDates[cd].month == firs.month + 1 && highlightDates[cd].year == firs.fullYear)
{
edit_desc_input.text = highlightDates[cd].desc;
currentDayHighlighted = true;
currentDayHighlightArrayID = cd;
if (highlightDates[cd].eYear)
{
everyYearCheck.selected = true;
}
}
}

visibleEditWindow(true);
visibleCalendar(false);
}
}

function visibleEditWindow(vis:Boolean):void
{
edit_desc_input.visible = vis;
edit_desc_clear.visible = vis;
edit_desc_apply.visible = vis;
edit_desc_text.visible = vis;
everyYearCheck.visible = vis;
}

function visibleCalendar(vis:Boolean):void
{
for (var v:int=0; v<42; v++)
{
allcells[v].visible = vis;
}
for (var d:int=0; d<7; d++)
{
dayArray[d].visible = vis;
}
yearpicker.visible = vis;
monthpicker.visible = vis;
dayDescription.visible = vis;
}

edit_desc_clear.addEventListener(MouseEvent.CLICK, clearCurrentDay);

function clearCurrentDay(MouseEvent):void
{
if (currentDayHighlighted)
{
highlightDates.splice(currentDayHighlightArrayID, 1);
}
visibleCalendar(true);
visibleEditWindow(false);
compute();
}

edit_desc_apply.addEventListener(MouseEvent.CLICK, applyCurrentDay);

function applyCurrentDay(MouseEvent):void
{
if (currentDayHighlighted)
{
highlightDates[currentDayHighlightArrayID].desc = edit_desc_input.text;
highlightDates[currentDayHighlightArrayID].eYear = everyYearCheck.selected;
}
if (! currentDayHighlighted)
{
highlightDates.push({day: selectedDay, month: firs.month+1, year: firs.fullYear, desc: edit_desc_input.text, eYear: everyYearCheck.selected});
}
visibleCalendar(true);
visibleEditWindow(false);
compute();
}


Thank you for reading!

Related:

How to create a calendar using only Actionscript 3 - part 1
How to create a calendar using only Actionscript 3 - part 2
How to create a calendar using only Actionscript 3 - part 3
How to create a calendar using only Actionscript 3 - part 4
How to create a calendar using only Actionscript 3 - part 5
How to create a calendar using only Actionscript 3 - part 6
How to create a calendar using only Actionscript 3 - part 7
How to create a calendar using only Actionscript 3 - part 8
How to create a calendar using only Actionscript 3 - part 9
How to create a calendar using only Actionscript 3 - part 10
How to create a calendar using only Actionscript 3 - part 11

4 comments:

Robert said...

Is there an easy way to change it so that Sunday is the first day and Saturday is the last day of the week? Thanks.

Kirill Poletaev said...

Check out the days array:

var days:Array = new Array(6,0,1,2,3,4,5);

Here each number represents a weekday (0 - Monday, 1 - Tuesday, etc.) Just put them in the order you want.

Robert said...

Yeah, I saw that. But to get the days before the first in an alpha less than 1 to display properly

and

var weekdays:Array = new Array("Sun","Mon","Tue","Wed","Thu","Fri","Sat");

I did the following:

var days:Array = new Array(0,1,2,3,4,5,6);

and added -1 below to firs.day and changed f>0 to f>-1

var f:Number;
var prefirst = new Date(firs.fullYear,firs.month,firs.date - 1);
for (f=days[firs.day-1]; f>-1; f--)
{
allcells[days[f]].text=prefirst.date-(days[firs.day-1]-f);
allcells[days[f]].setTextFormat(cellformat);
allcells[days[f]].alpha = 0.3;
}

otherwise day 1 would not display in the month and the alpha days would not start at the correct end of month dates and the first cell would be blank.

I'm sure there's an easier way though.

Samantha Lee said...

Hi there. I just want to say THANK YOU for posting this really awesome in depth tutorial. I need to do an events calendar for something I'm working on and this tutorial gives me exactly what I need and then some. I'll be tweaking things of course, but it gets me a great jumping off point. I just need to make it 'pretty'/match my theme. Thank you again. You are awesome :D

Post a Comment