Avg. Rating 3.3

Problem

This project demonstrates how to use the timer class as well as how to do some complex math to build a backwards countdown timer. While it appears simplistic, accounting for un-even length months and localized time zone offsets adds some complexity.

Solution

This recipe also demonstrates how to include multiple MXML components in one project and how to reference them. Prayank Swaroop and I wrote this last year and just ported it to Flex Builder 3, beta 3.

Detailed explanation

The basic structure of this project is as follows:

<project_root>
    - src
          - AIR3_BackwardsTimer.mxml
    -utils
          - SimpleClock.mxml
    - images
          - Picture 38..png


To include the //utils/SimpleClock.mxml components in the project, it is as simple as adding one attribute to the first line of the application as show below in bold:

<mx:WindowedApplication   showFlexChrome="false" xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"
    xmlns:utils="utils.*" creationComplete="init()" height="154" width="465">

This tells the compiler to look in the folder "utils" and include any components in that folder.  You can then add them to your project by using the namespace to qualify them as shown below:

<utils:SimpleClock x="109" y="43" fontSize="12" fontWeight="bold" id="countDownClock"  width="326" textAlign="right"/>   

Note that code complete in Flex Builder 3, beta 3 will automatically include any inherited properties, events etc.

The AIR3_BackwardsTimer.mxml class is as follows. You can also download the source below and import the finished project.

*****************SOURCE***********************

<?xml version="1.0" encoding="utf-8"?>
<mx:WindowedApplication   showFlexChrome="false" xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"
    xmlns:utils="utils.*" creationComplete="init()" height="154" width="465">
<!--Note the use of @showFlexChrome="false".  Without this, you will still end up with some AIR chrome. -->
<!--The line xmlns:utils="utils.*" declares the namespace and references anything in the utils folder -->
<!--creationComplete="init()" calls the init() function once the app has created itself-->

<!--The Style tag below declares the CSS to make the application fully chromeless-->
 <mx:Style>
  
        Application
        {
            /*make app window transparent*/
            background-color:"";
            background-image:"";
            padding: 0px;
            margin-top: 0;
            margin-right: 0;
            margin-bottom: 0;
            margin-left: 0;
        }
      
    </mx:Style>
 
     <mx:Script>

         <![CDATA[
            import flash.display.Bitmap;
            import mx.events.CloseEvent;
           
            private var MAX_DATE:Date = new Date();
             private function init():void {

            // Move the app when the panelis dragged
                mainPanel.addEventListener( MouseEvent.MOUSE_DOWN, startMove );
               
                function startMove(event:MouseEvent):void {
                   stage.nativeWindow.startMove();
            }
                 // This set the specific date as the 30th of the month.
                 MAX_DATE.setDate(29);
                 countDownClock.countDownDate = MAX_DATE;
             }
             // This makes the close button work.
             public function closeEvent(event:CloseEvent):void {
                   stage.nativeWindow.close();
            }

         ]]>

     </mx:Script>

    <mx:TitleWindow  id="mainPanel" backgroundColor="#0326FD"  layout="absolute" cornerRadius="15" alpha="1.0"
        color="#FFFEFE" width="465" height="153" backgroundAlpha="0.7" borderColor="#1FBDF7" themeColor="#2FE7FD"
        x="0" showCloseButton="true" close="closeEvent(event)">

            <mx:Image x="0" y="0" width="100%" height="113" source="images/Picture 38.png"/>
            <utils:SimpleClock x="109" y="43" fontSize="12" fontWeight="bold" id="countDownClock"  width="326" textAlign="right"/>   
            <mx:Label x="198" y="10" text="Adobe MAX 2008 Begins in" fontWeight="bold" fontSize="16"/>
            <mx:Label x="235" y="85" text=" http://www.adobemax2008.com" fontWeight="bold" fontSize="10" width="200"/>
            <mx:LinkButton x="145" y="81" label="Register"  enabled="true"/>
        </mx:TitleWindow>
</mx:WindowedApplication>

***********************************************

The SimpleClock.mxml component is where all the heavy lifting is done.  Note that all counts of arrays of days, months start at zero and not one.  Also note the complex math involved in calculating the days, months minutes, seconds remaining.  Lastly, there is a simple function call to get the time zone offset to account for the users local time.

********************SOURCE SimpleClock.mxml**********************

<?xml version="1.0" encoding="utf-8"?>
 
<!--
Simple clock class to return a string representing a count down to MAX 2007.
This can be modified to return a Date object instead of a string object
Authors: Prayank Swaroop, Duane Nickull 2007. No warranties exist - use
at your own peril.  We warned you. Send complaints to dev@null.net
-->
<mx:Label xmlns:mx="http://www.adobe.com/2006/mxml" creationComplete="init()">
    <mx:Script>
        <![CDATA[
            public var countDownDate:Date = new Date;
            // countDownDate.getDate();

            private function init():void

            {
                //public var countDownDate:Date;
                // creates a Timer that fires an event once per second
                var ticker:Timer = new Timer(1000);

                // designates the onTick() method to handle Timer events
                ticker.addEventListener(TimerEvent.TIMER, onTick);

                // starts the clock ticking
                ticker.start();
            }

           

            public function onTick(evt:TimerEvent):void

            {
                // updates the clock display
                //this.text = getCountDown(countDownDate.getTime() - (new Date()).getTime());
                this.text = getCountDown(countDownDate.getTime());

            }

            protected function getCountDown(uptime:Number):String

            {
                //current date
                var currentDate:Date
               
                // get current Date
                currentDate = new Date();
               
                //initialize event variables. Seconds are using Math().
                var eventMonth:int = 10; //Nov = 8
                var eventDay:int = 15; //day = 16
                var eventHour:int = 15; //the event starts at 8 AM local + 8 (-1 for starting at zero) for 15 GMT
                var eventMinutes:int = 0; // assume it starts right at 8:00 AM sharp. Yeah right....
               
                //get time zone offset. Number returned in minutes.
                var currentOffset:Number = currentDate.getTimezoneOffset();
               
                //check if we started
                if(uptime <= 0) return "MAX has begun!";

                var secs:Number = uptime/1000;
               
                // Construct String
                var result:String = new String();
               
                // For debug only...
                //result += "Current UTC date is: " + currentDate + ".  MAX 2007 is ";
               
                // Build Result string
                //result += "MAX 2007 begins in ";
              
                /*How many months until MAX 2007*/
                var months2MAX:int =
                eventMonth - currentDate.getMonth();
                result += months2MAX + " Months ";

                /*How many days until max*/
                var days2MAX:int = eventDay - currentDate.getDate();
                result += days2MAX + " Days " ;               
               
                /* How many hours including the offset from users local time
                 * - getHours returns the 0-23 value, adding in offset comes up with current GMT time
                 * - subtract the event hour to get offset then subtract number from 24 to count down.
                 */
                var hours2MAX:int = 24 - ((currentDate.getHours() + (currentOffset/60))- eventHour);
                result += hours2MAX + " Hours ";
           
                var minutes2MAX:int = (60 - currentDate.getMinutes());
                result += minutes2MAX + " Min ";
               
                result += (60 - currentDate.getSeconds()) + " Sec" ;
               
                return result;
            }
        ]]>

    </mx:Script>

</mx:Label>


AIR3_BackwardsTimer.zip
[Backwards timer, composed of multipel mxml components]
Report abuse

Related recipes