Showing posts with label flex. Show all posts
Showing posts with label flex. Show all posts

Deja vu all over again

english mobile

When I started this blog in 2007, I had been developing in a technology called Authorware that Adobe was in the process of killing off. So I decided to concentrate on teaching myself Flex, sharing what I was learning with others who were also making that transition.

I still work in Actionscript a lot, primarily in Flash, but unfortunately I've had to come to the decision that it's not the best use of my time to blog about some of the neat things I'm still doing.

It's not fair to say I'm learning JavaScript, since I've been doing JavaScript in some form for over ten years, but I am learning about the JavaScript ecosystem as I find it in 2014, particularly surrounding AngularJS. I'm shifting focus to once again ramp up in tools that are relevant instead of ones that are becoming less relevant. In the process, hopefully I can help others who are making a similar transition or just who want to learn about the parts of the process that I delve into. I like to think that I'm willing to write about things that others may not feel are glamorous enough to devote time to but that can be incredibly helpful if you're looking for just that information.

I have decided to keep the title of the blog the same. In part this is because I have some loyal readers who have been with me the whole way. In part this is because I think that the AngularJS world will realize in time that the particular experience that former Actionscript developers, especially Flex developers, bring to the table means that we're very well-suited to do things the "Angular way." I hope you enjoy the new direction.

ActionScript, E4X, and White Space

english mobile

I've been reading XML into ActionScript 3 for many years, and I still haven't solved all the issues with it. Given that my searches for solutions to these issues turn up so little, I decided to share the solutions I have found, especially when it comes to white space.

I think at least part of the reason that these problems are so hard to solve is that the XML documentation for many of the properties and methods we need to use is frustratingly circular. So let me start by laying out what some of these do in practice.

ignoreWhiteSpace

I think ignoreWhiteSpace is the property we first try to use to correct some of the issues with E4X. This property will, in fact, fix issues that are caused by having "extra" children that you weren't expecting to be parsing when you use normal formatting, like new lines and tabs, in your XML. However, it then causes other white spaces that might have been pretty important to disappear.

An alternative to using ignoreWhiteSpace is to use xmlVar.elements() instead of xmlVar.children(). This works relatively well unless you need to access something that's not an element, like a comment, or you need to pass the XML to Adobe code (like new DataProvider()) that for some reason is not equipped to handle the vagaries of their own E4X implementation.

prettyPrinting

We're all familiar with the problem where the default XML parsing adds even more formatting than we included in the original XML file, so that

<root>
 <p>The quick brown fox jumped over the
 <b>lazy</b> dog.</p>
</root>
becomes
<root>
 <p>The quick brown fox jumped over the 
  <b>lazy</b> 
 dog.</p>
</root>

I'm sure there are some versions of Flash where setting prettyPrinting to false fixes this problem, but in the version of the Flash player we target, setting this property has no effect. The good news is that TextField, the Flash Label component, and the Flex MX Label component support the condenseWhite property, which gets rid of this issue for text you want to display. I guess if you're using a spark label, the skin will need to use something that supports condenseWhite if you need this.

Wrap in CDATA

One of the reasons XML parsing is so thorny is that we're using the XML to store external content, often HTML-formatted. CDATA does work to preserve HTML formatting, but it has its own issues. One issue is that there's no real documentation about how to get the text out of CDATA.

Funny story--I was once on a Flex project where it turned out I needed to wrap the entire XML package I was building in CDATA. Try though I might, I couldn't find anything that told me how to get at the "stuff" inside the CDATA. With deadline fast approaching, I "hacked" it by giving the text to a Spark label (which did know how to do this), then reading the text out again and casting it to XML.

Some months later, I ultimately discovered that String(myNode) will retrieve the contents of a node, whether its contents are wrapped in CDATA or not. Unless the contents are not wrapped in CDATA but contain HTML formatting anyway. This is something that is quite likely to happen on my team, as the people who produce the XML see no reason they shoulld start wrapping everything in CDATA just because we're using ActionScript 3 now.

In addition, even when things are wrapped in CDATA when they should be, you have to dump your text in one line into CDATA because it faithfully reproduces all those \n's and \t's, and you wind up with a bunch of junk nodes if you have to cast the contents back to XML. This results in XML that isn't readable, and readability is one reason to use XML in the first place.

hasComplexContent

So, if you're getting XML and you know that sometimes certain nodes will contain HTML and sometimes that HTML will be wrapped in CDATA and sometimes it won't, what do you do? One thing you can do is create a function that checks for hasComplexContent and calls toString() if it returns false and children().toXMLString() if it returns true.

This works well, but one issue with it is you have to have access to this function wherever you're parsing XML. And since you can't really extend the XML Class, due to its dependence on static methods and properties, that means you either need to use a static method yourself (not my favorite thing) or you need to violate DRY, unless your application lends itself to only parsing XML nodes in exactly one place.

normalize()

This is probably my favorite method, because it gets rid of all the weird child nodes that contain "\n\t\t". This means that I can now parse formatted XML and not have to allow for weird extra junk in there. More importantly, I can pass that XML to "dumber" code, such as the Flash DataProvider constructor, and it works. It also does not take out the spaces around inline HTML tags, so you can normalize() the XML to make for easy parsing that you should get from ignoreWhiteSpace (but don't, due to the removed spaces), then you can call String(myXMLNode) on the node whether it has complex content or not, and it will work in a TextField with condenseWhite set to true. FTW!

Resources for Learning Flex

english mobile

I started this blog to document the hurdles I was finding as I was learning Flex 3. In the year since I started blogging on Flex, this task has become much easier. I wanted to take a minute to talk about two things that I've noticed that are real improvements. First, the Start Page appears to update itself occasionally.

I've posted before that I had problems learning to use the debugger due to lack of resources that explain its basic functionality. A few weeks ago, I cranked up the Start Page for some other reason and noticed it had scroll bars. I scrolled down, and lo and behold! there was a link to a video tutorial on the debugger!

The second, I noticed just today when I was looking at the web version of the Flex Builder forums (I usually use NNTP). I noticed there's a forum for Flex in a Week, and since I'm nosey I opened it up and discovered a link to the Flex in a Week training course. I haven't had a chance to look at all the resources, but the topics look like they should be useful to the new learner of Flex. Thanks to the folks at Adobe for being proactive and helping new users over the learning curve hump!

Using a CSS TypeSelector with an itemRenderer

english mobile

Today, I had more fun with item renderers. I had a component I was working on to try to prototype some new functionality, and I had set up styles for it in the <mx:styles> declaration of the Application tag. If I put my component in a container in the main Application, the style came through fine. If I used it as an itemRenderer of a List based class, only the text styles worked.

It seems that when you use a component this way, Flex will assign ListBaseContentHolder as the style name instead of the class name, but for some reason this only negates things like backround colors—text declarations come through just fine. This interesting feature isn't documented anywhere, so it took me a whole day to figure out the fix, which is so simple I wanted to pound my head against the wall till I couldn't see straight.

override protected function commitProperties():void{
this.styleName = this.className;
}

Hope this saves someone some time!

Another good itemRenderer Resource

english mobile

The longer I use Flex, the more firmly I believe that the key to understanding it is the component life cycle. Specifically, the life cycle as it applies to item renderers. Today on Flex Coders, Douglas Knudsen posted a link to this great presentation on the component life cycle by Eli Greenspan. I can't for the life of me figure out how to bookmark to a pdf, but if I post a link here, I'll be able to find it forever :-).

Great ItemRenderer Resource

english mobile

I really struggle with itemRenderers--what goes where to make what you want to occur happen when you want it to. So I've been talking to various people and reading, reading, reading trying to make sense of it all. From the posts on the yahoo FlexCoders group, it seems like I'm not the only one experiencing confusion.

I think the biggest problem is that there don't seem to be many "from the ground up" resources on this subject. But that doesn't mean there aren't any. In addition to the Flex help and LiveDocs, which, let's face it, confuse us as much as inform us, there are several blogs that tackle this subject. Today I found Peter Ent's blog, which contains a five part series just on itemRenderers. Thanks, Peter!

Working with Dates in AS3

english mobile

The Date examples that come with Flex (and, presumably, Flash) are all very well and good, but to me they don't seem to be very...practical. And it doesn't help that the documentation doesn't provide any clues about how to do simple things like, oh, figuring out how many days there are in a month. There's probably very good code for these things in opensource projects like the Flex scheduler, but I think you have to know where to dig.

So I played around with the Date object, and I discovered that you can use numbers outside the integers 1-31 in the date parameter (new Date(year, month, date)) and get some interesting results. Such as if you use 0, you get the last day of the previous month. As you might expect, negative numbers will go further back into the previous month. I suspect numbers higher than the last day of the month you're dealing with will continue into the next month, though I haven't tried it.

What I was trying to do was create an ArrayCollection that could be used as a dataprovider for a TileList and then that TileList could display a calendar page just like what you see when you look at the calendar on your wall...i.e. the first few days might be in the previous month and the last few days might be in the next month, because only February ever has a shot at fitting exactly in a grid that is seven days wide. I figured that I'd share my class, since I'm probably not the first or last person to ever want to do this. Note that it's not finished...you'll need to add the last few days when the end of the month doesn't fall on Saturday, but that's not rocket science.



package com.magnoliamultimedia.vo
{
import mx.collections.ArrayCollection;
public class DisplayMonth
{
private var _year:int;
private var _month:int;
private var _startIndex:int;
private var _dateColl:ArrayCollection;
public function DisplayMonth(monthNumber:int, yearNumber:int)
{
_month=monthNumber;
_year=yearNumber;
var tmpArray:Array=new Array();
var firstDay:Date=new Date(yearNumber, monthNumber);
var lastDay:Date=new Date(yearNumber, monthNumber +1, 0);
var lastDayNum:int = lastDay.date;
_startIndex = firstDay.day;
var tempDay:Date;
var i:int;
//fill blank days before beginning of month
for (i=0; i<_startindex; i++)
tempday = new Date(yearNumber, monthNumber);
tempday.date -= 6-i;
tmpArray.push(tempday);
}
//fill in the rest of the dates here...
}
}
}



Sorry about the crap formatting...I haven't figured out the spiffy scrolling thing some other bloggers manage.

Updated 5/28/10. I noticed that part of the code had been "eaten" by Blogger. I replaced the relevant code, but may not have put back everything that was once there. For a better example of how to do this, look at my GroupingCollection example.

Is the HorizontalList faster than an HBox with a Repeater?

english mobile

The Help files that come with Flex Builder claim that the HorizontalList control can have better performance than a HBox with a repeater:

"...performance of a HorizontalList control can be better than the combination of an HBox container and a Repeater object because the HorizontalList control only instantiates the objects that fit in its display area."

The truth is, this statement is false. The HorizontalList always instantiates one more control than is drawn in the display area. This extra component is created simply for measurement purposes and is kept in memory in case extra measurements need to be done. That's highly ironic, as I'll get to in a moment.

In a situation where the number of items does not exceed the area available, the HBox with a repeater component will instantiate exactly the number of renderers as items in your dataprovider, whereas the HorizontalList will instantiate one more. If your itemRenderers are heavy (for instance, if they themselves have a component that takes an itemRenderer), this difference can be significant. Additionally, Repeaters do offer the ability to recycle their renderers, which offsets most of the performance advantage you might get from a HorizontalList.

The second problem with the way the HorizontalList "does business" is more significant. If you have to use callLater to do anything that affects the size of the itemRenderers, the HorizontalList has already measured the component before the call that changes the size, and so the space it allocates to the renderer will not be the actual size of the renderer. And there doesn't appear to be any way to dispatch any events from the renderer or set any variables or call any methods that will convince the HorizontalList to use that extra, useless itemRenderer that is hanging around at the new and improved size to update the size.

Possibly you could subclass HorizontalList to make this work correctly, but why would you, since the HBox with an ItemRenderer just works?

Updated May 19: Today, I discovered that the HorizontalList doesn't always draw this extra renderer. If you specify a rowHeight, this step will be skipped.

Updated September 11, 2008: I think if I'd overridden measure() in my itemRenderer to explicitly report the size after the dataProvider was set in commitProperties, I could have gotten a HorizontalList to work. I later had a similar problem with a regular List, and overriding measure() fixed it.

eLearning Guild Online Forum on Flex

english mobile

The eLearning Guild does online forums from time to time that are like conferences that you attend from the comfort of your home or office. I am very excited that my first conference presentation on Flex will be at their online forum Selecting, Combining, and Using Authoring Tools. I will be presenting on strategies for migrating from Authorware to Flex.

Hope to see you there!

Easy when you know how

english mobile

I think I spent a couple of hours yesterday scouring the Flex docs to figure out how to make a tab on a TabNavigator disabled. And it seems like I'm not the only one. After messing with it for a while, I decided to set the enabled property on the child form to false. Which worked.

I went back to the docs and discovered that it had been there all the time:

If you disable a child of a TabNavigator container by setting its enabled property to false, you also disable the associated tab.


Weird, because I know I searched the TabNavigator help page for the word "disable" like a million times.

Problems with HTML within XML

english mobile

Around a month ago, I promised more fun and exciting posts about passing XML through ExternalInterface from Authorware to be used within Flex. The specific task I was trying to accomplish is taking a series of xml nodes and displaying their contents on screen using a repeater control. The contents could be images, text, or swfs.

The problem I had was with the text. It seems that Flex is very persnickety about its XML formatting, so each XML node must be indented and on a new line. This is fine for ordinary XML, since who cares how it looks to Flex, but when you have line breaks and tabs added around your <b > tags, that is a problem!

The irritating thing is that the problem occurs not once, but twice! The first time is when the XML gets passed through ExternalInterface. I did eventually find a way to defeat that one, but since it also happens again when you pass the string to the XML() object to make the data source for the repeater, that didn't help much. Flex essentially ignores CDATA tags put into the XML nodes and formats the data anyway, so that didn't help either.

What I eventually wound up doing is replacing the "<" characters in embedded html with "^", then replacing that in the final step before rendering. I'm thinking now that I probably also could have gone with a separate text file for each bit of HTML text and told the Flex file to read that in and display it. However, at the time I didn't know how to get a non-air Flex file to read directly from the hard drive, so it didn't occur to me.

Updated September 18, 2008:
I think this was caused by the prettyPrinting and prettyIndent settings on the global XML object itself. I think that if I'd set prettyPrinting to false, I could have avoided the hassle. One day I may even revisit that component...I'll let you know how it turns out.

More on ExternalInterface

english mobile

One of my first posts was about using ExternalInterface to call Flex from Authorware, and about how there is virtually no documentation on how to use this API to run functions inside a Flex swf from an ActiveX control embedded in an executable (in this case, Authorware). I've found some more anomalies which are worth jotting down for my own future reference and the reference of anyone who's bored enough to read my blog.

It seems that the <arguments> parameter does not recognize the full spectrum of data types supported by Flex. So far, I have found that if your Flex function expects an int or a Boolean argument, these values must be wrapped in a <number> tag. I guess Flex knows ExternalInterface can't handle these data types, and converts them from generic numbers into the appropriate data type by pfm in the background.

Ain't life grand?

Dispatching Events

english mobile

I'm thinking I'm probably extra stupid, but I kind of got the impression from the Event handling docs that if you wanted to send out your own events, you had to have your own events class. It seemed to me there was something magical in the constants defining event names in your events class that somehow made the events so named "your" events. It turns out that if you want to dispatch an event "this is an event" then it really is as simple as

dispatchEvent(new Event("this is an event"));

Then all you have to do is add an event listener for "this is an event". There's no more magic to it than that. The event just needs to be called the same thing on both sides, and that is what the constants make sure of. But they're not required.

Now, if you want to pass more information in an event, such as whether a click on a Multiple Choice Question is right or wrong, then you'd need your own Event class. But for simply broadcasting an event you know is yours, you just send out an event as above. Duh.

I figure most people reading this are not as "challenged" as I am, but hopefully this helps someone anyway.

Update 7/3/2008: When a component is dispatching events, it should also "announce" what events are available on it with an Event metadata tag, such as [Event (name="thisIsAnEvent" type="flash.events.Event")]. This allows you to use it in MXML without a compiler error. I honestly don't know whether multi-word event name, as stated in my original example, would cause an error or not.

Modules for eLearning

english mobile

I've written before about how difficult I've found it to figure out how to use Modules for eLearning style structures within Flex. It seems to me I may have hit upon an approach that works. The new documentation on Modules has an example that shows creating an Interface so that you have a known "contract" between the Module and the parent container. The example shows how to pass information into the Module, but didn't seem at all concerned about passing information back out. So I put my thinking cap on, and went to researching.

The first thing that seemed obvious to me was that you'd need to have some sort of event that would be propogated from the Module to tell the parent container that something had happened. So, I went and looked at the documentation about how to handle events. And I really, really tried to figure out a way to do it just with the implementation of the functions from the Interface. But functions in an Interface are kinda tricky. They're fairly plain Jane (in the Interface itself they're just stubs, with no implementation) and are really designed to be called from whatever is Interfacing with the Interfacee (as it were). I couldn't figure out a way to use them to push information out with them.

Instead, what I did was create a function that will return the name of the event that the Module expects to send out to the container. This allows the container to attach an event listener for that event without having to know up front what it will be called. So, for instance you could have an ElearningEvent.MENU_CLICK or an ElearningEvent.MC_SELECTION.

Where did the names for these events come from? Well, let me back up. I wrote a custom event class called ElearningEvent, specifically for handling events from my own eLearning Modules. I imported this class both into the Module file and into the Container file. It had public static constants in it that defined the ELearningEvent types. Ultimately, I plan to extend it so that more custom events can convey more information, such as whether a question was right or wrong (right now, it just publishes a value and ID).

So now that I've rambled all over the map, let me distill the process into a nutshell:

  1. First, I wrote the Interface .as file (IELearning.as), which essentially said "these are the functions you can use to access me, and here are the arguments I expect and what I will return."
  2. Next, I wrote the ELearningEvent class, which defined my custom event, including constants covering the event types included in it. I made it Inspectable so that Flex Builder would help with the typing.
  3. I added the implements element to the Module to specify that it implemented IELearning. I added the implementation of the Interface functions, including the one that published the specific event for this Module (in this case, a MENU_CLICK). And I added logic to listen for a click on the menu and generate my ElearningEvent.
  4. In the containing Application, I added logic similar to the logic in the Module docs to retrieve a reference to the Module child when it loaded. The difference is, I also asked for the name of the event that the Module child was planning to generate, and attached an event listener to the child.

The Module file was already inserted into the Application file, and I'd already worked out its base functionality before I started the process above.

I'm still not sure why an Interface is the suggested solution for this. I would think that maybe just writing an ordinary class, might be better, or even a fake abstract class.

AS3 Basics

english mobile

I've been struggling a lot with the Flex documentation (can ya tell?), and a lot of it, I think, is because the people who write docs know the whole thing inside and out. So they don't realize that before they go off all half cocked telling you how to write the code in a package, they should probably take a moment or two to tell you where to put the package, what to call the package so it will work, and how you refer to it from within your code and MXML. That's just an example of my "issues" with the docs, but a very pertinent one.

I'd pretty much worked all those things out with a little creative "reading between the lines" and reading the same articles on the Developer's Center over and over. However, I finally stumbled across the free ActionScript 3 Cookbook Excerpts from O'Reilly, and let me tell you, it has really codified a lot of stuff I thought I'd figured out, as well as correcting some misconceptions as a result of the roundabout route I took to the figurin'. I have only read up to Chapter 2, which, incidentally, explains all that stuff about packaging. I think I'll be ordering this book tomorrow! Wonder if it comes in MS Reader format...?

ELearning Approaches

english mobile

I'm trying to get my head around the best way to use Flex for eLearning, and I'm truly having to start with the basics. The average computer based course has an interface which may show some front matter, usually shows a menu, and then will show the content. After that, it may show a summary or have a quiz. But all of these things "live" in the same interface. Sounds simple, right?

In Authorware, it pretty much is. But in Flex it's another story. Flex has the ability to do this kind of thing with several different techniques. For instance, you can use a ViewStack, View States, or Modules. All seem to have their own advantages and disadvantages, but it feels like they're all totally different ways of doing business. Ah, what to choose, what to choose?

My first experiments have been with Modules. I find myself really frustrated (again), because it seems like it's hard to find information at all, and then when you do find it, it may or may not tell you about all the "gotchas" that seem to lurk under every rock in Flex. But I've found a decent reference for Modules and several of the other Flex features you might find useful. The links on the right seem to point to chapters in the upcoming Flex Builder 3 manual.

Introduction

english mobile

Hello, my name is Amy and I'm an Authorware-holic. The thing is, Adobe has been deafeningly silent on the future of Authorware, so I'm checking out other tools that can make a web application and a desktop application from the same source code. I have spent the last couple of weeks trying to learn Flex, and honestly I find it quite frustrating.

The Flex documentation, like the documentation of many programs, makes (nearly) perfect sense if you already know what it is talking about. However, when you are trying to learn a software program, you do not already know what it is talking about, so you spend a lot of time puzzling out what the Flex definition of is is.

So, I am starting this blog of my experiences as a Flex newbie trying to get a handle on this beastie. Hope it helps someone.