<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>hubflanger &#187; PureMVC</title>
	<atom:link href="http://hubflanger.com/category/puremvc/feed/" rel="self" type="application/rss+xml" />
	<link>http://hubflanger.com</link>
	<description>adventures in code</description>
	<lastBuildDate>Mon, 29 Mar 2010 22:41:12 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
		<atom:link rel='hub' href='http://hubflanger.com/?pushpress=hub'/>
		<item>
		<title>Building a Flash site using PureMVC</title>
		<link>http://hubflanger.com/building-a-flash-site-using-puremvc/</link>
		<comments>http://hubflanger.com/building-a-flash-site-using-puremvc/#comments</comments>
		<pubDate>Mon, 14 Apr 2008 03:55:44 +0000</pubDate>
		<dc:creator>Peng</dc:creator>
				<category><![CDATA[Actionscript]]></category>
		<category><![CDATA[Flash]]></category>
		<category><![CDATA[PureMVC]]></category>
		<category><![CDATA[Tutorials]]></category>

		<guid isPermaLink="false">http://hubflanger.com/?p=37</guid>
		<description><![CDATA[At a recent FlashCodersNY meeting where the discussion centered around the subject of the MVC (Model-View-Controller) design pattern, it struck me that a lot of Flash developers, especially those coming from design backgrounds, did not see the value in using the MVC design pattern.
Well, I&#8217;m not here to make the case for using MVC but [...]]]></description>
			<content:encoded><![CDATA[<p>At a recent <a href="http://flashcodersny.org" target="_blank">FlashCodersNY</a> meeting where the discussion centered around the subject of the MVC (Model-View-Controller) design pattern, it struck me that a lot of Flash developers, especially those coming from design backgrounds, did not see the value in using the MVC design pattern.</p>
<p>Well, I&#8217;m not here to make the case for using MVC but if you have spent enough time struggling with structuring an application so that it&#8217;s clearly represented by a set of well-defined relationships and responsibilities, you would&#8217;ve likely tried to implement some kind of MVC pattern. Now, some design pattern is certainly better none. Trouble is, every developer has his or her own approach to MVC. When a team of developers are working on the same project, things can get confusing pretty quickly if there are no common standards to adhere to.</p>
<p><span id="more-37"></span><br />
This brings us to the <a href="http://puremvc.org" target="_blank">PureMVC</a> framework. Created by Cliff Hall, this framework provides a set of well-defined protocols for implementing the MVC design pattern with your application, rendering the grunt work of manually hooking up an MCV structure a thing of the past. However, great as <a href="http://puremvc.org" target="_blank">PureMVC</a> may be, it does not present an easy learning curve for some, especially those who are just getting started with OOP and design patterns.</p>
<p>In this tutorial, I will show you how to build a Flash site using PureMVC. If you&#8217;re familiar with the Flash IDE and have some experience with OOP and writing classes, you&#8217;re pretty much ready to go. </p>
<p><a href="/demos/puremvc_flashsite/">View Demo</a></p>
<p><a href="http://github.com/hubflanger/PureMVC_Flash_Site">Download Source Files</a></p>
<h3>1. Creating the Flash assets</h3>
<p>Open <code>fla/PureMVCSite.fla</code> in the Flash IDE. In the Library Panel, you&#8217;ll see that I have created various assets for our Flash site: </p>
<ul>
<li>A <code>site</code> movieclip that serves as a container clip with the UI elements laid out in the desired fashion</li>
<li>A <code>header</code> movieclip containing a dynamic textfield for the site header</li>
<li>A <code>nav</code> movieclip containing 3 <code>navButton</code> instances
</li>
<li>A <code>body</code> movieclip containing a dynamic multiline textfield for the body content</li>
</ul>
<p>The <code>site</code> movieclip symbol is linked to the class <code>Site</code>. The <code>nav</code> movieclip symbol is linked to the class <code>MainNav</code>. Both these classes belong to the package <code>com.hubflanger.puremvc.view.component</code>. In the PureMVC world, these are known as &#8220;view components&#8221;, not to be confused with the built-in Flash components. These components communicate with the PureMVC framework via their associated <em>Mediators</em>, allowing them to be &#8220;loosely-coupled&#8221;, thereby granting you great flexibility in changing their behavior without impacting the rest of your application.</p>
<p>In the <strong>ActionScript 3.0 Setting</strong> of the <strong>Publish Settings</strong>, you&#8217;ll see that <strong>Classpath</strong> has been set to point to &#8220;<code>../src</code>&#8220;. This tells the Flash compiler that the <code>as</code> folder is where you&#8217;ll look for the class files for this application.</p>
<h3>2. Examining the PureMVC package</h3>
<p>The PureMVC package <code>org.puremvc.as3</code> (version 2.0.3) is located at <code>src/org/puremvc/as3</code> and has been included for your convenience. The AS3 port of the PureMVC framework is hosted <a href="http://puremvc.org/component/option,com_wrapper/Itemid,160/" target="_blank">here</a>. I strongly encourage you to spend some time reading the online <a href="http://puremvc.org/component/option,com_wrapper/Itemid,35/" target="_blank">documentation</a> if possible.</p>
<p>At any time during this tutorial, if you feel the need for a clearer understanding of PureMVC terminologies such as <em>Mediator</em>, <em>Proxy</em> or <em>Notification</em>, please feel free to refer to these classes. Cliff Hall has done an excellent job of commenting them and the comments will provide a clear picture of each class&#8217; role in the framework.</p>
<h3>3. Examining PureMVCSite.as and ApplicationFacade.as</h3>
<p>The main timeline of <code>PureMVCSite.fla</code> is linked to the document class <code>PureMVCSite</code> which is initialized when the application starts. <code>PureMVCSite.as</code> resides at the root of the <code>as</code> folder. When the application launches, <code>PureMVCSite</code> creates a Singleton instance of <code>ApplicationFacade</code>. The <code>ApplicationFacade</code> is the entry point to the PureMVC framework. When you instantiate <code>ApplicationFacade</code>, a whole slew of events take place behind the scenes to wire up your application with the PureMVC framework.</p>
<div class="codeblock">
<pre>
package
{
  import com.hubflanger.puremvcsite.ApplicationFacade;
  import flash.display.Sprite;

  public class PureMVCSite extends Sprite
  {
    private var facade:ApplicationFacade;

    public function PureMVCSite()
    {
      facade = ApplicationFacade.getInstance();
      facade.startup( this.stage );
    }
  }
}
</pre>
</div>
<p>Let&#8217;s first examine the static constants defined at the beginning of this class. <code>STARTUP</code><code>, </code><code>INITIALIZE_SITE</code> and <code>SECTION_CHANGED</code> represent the <em>Notification</em> names of the events that our application will be responding to. A <em>Notification</em> is the default messaging deployed by PureMVC to inform the framework of an event that has been dispatched. In PureMVC land, sending a <em>Notification</em> is synonymous with broadcasting an event. Only difference is, it does a little more than just broadcasting it to everyone, whether they want to hear it or not. PureMVC finds the select audience who are &#8220;ticket holders&#8221; to an event, and drives them to the venue. I will explain this in greater detail later.</p>
<div class="codeblock">
<pre>
package com.hubflanger.puremvcsite
{
  import org.puremvc.as3.interfaces.IFacade;
  import org.puremvc.as3.patterns.facade.Facade;
  import com.hubflanger.puremvcsite.controller.StartupCommand;

  public class ApplicationFacade extends Facade implements IFacade
  {
    public static const STARTUP:String      = "startup";
    public static const INITIALIZE_SITE:String  = "initializeSite";
    public static const SECTION_CHANGED:String  = "sectionChanged";

    public static function getInstance() : ApplicationFacade
    {
      if ( instance == null ) instance = new ApplicationFacade();
      return instance as ApplicationFacade;
    }

    override protected function initializeController() : void
    {
      super.initializeController();
      registerCommand( STARTUP, StartupCommand );
    }

    public function startup( stage:Object ):void
    {
      sendNotification( STARTUP, stage );
    }
  }
}
</pre>
</div>
<p><code>ApplicationFacade</code> overrides <code>initializeController()</code> to register <code>StartupCommand</code> with the <code>STARTUP</code> <em>Notification</em>. Behind the scenes, the <em>Controller</em> adds <code>StartupCommand</code> to its <code>commandMap</code> array and notes that <code>StartupCommand</code> is interested in listening for the <code>STARTUP</code> notification event.</p>
<p>The <code>startup()</code> method in <code>ApplicationFacade</code> is then explicitly called by <code>PureMVCSite</code>, passing in a reference to the <code>Stage</code>. This creates a <em>Notification</em> object with the name &#8220;startUp&#8221; and a reference to the <code>Stage</code> assigned to the its <code>body</code> property.</p>
<h3>4. Examining StartupCommand.as</h3>
<p>Upon receiving the <em>Notification</em>, the <em>Controller</em> iterates through its <code>commandMap</code> and retrieves <code>StartupCommand</code> as an object that is interested in the <code>STARTUP</code> notification. This results in the <code>execute()</code> method in <code>StartupCommand</code> being called.</p>
<div class="codeblock">
<pre>
package com.hubflanger.puremvcsite.controller
{
  import flash.display.Stage;
  import org.puremvc.as3.interfaces.ICommand;
  import org.puremvc.as3.interfaces.INotification;
  import org.puremvc.as3.patterns.command.SimpleCommand;
  import com.hubflanger.puremvcsite.ApplicationFacade;
  import com.hubflanger.puremvcsite.view.StageMediator;
  import com.hubflanger.puremvcsite.model.SiteDataProxy;

  public class StartupCommand extends SimpleCommand implements ICommand
  {
    override public function execute( note:INotification ) : void
    {
      var stage:Stage = note.getBody() as Stage;
      facade.registerMediator( new StageMediator( stage ) );
      facade.registerProxy( new SiteDataProxy() );
    }
  }
}
</pre>
</div>
<p>The <code>execute()</code> method in <code>StartupCommand</code> retrieves the reference to the <code>Stage</code> from the <em>Notification</em> and passes that along to an instance of the <code>StageMediator</code> being created. It also creates an instance of <code>SiteDataProxy</code>. </p>
<p><code>facade</code> is a built-in property of the <em>Mediator</em> and <em>Proxy</em> base classes from which <code>StageMediator</code> and <code>SiteDataProxy</code> extends respectively. It refers to the <code>ApplicationFacade</code> instance which extends the <em>Facade</em> base class. </p>
<p><code>facade.registerMediator()</code> registers the newly created <em>Mediator</em> instance with the <em>View</em> which stores it in its <code>mediatorMap</code>. The <em>Mediator</em> instance can be retrieved during runtime via a simple reference of its static <code>NAME</code> property using <code>facade.retrieveMediator()</code>.</p>
<p>Similarly, <code>facade.registerProxy()</code> registers the newly created <em>Proxy</em> instance with the <em>Model</em> which stores it in its <code>proxyMap</code>. The <em>Proxy</em> instance can also be retrieved by passing its <code>NAME</code> property to the <code>facade.retrieveProxy()</code> method.</p>
<p>At this point, you&#8217;ll probably start to notice a pattern here. The <em>Model</em>, <em>View</em> and <em>Controller</em> all have methods and properties that mirror each other, tying the <em>Proxy</em> to the <em>Model</em>, the <em>Mediator</em> to the <em>View</em> and the <em>Command</em> to the <em>Controller</em>. You&#8217;ll also notice that the <em>Facade</em> indeed provides a &#8220;shortcut&#8221; to accessing various parts of your application within the PureMVC framework. Nobody talks to the <em>Model</em>, <em>View</em> or <em>Controller</em> directly. Everybody goes through the middle man named <em>Facade</em>.</p>
<h3>5. Examining StageMediator.as</h3>
<p>The <code>StageMediator</code> facilitates the communication between the <code>Stage</code> and the PureMVC framework. The <code>Stage</code> instance is referenced via the <code>viewComponent</code> property inherited from the <em>Mediator</em> base class. In PureMVC convention, it is also commonplace to create an accessor method such as &#8220;<code>get stage()</code>&#8220;. Two very important methods of the <em>Mediator</em> instance are the <code>listNotificationInterests()</code> method and the <code>handleNotification()</code> method, which every <em>Mediator</em> subclass must override. </p>
<p><code>listNotificationInterests()</code> returns an array of <em>Notification</em> names as defined in <code>ApplicationFacade</code>, representing events that this particular <em>Mediator</em> is interested in. When the <em>View</em> runs through its list of <em>Observers</em>, it checks each <em>Mediator</em> against its <em>Notification</em> interests. If there is a match pertaining to a specific <em>Notification</em>, the <code>handleNotification()</code> method of that <em>Mediator</em> is called. This is what I was referring to earlier by the select audience who are &#8220;ticket holders&#8221; to an event. In this case, our <code>StageMediator</code> is interested in the <code>INITIALIZE_SITE</code> <em>Notification</em>.</p>
<p>The <em>Mediator</em> base class extends <em>Notifier</em> which means that in addition to responding to <em>Notification</em>s, it is also capable of sending out <em>Notification</em>s via the <code>sendNotification()</code> method. In other words, it can dispatch events. Although, unlike a MovieClip, it can&#8217;t dispatch any Flash Events, instead, it dispatches <em>Notification</em> objects.</p>
<div class="codeblock">
<pre>
package com.hubflanger.puremvcsite.view
{
  import com.hubflanger.puremvcsite.ApplicationFacade;
  import com.hubflanger.puremvcsite.view.component.Site;
  import flash.display.Stage;
  import flash.events.MouseEvent;
  import org.puremvc.as3.interfaces.*;
  import org.puremvc.as3.patterns.mediator.Mediator;

  public class StageMediator extends Mediator implements IMediator
  {
    public static const NAME:String = "StageMediator";

    public function StageMediator( viewComponent:Object )
    {
      super( NAME, viewComponent );
    }

    override public function listNotificationInterests():Array
    {
      return [
          ApplicationFacade.INITIALIZE_SITE
          ];
    }

    override public function handleNotification( note:INotification ):void
    {
      switch ( note.getName() )
      {
        case ApplicationFacade.INITIALIZE_SITE:
          initializeSite();
          break;
      }
    }

    private function initializeSite():void
    {
      var site:Site = new Site();
      facade.registerMediator( new SiteMediator( site ) );
      facade.registerMediator( new NavMediator( site.nav ) );
      stage.addChild( site );

      var navMediator:NavMediator = facade.retrieveMediator( NavMediator.NAME ) as NavMediator;
      sendNotification( ApplicationFacade.SECTION_CHANGED, navMediator.currentSection );
    }

    protected function get stage():Stage
    {
    return viewComponent as Stage;
    }
  }
}
</pre>
</div>
<h3>6. Examining SiteDataProxy.as</h3>
<p><code>SiteDataProxy</code> represents the data model for the application. It loads in dynamic data via xml and then parses and stores that information in a built-in property named &#8220;<code>data</code>&#8220;. Like the <em>Mediator</em>, the <em>Proxy</em> object also extends <em>Notifier</em> which makes it capable of sending out <em>Notification</em>s via the <code>sendNotification()</code> method. Unlike the <em>Mediator</em>, the <em>Proxy</em> does not have <em>Notification</em> interests and one can and should only update the <em>Proxy</em> via a <em>Command</em>.</p>
<div class="codeblock">
<pre>
package com.hubflanger.puremvcsite.model
{
  import com.hubflanger.puremvcsite.ApplicationFacade;
  import flash.events.Event;
  import flash.net.URLLoader;
  import flash.net.URLRequest;
  import org.puremvc.as3.interfaces.IProxy;
  import org.puremvc.as3.patterns.proxy.Proxy;

  public class SiteDataProxy extends Proxy implements IProxy
  {
    public static const NAME:String = "SiteDataProxy";
    public var navIDs:Array;

    public function SiteDataProxy( )
    {
      super( NAME, new Object() );

      var loader:URLLoader = new URLLoader();
      loader.addEventListener( Event.COMPLETE, onDataLoaded );

      try {
        loader.load( new URLRequest( "data.xml" ));
      } catch ( error:Error ) {
        trace( "Unable to load requested document." );
      }
    }

    private function onDataLoaded( evt:Event ):void
    {
      var xml:XML = new XML( evt.target.data );
      xml.ignoreWhitespace = true;

      data.header = xml.header.children().toXMLString();

      var sections:XMLList = xml.sections.section;
      navIDs = new Array();

      for ( var i:uint=0; i&lt;sections.length(); i++ )
      {
        var section:XML = sections[ i ];
        var id:String = section.@id;
        navIDs[ i ] = id;

        var vo:SectionVO = new SectionVO( id,
                          section.@label,
                          section.content );
        data[ id ] = vo;
      }

      sendNotification( ApplicationFacade.INITIALIZE_SITE );
    }
  }
}
</pre>
</div>
<p>When <code>SiteDataProxy</code> is done parsing the xml data, it sends out a <code>INITIALIZE_SITE</code> <em>Notification</em>, resulting in the <code>handleNotification()</code> method of <code>StageMediator</code> being called. This in turn calls the <code>initializeSite()</code> method which initializes the <code>SiteMediator</code> and <code>NavMediator</code> instances. These two <em>Mediators</em> serve to facilitate communication between the <code>Site</code> movieclip and the <code>MainNav</code> movieclip with the framework.</p>
<h3>7. Examining SiteMediator.as</h3>
<p><code>SiteMediator</code> retrieves data from <code>SiteDataProxy</code> and calls <code>site.init()</code> to initialize the header text. It also declares an interest in the <code>SECTION_CHANGED</code> <em>Notification</em> event and calls <code>site.updateBody()</code> to update its content when such an event is dispatched.</p>
<div class="codeblock">
<pre>
package com.hubflanger.puremvcsite.view
{
  import com.hubflanger.puremvcsite.ApplicationFacade;
  import com.hubflanger.puremvcsite.model.*;
  import com.hubflanger.puremvcsite.view.component.Site;
  import org.puremvc.as3.interfaces.*;
  import org.puremvc.as3.patterns.mediator.Mediator;

  public class SiteMediator extends Mediator implements IMediator
  {
    public static const NAME:String = "SiteMediator";
    private var _siteDataProxy:SiteDataProxy;

    public function SiteMediator( viewComponent:Object )
    {
      super( NAME, viewComponent );

      _siteDataProxy = facade.retrieveProxy( SiteDataProxy.NAME ) as SiteDataProxy;
      var data:Object = _siteDataProxy.getData();
      site.init( data.header );
    }

    override public function listNotificationInterests():Array
    {
      return [
          ApplicationFacade.SECTION_CHANGED
          ];
    }

    override public function handleNotification( note:INotification ):void
    {
      switch ( note.getName() ) {
        case ApplicationFacade.SECTION_CHANGED:
          update( note.getBody() as String );
          break;
      }
    }

    private function update( s:String ):void
    {
      var data:Object = _siteDataProxy.getData();
      var vo:SectionVO = data[ s ];
      var content:XMLList = vo.content;

      site.updateBody( content.toXMLString() );
    }

    protected function get site():Site
    {
      return viewComponent as Site;
    }
  }
}
</pre>
</div>
<h3>8. Examining NavMediator.as and MainNav.as</h3>
<p><code>NavMediator</code> retrieves navigation id and label info from <code>SiteDataProxy</code> and passes that along to the <code>MainNav</code> instance, allowing <code>MainNav</code> to initialize its <code>navButton</code> instances. <code>MainNav</code> registers itself as an event listener of <code>MOUSE_DOWN</code> events triggered by the <code>navButton</code> instances. </p>
<p><code>NavMediator</code> in turn registers itself as an event listener of the <code>NAV_BUTTON_PRESSED</code> UIEvent bubbled up by the <code>MainNav</code> instance. Upon receiving such an event, <code>NavMediator</code> checks it against its <code>currentSection</code> variable to determine if a <code>SECTION_CHANGED</code> <em>Notification</em> should be sent.</p>
<p>When the <code>SECTION_CHANGED</code> <em>Notification</em> is sent, <code>SiteMediator</code> will respond and update the content in the <code>body</code> movieclip, and <code>NavMediator</code> will update its <code>navButton</code> instances to display the correct state depending on each button&#8217;s id.</p>
<div class="codeblock">
<pre>
package com.hubflanger.puremvcsite.view
{
  import com.hubflanger.puremvcsite.ApplicationFacade;
  import com.hubflanger.puremvcsite.model.*;
  import com.hubflanger.puremvcsite.view.component.MainNav;
  import com.hubflanger.puremvcsite.view.event.UIEvent;
  import org.puremvc.as3.interfaces.*;
  import org.puremvc.as3.patterns.mediator.Mediator;

  public class NavMediator extends Mediator implements IMediator
  {
    public static const NAME:String = "NavMediator";
    private var _siteDataProxy:SiteDataProxy;
    public var currentSection:String;

    public function NavMediator( viewComponent:Object )
    {
      super( NAME, viewComponent );

      _siteDataProxy = facade.retrieveProxy( SiteDataProxy.NAME ) as SiteDataProxy;
      nav.addEventListener( UIEvent.NAV_BUTTON_PRESSED, onNavButtonPressed );

      var data:Object = _siteDataProxy.getData();
      var navIDs:Array = _siteDataProxy.navIDs;
      var navLabels:Array = new Array();

      currentSection = navIDs[ 0 ];

      for ( var i:uint=0; i&lt;navIDs.length; i++ )
      {
        var id:String = navIDs[ i ];
        var vo:SectionVO = data[ id ];
        navLabels[ id ] = vo.label;
      } 

      nav.init( navIDs, navLabels );
    }

    override public function listNotificationInterests():Array
    {
      return [
          ApplicationFacade.SECTION_CHANGED
          ];
    }

    override public function handleNotification( note:INotification ):void
    {
      switch ( note.getName() ) {

        case ApplicationFacade.SECTION_CHANGED:
          nav.update( note.getBody() as String );
          break;
      }
    }

    private function onNavButtonPressed( evt:UIEvent ):void
    {
      if ( evt.id != currentSection ) {
        currentSection = evt.id;
        sendNotification( ApplicationFacade.SECTION_CHANGED, evt.id );
      }
    }

    protected function get nav():MainNav
    {
      return viewComponent as MainNav;
    }
  }
}
</pre>
</div>
<p></p>
<div class="codeblock">
<pre>
package com.hubflanger.puremvcsite.view.component
{
  import com.hubflanger.puremvcsite.view.event.UIEvent;
  import flash.display.MovieClip;
  import flash.events.*;

  public class MainNav extends MovieClip
  {
    public var btn0:MovieClip;
    public var btn1:MovieClip;
    public var btn2:MovieClip;
    private var navButtons:Array;

    public function MainNav()
    {
      navButtons = [ btn0, btn1, btn2 ];
    }

    public function init( navIDs:Array, labels:Array ):void
    {
      for ( var i:uint=0; i&lt;navIDs.length; i++ )
      {
        var id:String = navIDs[ i ];
        var btn:MovieClip = navButtons[ i ];
        btn.id = id;
        btn.txt.text = labels[ id ];
        btn.buttonMode = true;
        btn.mouseChildren = false;
        btn.addEventListener( MouseEvent.MOUSE_DOWN, onMouseDownHandler );
      }
    }

    public function update( s:String ):void
    {
      for ( var i:uint=0; i&lt;navButtons.length; i++ )
      {
        var btn:MovieClip = navButtons[ i ];

        if ( btn.id == s ) {
          btn.txt.textColor = 0x4B1E18;
        } else {
          btn.txt.textColor = 0xFFFFFF;
        }
      }
    }

    private function onMouseDownHandler( evt:Event ):void
    {
      dispatchEvent( new UIEvent( UIEvent.NAV_BUTTON_PRESSED, evt.target.id ));
    }
  }
}
</pre>
</div>
<h3>9. In Closing</h3>
<p>This is pretty much the gist of what happens within a PureMVC Flash application. It is my hope that this real-world example will help you get a jump start on using the PureMVC framework for your Flash projects. I also hope this tutorial managed to demonstrate the value and power of the MVC design pattern. As you start developing applications of greater complexity, using a framework such as PureMVC will help immensely in keeping your classes loosely-coupled, and easier to scale and maintain. Happy coding!</p>
]]></content:encoded>
			<wfw:commentRss>http://hubflanger.com/building-a-flash-site-using-puremvc/feed/</wfw:commentRss>
		<slash:comments>54</slash:comments>
		</item>
		<item>
		<title>PureMVC Tutorials</title>
		<link>http://hubflanger.com/puremvc-tutorials/</link>
		<comments>http://hubflanger.com/puremvc-tutorials/#comments</comments>
		<pubDate>Mon, 31 Mar 2008 02:44:23 +0000</pubDate>
		<dc:creator>Peng</dc:creator>
				<category><![CDATA[Actionscript]]></category>
		<category><![CDATA[Flex]]></category>
		<category><![CDATA[PureMVC]]></category>
		<category><![CDATA[Flash]]></category>

		<guid isPermaLink="false">http://hubflanger.com/?p=36</guid>
		<description><![CDATA[I recently started looking into using PureMVC for our Flash projects at work. While the project site has plenty of great demos for one to download and examine, there aren&#8217;t enough tutorials out there that show step-by-step, how to start building an application using the framework. Fortunately, my friends over at 9M Media have put [...]]]></description>
			<content:encoded><![CDATA[<p>I recently started looking into using <a href="http://www.puremvc.org/" target="_blank">PureMVC</a> for our Flash projects at work. While the project site has plenty of great demos for one to download and examine, there aren&#8217;t enough tutorials out there that show step-by-step, how to start building an application using the framework. Fortunately, my friends over at <a href="http://9mmedia.com" target="_blank">9M Media</a> have put together an excellent series of articles on <a href="http://www.puremvc.org/" target="_blank">PureMVC</a> to help get you started. <a href="http://9mmedia.com/blog/?cat=9" target="_blank">Check it out</a> for yourselves. <span id="more-36"></span></p>
<p>The first 3 articles are: </p>
<p><a href="http://9mmedia.com/blog/?p=9" target="_blank">Why PureMVC Kicks Ass</a><br />
<a href="http://9mmedia.com/blog/?p=10" target="_blank">How to Setup Your First PureMVC Application</a><br />
<a href="http://9mmedia.com/blog/?p=22" target="_blank">Reusable Components using PureMVC</a></p>
]]></content:encoded>
			<wfw:commentRss>http://hubflanger.com/puremvc-tutorials/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>
