Baby meet world - world meet baby nimer!

No one ever called me the quickest blogger, but I'm excited to announce the newest nimer in the world.



Kayden Michael Nimer
Born: Oct 29th 2007
7lbs 10oz - 21" long


Kayden is a perfectly healthy baby boy and both mom and are baby are doing great. So being a new dad I can't stop thinking about the question where do I start with all of these cool toy options? :)

Flex Tip - Trigger validation when submitting form

I just noticed a common pattern in the way I do validation, so I thought I would share. (in case you didn't know this already)

The validators are great at telling the user what is required or failing validation as the tab through the form. However they don't actually block the user from submitting the invalid form. But there is a simple way to do this with the validators.

1. Group all of the validators into an MX:ARRAY tag, and give it a unique id. - I usually use "validators"

<mx:Array id="validators">
   <mx:StringValidator source="{abbreviations}" property="text" required="true"/>
   <mx:StringValidator source="{subcode}" property="text" required="true"/>
   <mx:StringValidator source="{name}" property="text" required="true"/>
   <mx:StringValidator source="{letterType}" property="text" required="true"/>
   <mx:StringValidator   source="{scheduleType}" property="text" required="true"/>
</mx:Array>

Since the validators are now all grouped in an Array, you can call the Validator.validateAll() function to check them all at once.

2. Use this if statement in the click event of your form submit button to check the validators before submitting. You can also add this if check inside your doSave() method too. whichever you prefer.

if( Validator.validateAll(validators).length==0 ){ doSave() }

<mx:Button
   label="Save"
   click="if( Validator.validateAll(validators).length==0 ){ doSave() }"/>

Suddenly I don't want anything to do with plastic products.

"A vast swath of the Pacific, twice the size of Texas, is full of a plastic stew that is entering the food chain. Scientists say these toxins are causing obesity, infertility...and worse"

There is everything wrong with the fact that this pile of trash exists. And even worse, there is more than one in the world.

I don't even know where to begin with a solution. But cutting back on the use of plastic seems like a good place to start. Everything doesn't need to be made out of plastic, I know I prefer the glass coke bottles to the plastic ones. Maybe some mandatory recycling programs are needed. I just hope something changes other wise the world 20 years from now could be a nasty place to live.

Read article

I want to see this - looks like I need to go to Berlin

"Placed at the lobby of the Radisson SAS Hotel in Berlin, the 25 meters high AquaDom is the largest cylindrical aquarium ever built." http://fogonazos.blogspot.com/2007/01/aquadom-worlds-largest-cylindrical.html

Bye bye -services!

When you are building an application that uses the Flex FDS or ColdFusion servers as a back-end you need to define in your FlexBuilder project properties an additional compiler argument, -services. Why? FlexBuilder needs this argument/path to your services-config.xml file so it can pull just a few pieces of information out of the xml file. In turn, these pieces of information are what allows your flex client application to know what server to talk to and how. However, this has a few drawbacks.

  • You need to be able to access your services-config.xml file. Which can be difficult if you are developing against a remote Flex server. Confusion with the launch url in FlexBuilder.
  • By default endpoint urls in the services-config.xml use wildcards to define the host/port of the url "{server.host} and {server.port}". However, the default for FlexBuilder is to launch flex applications with a file://c:\ absolute path, easily corrected but still the default. Now the problem is that if your movie is launched with a file:// path, Flex can't use the {server.host}/{server.port} wildcards (there is no http url to pull the host and port from)
  • But, you can't hardcode the url in services-config.xml either. Otherwise your .swf will be compiled with a url that points back to your development server. And you don't want to recompile the .swf for production because then the .swf you tested is NOT the same .swf as the one you deploy. (you always want to deploy the same code you test). Context-root problems, if you develop with one context-root and deploy to production under a different context-root - Watch out!
  • Because the context-root needs to be hard coded in the services-config.xml or defined as a compiler argument in FlexBuilder too, it is compiled into the swf as a hard coded value. Which means, you need a different .swf for each platform you run one (a testing nightmare).

Alas, there is a solution! (You knew I was going there didn't you). All of this can be defined at runtime without the -services argument and the services-config.xml. Defining this at runtime also has a few advantages.

  • Your context-root can be defined at runtime as a FlashVar and your .cfm or .jsp can easily set that with a simple variable.
  • You can switch URL's as needed, for instance if the movie is loaded under an http:// url, use the wildcards. If it's loaded under a file:// or c:\.. path use a hard coded development url.
  • Different developer enviroments and configurations don't matter, everyone should be able to drop the code, sorry sync from source control, on their machine and run the application.

There are different ways to do this but how I do it is with 2 files; a ConfigModel class and a standard ServiceLocator class.

ConfigModel.as

package model
{
   import mx.core.Application;
   import mx.controls.Alert;
   import mx.utils.ObjectUtil;
   
   /**
    * Used to store Application config settings, and the
    * FlashRemoting channel and endpoint url settings, with this you
    * won't need define a -services compiler argument for the project.
    *
    * @author: Mike Nimer
    **/
   [Bindable(event="configChange")]
   public class ConfigModel
   {
      public static var TIMEZONEOFFSET:Number; //est=4 or 5, depending on DST       
      // debug setting to switch between live and stub data       public static const USE_STUB_DATA:Boolean = false;

      // Flash remoting config issues       public static const CHANNELID:String = "orca-amf";      
      private static const default_context_root:String = "/"; // adjust as needed for your default server.

      /**
       * pull the context-root out of the flash var, if it's defined in your <object/> or <embed/> tags.
       * ex: contextRoot=/flex
       **/      
      private static function get CONTEXT_ROOT():String
      {
         var app:Application = Application.application as Application;
         if( app.parameters.contextRoot != null )
         {
            //Alert.show( ObjectUtil.toString(app.parameters) );             return    app.parameters.contextRoot;
         }
         return ConfigModel.default_context_root;
      }
      
      
      // return the correct endpoint, if this is server from an HTTP request       // return the default localhost:8500 for development, if FlexBuilder launches       // the application locally with an absolute path (file://c:\...)       public static function get AMFENDPOINT():String
      {
         var app:Application = Application.application as Application;
         if( app.url != null && app.url.indexOf("http:") != -1 )
         {
            return "http://{server.name}:{server.port}" + ConfigModel.CONTEXT_ROOT +"/messagebroker/amf";
            // for ColdFusion users             // return "http://{server.name}:{server.port}" + ConfigModel.CONTEXT_ROOT +"/flex2gateway";          }
         else
         {
            return "http://localhost:8500" + ConfigModel.CONTEXT_ROOT + "/messagebroker/amf";
            // for ColdFusion Users             // return "http://localhost:8500" + ConfigModel.CONTEXT_ROOT + "/flex2gateway";          }
      }

   }
}

ServiceLocator.as

package services
{
   import model.ConfigModel;
   import mx.messaging.Channel;
   import mx.messaging.ChannelSet;
   import mx.rpc.remoting.mxml.RemoteObject;
   import mx.rpc.events.ResultEvent;
   import mx.messaging.channels.AMFChannel;
   import mx.rpc.events.FaultEvent;
   import mx.rpc.AbstractService;
   import mx.messaging.config.ServerConfig;
   
   /**
    * Create the RemoteObject tags used by the application service delegates
    * @author: Mike Nimer
    **/
   public class ServiceLocator
   {
      public var service:AbstractService;
      public var amfChannelSet:ChannelSet;
      public static var serviceLocator:ServiceLocator;
      
      public function ServiceLocator()
      {
         var amfChannel:Channel = new AMFChannel(ConfigModel.CHANNELID, ConfigModel.AMFENDPOINT);
         amfChannelSet = new ChannelSet();
         amfChannelSet.addChannel(amfChannel);
      }      
      
      public static function getInstance():ServiceLocator
      {
         if( ServiceLocator.serviceLocator == null )
         {
            ServiceLocator.serviceLocator = new ServiceLocator();
         }
         return ServiceLocator.serviceLocator;
      }
      
      
      /**
       * Individual Services used by the Application.
       **/            
      public function getSomeService():AbstractService
      {
         if( service != null )
         {
            return service;
         }         
         service = new RemoteObject('someDestination');
         service.channelSet = this.amfChannelSet;
         (service as RemoteObject).showBusyCursor = true;
         
         // service.source = "dot.path.to.cfc" // If you are using ColdFusion      
         //service.setCredentials(username, password); // if you need it    return service;
      }
      
   }
}

Set Context-root FlashVar (ColdFusion)

// You'll find this in the default html flex generates, just make the html page a cfm and add this FlashVar.
// note: Use contextRoot=<%=request.getContextPath()%> for JSP pages.
   AC_FL_RunContent(
         "src", "Orca",
         "width", "100%",
         "height", "100%",
         "align", "middle",
         "id", "Orca",
         "quality", "high",
         "bgcolor", "#869ca7",
         "name", "Orca",
         "flashvars",'contextRoot=#getContextRoot()#&historyUrl=history.htm%3F&lconid=' + lc_id + '',
         "allowScriptAccess","sameDomain",
         "type", "application/x-shockwave-flash",
         "pluginspage", "http://www.adobe.com/go/getflashplayer"
   );

CFForm xml forms

Sure it's a slow adoption feature in ColdFusion, but it hasn't been forgotten. And those that know how to use it - love it.

Wim Dewijngaert @ http://cfform.dewijngaert.be has created a number of great DHTML components that work with CFForm (format="xml").

So if you've already discovered the hidden power in xml forms or have been meaning to use them - go take a look and try some of them out.

I knew that people would eventually start posting components/xsl skins for cfform. Does anyone else have any that they would like to post (they aren't hard to make).

For the kids - new favorite charity!

Late last year, to late to tell everyone, I gave to what has become a favorite charity of mine. So this year I'm telling everyone about it.

Childs Play Charity

What makes this one different? They way you donate, instead of sending in a check you go shopping on Amazon. Volunteers from dozens of children's hospitals around the world have worked with Amazon to build wish lists for the kids. This means that not only does 100% of your money go to the kids toys, but, the exact toys you pick out do too. Amazon will then ship your toys directly to the hospital(s).

So head over to childs play and pick a hospital (or 2,3...), then imagine kids who have to spend christmas at the hospital, and start picking out toys you would want to play with if you were stuck in a hospital too.

Merry Christmas!

Motionbox.com launches flex app to manage multi-file uploads

It's not very often that we ("Tapper, Nimer, and Associates") do work that lives outside the firewall, so when we do it's great to be able to share it. This week Motionbox.com launched a new flex 2 multi-file uploader, written by our own Angela Nimer!

This has to be one of the best examples of flex doing what it does best; can you imagine trying to provide this kind of interaction and feedback with old-school html (or dare I say Ajax). You'd be in ActiveX/Applet hell. Instead with the flex components, lots of event listeners, and some css we were able to quickly build a rich interactive experience that does the job while informing the user about what is happening at all times.

If you?re not familiar with Motionbox.com, check it out! Motionbox is a video sharing site, but not any regular video sharing site, Motionbox lets you share whole videos, but, even better you can share just the clips of a video (aka, just the good parts). Plus they have a cool flex video player and filmstrip tool too.

CustomRowColorDataGrid component

In the last 2 projects I've worked on I've needed to change the background row color of items in the datagrid, based on values in the dataProvider.

However the flex DataGrid doesn't allow you to set the row color this way. Turns out in order to do this you need to extend the DataGrid and override the drawRowBackground() method and put your own logic in it. Not fun at all.

So to make it easier for myself, and you, I've abstracted this out in a way that make the new DataGrid re-usable, and I've added it to my growing collection of components that you can download from here.

[Download]

So the syntax to use this new grid is to write a new function, just like the ArrayCollections filterFunction. And the new DataGrid will call this function for every row it renders in the DataGrid, to get the right background row color.

The function signature needs to be this:

f(item:Object, defaultColor:uint):uint

<?xml version="1.0" encoding="utf-8"?>
<mx:Application
   xmlns:mx="http://www.adobe.com/2006/mxml"
   xmlns:nimer="com.mikenimer.components.datagrid.*">

   
   
   <mx:Script>
      <![CDATA[
         import mx.collections.ArrayCollection;
         private function selectTypeColor(item:Object, color:uint):uint
         {
            if( item['type'] == "Warning" )
            {
               return 0xFFFF00;
            }
            else if( item['type'] == "Error" )
            {
               return 0xFF0033;
            }
            return color;
         }
      ]]>
   </mx:Script>

   
   <nimer:CustomRowColorDataGrid
      id="sampleGrid"
      rowColorFunction="selectTypeColor"
      width="100%" height="100%">

      
      <nimer:dataProvider>
         <mx:Array>
            <mx:Object type="Information" message="something good worked"/>
            <mx:Object type="Information" message="something else worked"/>
            <mx:Object type="Information" message="I like flex"/>
            <mx:Object type="Error" message="Opps, something didn't work."/>
            <mx:Object type="Warning" message="flex has a learning curve"/>
            <mx:Object type="Information" message="flex is fun"/>
         </mx:Array>
      </nimer:dataProvider>      
   </nimer:CustomRowColorDataGrid>
   
</mx:Application>

AS3 randRange() function

Recently I needed to generate a random number of items for a unit test in flex. In ColdFusion this is easy, I can use the randRange(x,x) function. However, there is not a randrange() function built into AS3.

So with a little help from google, here is a simple AS3 randRange() you can use.

[Update: Thanks to Till & Keith, here is an updated function]

function randRange(start:Number, end:Number) : Number
{
return Math.floor(start +(Math.random() * (end - start)));
}

More Entries

BlogCFC was created by Raymond Camden. This blog is running version 5.9.001.