Mike Orth – Booya!

Flex, Actionscript

How to use a DataGrid with no column headers

This is one of those quirky things that is not all that well documented.  I had a client that needed a datagrid but didn’t want the header row.  It sparked the memory of struggling to find how to do this the first time I needed it.  So hopefully this will help end your search for the answer

<mx:DataGrid showHeaders=false/>
No comments

Easily Validating Dynamic Forms (or with just ‘too many’ fields)

Don’t you hate having to specify validation on each individual control in your form? Or how about when project management is continually adding new form fields to a form? “A user should have to retype an email address” or, “we need to add a billing address section.” Well now rather than having to add a new validator source or explictly call validate() for the new control, this code takes care of it all automatically. This works especially great for forms with dynamic fields.

Just add the FormItem to your form, set it to required and you’re set! Simply call

validateForm(form:Form)

passing in any Form object and it will create an array of all the fields inside of the form. Since mostly you’ll be dealing with TextInput controls in your FormItem, that’s what this example uses. See comments in example code for more detailed information on usage.

Click to view demo app (Right click to View Source)
Click to view app (Right click to View Source)

Sample code:

        /**
         * Helper function that returns all the fields for a
         * given form. Pass in requiredOnly = true if you only want
         * the required fields.
         */
        private function getFields(form:Form, requiredOnly:Boolean=false):Array
        {
            var a:Array = [];
            // get every child of the Form
            var formItems:Array = form.getChildren();
            for (var i:int=0; i<formItems.length; i++)
            {
                // make sure it's a FormItem - if you use FormHeading or have
                // items that are not wrapped in a FormItem tag then ignore those
                if (formItems[i] is FormItem)
                {
                    var formItem:FormItem = formItems[i];
                    // add the formItem's child to the array.
                    // if you only need required items, set requiredOnly = true
                    // Note: this assumes you only have one form field per FormItem
                    //       You could easily add additional logic here for more
                    if (formItem.required || !requiredOnly)
                        a.push(formItem.getChildAt(0));
                }
            }
            return a;
        }
       
        /**
         * Validates all fields in a given form.
         */
        private function validateForm(form:Form):Boolean
        {
            // reset the flag
            var _isValid:Boolean = true;
           
            // populate the fields - if your fields aren't dynamic put this in creationComplete
            var fields:Array = getFields(form, true);
           
            for each(var source:UIComponent in fields)
            {
                // create a simple string validator
                var validator:StringValidator = new StringValidator();
                validator.minLength = 2;
                validator.source = source;
                validator.property = "text";
                var result:ValidationResultEvent;
                // typical validation, but check to this checks for any different
                // types of UIComponent here
                if (source is TextInput)
                    result = validator.validate(TextInput(source).text)
                else if (source is TextArea)
                    result = validator.validate(TextArea(source).text)
                // if the source is valid, then mark the form as valid
                _isValid = (result.type == ValidationResultEvent.VALID) && _isValid;
            }
           
            return _isValid;
        }

4 comments

TitleWindow Subclass for Easily Handling Popups

Typically if you choose to use a TitleWindow, odds are you’re going to add it with the PopupManager and use the Close button. So rather than having to always set that up and add listeners for the CloseEvent, use this extended class PopupBase. It’s used the same as TitleWindow, declared in actionscript

var popup:PopupBase = new PopupBase();

or mxml,

<containers:PopupBase />

but by default it:

  • sets showCloseButton=true
  • sets a listener for CloseEvent
  • removes the popup when Close button is pressed

You can override the onClose handler to add different functionality.

package containers
{
    import mx.containers.TitleWindow;
    import mx.events.CloseEvent;
    import mx.managers.PopUpManager;
   
    public class PopupBase extends TitleWindow
    {
        public function PopupBase()
        {
            showCloseButton = true;
            addEventListener(CloseEvent.CLOSE, onClose);
        }
       
        protected function onClose(event:CloseEvent):void
        {
            PopUpManager.removePopUp(this);
        }
    }
}
No comments

MediaCoreLib for Actionscript 3 – Play Rich-Media Content Easily

MediaCoreLib – Here’s an easy way to play rich media content (audio, video) inside Flash or Flex and manage it all in one place.

The new MediaCoreLib alpha release includes an extensive PlaylistManager as well as a merging of my FadingSound component to allow for crossfading between tracks. For a more info check out the Google code repository.

Features:

  • Play
  • Pause
  • Stop
  • Prev / Next
  • Rewind / Fast-forward
  • Repeat
  • Preloading and Caching
  • Fade In / Out
  • Crossfade
  • More…

Check out the testing panel to try it out yourself:
BASIC PANEL
ADVANCED PANEL

This is an effort bewtween Justin Opitz and myself and we are continuing to add features. Look for a Beta release soon!

2 comments

Dynamically change asset color using ColorTransform

Usually, changing colors inside your application is easy. You can set just about everything from textColor to backgroundColor, inline (backgroundColor = “#FFFFFF”), in a stylesheet (background-color: #FFFFFF) or using the setStyle method( uic.setStyle(”borderColor”, “green”) ). But what if you are trying to change the color of an embedded asset?

Say your designer gives you an asset, like a black funky shaped blob for a logo or icon. Then, later on, your company changes the icons to white. Why wait around for 2 weeks while your designer finds time to change the graphic when you could change in the code? Or perhaps a better example would be if your application requires applying different stylesheets at run-time for users to pick custom colors and layouts.

This is where using transforms comes in handy. The ColorTransform class lets you do some cool things to set RGB and alpha offsets or multipliers as well as set the color explicitly, which is what this example does. All you do is create a new instance, set the color value and assign the instance.

        var ct:ColorTransform = new ColorTransform();
        ct.color = event.color;
        img_funky.transform.colorTransform = ct;

This is not just limited to embedded assets. You can use transforms on almost any DisplayObject.

Example Application – Click Here

No comments

Object Translator – Normalizing Objects

This is an extension of a great blog from Justin Opitz on normalizing value objects.  We were discussing the a best way to take objects that are somewhat similar in form and conform them to an interface. Normalizing objects allows you perform logic on data that is generic and more makes your code more reusable.

So imagine we have several different object types coming in, like Artist, Album, & Track objects with properties that are similar, yet unique, including “artistName”, “albumName”, “trackName”, among others. We want to put this into a VO with just “name”.

Below is a modified version of the translator. If you have several different VOs that implement an interface then you may want the ability to assign them as needed. Since it could be any one of the VOs being, we’ll pass it in as a wild card

vo:*"

and then return the newly assigned object. Also, if the current propety doesn’t match a pattern we’re looking for, then it assigns it as-is.

So here’s what the function will look like:

public static function TranslateObject ( targetObject:Object, vo:* ):*
{

for (var s:String in vo)
{
//we are going to check each prop name to see if there is a match for our
//targetObject’s known properties
//obvious ly this list will grow the more props you have to normalize
//however it only grows once regardless of the number of non-normalized VOs

if (s.toLowerCase().indexOf(’name’) != -1)
targetObject.name = String(vo[s]);

else if (s.toLowerCase().indexOf(’id’) != -1)
targetObject.id = int(vo[s]);

else if (s.lowerCase().indexOf(’genres’) != -1)
targetObject.genres = vo[s] as Array;

else
targetObject[s] = vo[s];

return vo;
}
}

1 comment

Tiny Alarm

If you’re like me, and always get really wrapped up in your work, then you should check out Tiny Alarm for Mac. It’s a great little app that lives in your menu bar and is a snap to use. Just click the alarm clock to set the time and it gives you a few short beeps (or other sounds) when the time comes and subtly flashes. You can ignore it and it’ll beep again every minute. Clicking it again will turn it off or snooze depending on preference.I use it to remind myself to get up and stretch or to move on to working on something else. I just got the new version which has cool features to gives you notes on why you decided to set the alarm in the first place. Now if it only made me get up instead of ignoring it or hitting snooze 8 times….More info on Tiny Alarm here

No comments

Number Class, IEEE 754 Math Inequality

The “Number” data type in Flex is used for floating-point numbers (i.e. decimals like 42.11). It is usually the default type when using numerical values, even though Flash Player handles int and uint more effeciently. The Number class uses the IEEE 754 standard which gives you values up to 53 bits (highest of which is approx. 1.79e+308).

When doing calculations involving Numbers, calculations are done using binary addition. This can really throw you off course in a few rare instances if you’re not careful! Take the following example:

   var a:Number = .1;
   var b:Number = a * 3;     // .1 + .1 +.1

b = .3, right? Right.. only, not. The value comes out to 0.30000000000000004 instead. Ok, not too far off, but imagine making several calculations on the result and you can start to sway off course. The following example is a watered-down version of what I encountered lately. I knew about this type of discrepancy, but it took me a couple of days to figure out where things were going wrong because I didn’t assume that something was failing at such a base level; you typically expect things like subtraction to work correctly.

   var a:Number = 1;
   var b:Number = .2;
   while (a > 0){
      a = a - b
      trace(a);
   }
   ...
   OUTPUT:
   .8
   0.6000000000000001
   0.4000000000000001
   0.2000000000000007
   5.551115123125783e-17
   -0.19999999999999996

Whoa. Things start getting funky (btw, in case you’re not familiar with the notation, that second to last one is 5 with 17 decimal places, “.00000000000000005″). Why the discrepancy? Again, it has to do with converting the numbers to binary and evalutating them. You can read more on the IEEE 754 standard here. This is typically not something you will have to deal with, but when you do encounter it, you can spin your wheels for a while.

Try it for yourself here.
Demo application that adds/subtracts and includes some default cases.

No comments

Crossfade audio in Flex – FadingSound prototype

I’ve been fielding questions about fading audio in Flex lately and decided to package up my FadingSound. I worked on this about a year ago and then threw it on the shelf, so I’ve begun cleaning it up and wanted to release a prototype as a proof of concept. This class creates the Sound and SoundChannel objects for you and fades in and out each song in a playlist. It’s so simple, all you have to do is create an instance say:

myFadingSound.play(playlist);

where “playlist” is an ArrayCollection of URLs. If you just want to have 1 song fade in or out, only put 1 URL in the array. Optional params specify the length of fades and the duration of the songs (if you want to scan through 10 second clips for example). See it in action here.

Fading 1 song in was the easy part – the hurlde was to have 2 channels playing at the same time and control their fades to give the illusion of concurrecny. There are still some bugs in it with buffering songs and fading out at the right time with dynamic tracks which is why the example only plays short clips rather than full songs. I’m in the process of cleaning that up and will update things when I get time. Also I’m going to have an mp3 player that utilizes this where you can create XML playlists to feed it. Feel free to drop me line with features you’d like or any comments on the FadingSound.

Application demoing the Prototype

4 comments

Firefox Popup Blocker – Don’t get caught!

Don’t get caught by Firefox’s popup blocker! Have you ever had some windows blocked and some not? Here’s a way to help ensure that your navigateToURL works in FF (even though having a popup is typically not a good idea in the first place and should be used sparingly).

Firefox tries to help you out and block malicious popups. This has to do with opening a new window without a direct user-interaction (e.g. opening a popup on page load rather than opening a window when a user specifically clicks a button).

I worked on a project where I had to open a new window from within a Flex app. When the user clicked a button, it did some processing behind the scenes based on their input fields, assembled a query string, then made the request to open a new window. Sometimes it worked, sometimes it didn’t! It was a really hard issue to nail down, but after a lot of testing I finally concluded that it had to do with the amount of time taken before the request was sent out.

After you initiate a click event, there’s a set amount of time the browser has to respond to it. If a new window is opened within that time limit, then you can get past the popup blocker because this is an accepted behaviour. Otherwise, it assumes that the request is not potentially not valid. Firefox (and most browsers) blocks this type of action because of malicous applications that could open several windows at will without permission.

Depending on your machine and what you has running at the time, the amount of code you can execute before you choke is variable. I created a quick demo here that illustrates this. If your popup blocker is enabled, one button will open a blank page, the other should get blocked. Right-click to view source. Here’s a snippet from it:

            private function onButtonClick(event:Event):void
            {
                if (event.target.id == "success_btn")
                {
                    popupSuccess();
                }
                else
                {
                    popupFail();
                }
            }

            private function popupSuccess():void
            {
                openNewWindow();
            }
           
            private function popupFail():void
            {
                // do some sort of heavy processing before making the request
                for (var i:int=0; i < 1000; i++)
                {
                    var o:Object = new Object();
                    var num:Number = Math.log(Math.PI);
                    o.num = num;
                }

                openNewWindow();
            }
           
            private function openNewWindow():void
            {
                navigateToURL( new URLRequest(URL), '_blank');
            }

Click here to view the app

5 comments

« Previous PageNext Page »

Mexico

Google Tracking Code