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?

Showing item number in ItemRenderer

english mobile

I asked a question several weeks ago on the FlexCoders forum on how to get the item number of an item that had been clicked in a Repeater. None of the answers that I got seemed to help and it wasn't that critical, so I let it drop. In my current project, it is critical, because I have to show that number on the screen.

Luckily, I am using XML. E4X XML, like Authorware icons, is very "self-aware." In Authorware, you can get from any place in the program to any other place using the numeric values implicit in the parent/child relationship. Similarly, an E4X XML node "knows" what its child number is relative to the parent node. So displaying the node number on the screen was as simple as {data.childIndex + 1}.

Some days Flex is really cool :-).

Updated 12-3-08:
I've posted a simple example that shows how to display the line number in a List based control with either an XML or ListCollectionView source.

Order of Events for ItemRenderers

english mobile

I suspect that I'll be blogging a lot about ItemRenderers, because it seems that there's a ton that can go wrong with them and lots of stuff to learn before you can get it right. A good starting point in learning about them is Alex Harui's Blog. I found this source a bit misleading in my current project, because it suggests that you should run your init code in the dataChange event listener function.

The problem I found is that the dataChange event runs before some objects in the component have been instantiated, so trying to change their attributes results in a spectacular explosion. The solution I found is to set a boolean value in the creationComplete listener to indicate whether or not the component was completely drawn, then run the same logic that would have run from the dataChange function. So when the data changes, the dataChange listener will initialize the objects, but on first creation, the creationComplete listener handles it.

I suspect this is not the optimal way to handle this, but it works and doesn't require much rocket science on my part.

Update 7/3/2008: I eventually had a series of conversations about this with Alex, and it seems that the mistake I was making was that I was trying to address objects directly in the dataChange event handler, and, as noted above that doesn't work. But instead of repeating that call in dataChange and creationComplete, what I should have done is to set a boolean flag in dataChange only to indicate that the property (which in this case was a dataProvider) needs to be set on the child object.

I was trying to avoid overriding any of the inbuilt methods, but the engineers intended for developers to override many of the methods when creating itemRenderers. In this case, I needed to override commitProperties and set the dataProvider whenever that flag was true (and then set the flag back to false, of course).

Unhandled Error

english mobile

I am often trying to do sort of off-the-wall things in Flex, because I am slowly building new functionality in Flex that gets plugged into Authorware. When enough of the functionality exists in Flex, we'll rebuild the shell logic to finally port it all to Flex. But for right now I find myself doing things I suspect the Flex team never intended.

For instance, last week I was sending XML in through ExternalInterface that contained XML that was destined to be the htmlText for a TextArea (I have more fun and interesting posts about that to come later). But the upshot is that I was getting "Error #2044: Unhandled IOErrorEvent:. text=Error #2036: Load NeverCompleted." I thought it was a problem with the XML getting through the ExternalInterface or maybe with the parsing or possibly with the component that was displaying the content. I couldn't find anything on this error, so I was pretty much stumped.

As it turns out, the problem was that I'd gotten the path to an image in the HTML slightly wrong, and when that didn't load, I got the error. A secondary issue was that the latest Flex Beta spits out a debug swf by default, so this helpfully shows the error to anyone and everyone unless you go out of your way to put out a production version. I'd forgotten about this new quirk, so this was fairly alarming in a file I'd planned to pass along to my client.

Anyway, we're going for dinner now. Ta.

Undocumented Image Control Properties

english mobile

For over a week, I've been struggling to make an image gallery similar to the one here. The problem I was having is that the images were all different sizes, and when they were displayed on the screen they were jumping all over the screen. Let me go back to the beginning...

It seems that the Image control doesn't scale properly unless you set its size as a percentage of the container size. So, if you leave the size off to let the image size itself, you get a giant image with scrollbars, regardless of whether you've set scaleContent to true or not. So, when you set the image size as a percentage of the container size, the image control probably won't have the same dimensions as the image, which means that the image is "floating" inside the container. By default, the image is supposed to be in the top left of the image control, but my experience is that it can wind up pretty much anywhere in the control.

I scoured the documentation and even asked on FlexCoders, but no one could tell me a fix for this problem. Finally, in desperation, I went back to the example, and found this text nestled in the image tag's properties:

verticalAlign="bottom" horizontalAlign="center"


Grrr... I hope this saves someone else from over a week of fruitless frustration!

Update 7/3/2008: I ultimately learned that if I want to affect any visual property of a component, that I needed to look at both properties and styles. These two "properties" are, in fact, documented--styles.

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.

Application vs. WindowedApplication

english mobile

When I first saw Flex and what it could do, I was really excited. I started my working life as a graphic designer, so I'm always interested in the visual possibilities of a new tool. One of the things I spotted right away is that you can make an AIR application that floats on top of the desktop, with a drop shadow and full alpha transparency.

I trotted off to try to make my first AIR app with these features, and it was like hitting a brick wall. I tried everything the Help suggested, to no avail. Finally, I noticed that in the examples, the base tag was Application and not the WindowedApplication you get as the default when you start an AIR project. If you change the base tag to Application, then everything works as expected.

I find that very puzzling, because the main difference between Application and WindowedApplication is that Application is for a file designed to run in a web page and WindowedApplication is designed for AIR. Correct me if I'm wrong, but it seems to me way more useful to have a transparent window for a desktop application than one that is stuck in a window that is decidedly not transparent, ever. Yes, I know about the whole WMode thing, but it seems to me that its chief use is to annoy the snot out of hapless users who find themselves visiting a page that likes to run its ads over the top of the content. I'd be interested in finding out the real reason behind this odd dichotomy.

Updated September 24, 2008:
To find the real solution to this problem, you had to read my comment, follow the links, and then read the comment on the post it linked to. So I'm going to summarize the solution here.

To make the main application window transparent in AIR, you need to edit the {YourAppName}-app.xml file to change these values in the initialWindow section:
systemChrome (set to "none")
transparent (set to "true")

Then, set the showFlexChrome property in the WindowedApplication tag to "false".

Calling Flex from Authorware

english mobile

So I finally had my datagrid calling my ASP page, which squirted out XML. I embedded my Flex swf and could not for the life of me figure out how to call the functionality from Authorware. I did a lot of Googling and banging my head up against a wall, and here is what I came up with:

CallSprite(@"Flash", #CallString, "CallFunction('<invoke
name=\"myFlexFunction\" returntype=\"void\"><arguments><string>hello
world</string></arguments></invoke>')")


If you're not familiar with Authorware, it has two methods for embedding swf files. One is a sort of proprietary method called the Flash Asset Xtra. It actually contains the Flash player so the user does not need to have the player installed. Problem is, it only goes up to Flash 6. So this Flash Sprite is the other type, the Flash 9 ActiveX control embedded in Authorware. #CallString is a method of the CallSprite function that allows you to get access to all methods of a given sprite, even ones that aren't exposed in the way Authorware recognizes. All of this is a long hand way of saying if you're not using Authorware, you'd probably use the CallFunction function some other way.

However, the important part is the XML string, which the Flex documentation doesn't, well, document. I haven't found anything but examples, but I'll give it a stab from my surmises which have borne out through trial and error so far.

<invoke>-root level tag. It has a name property that tells Flex what to invoke (i.e. the name of your function). Those backslashes you see there in my code are to tell Authorware those are literal quotes that should be passed on through to the function. Also has a returntype property, which, presumably, is the return type you expect. Probably this can be any valid return type a function could have from Flex.
<arguments>-nested within invoke, this is a container for all the arguments your function is expecting. Each argument should, again presumably, be wrapped in a tag that tells Flex what type of argument it is. IMO a cleaner implementation would be <argument type="string>foo</argument> but then I'm just a random spong so I don't control these things.

If there's anything else that you could put in here I haven't found it.

Note that I am really curious as to whether a function that returned a value would return it back to Authorware and what form that would take, but not quite curious enough to try it until I need to.

Flex reorders URL String Parameters

english mobile

So now I'm trying to capture the Flex things I've learned in the last couple of weeks with Flex, and most of them are just a big amorphous blur. One thing I do remember is that my ASP page broke when called from Flex. Turns out that Flex doesn't leave the request parameters in the order you put them in when sending to ASP, even when you hard code the full URL string. No I have no idea either why it would rearrange them, but there you have it.

You may be asking yourself why does it matter? Well, I had some pre-existing code that runs stored queries living in my Access database. The SQL for that looks something like "Exec [myQuery] 'param1', 'param2', 'param3'". The ASP code doesn't know anything about what order those parameters are supposed to be in and how many there are supposed to be. So the order needs to come from somewhere.

When I found this bug, I could well have assumed that any code calling the ASP page would use a specific naming convention, and indeed my existing logic does do that. However, I did not want to be tied to a naming convention forever when it should not be necessary. What I could assume is that the parameters would be put together automatically in a loop, since it makes sense to call this logic from a function (and indeed that is how it is called from within Authorware). That meant that the names would be auto-generated and in ascending order.

So, I wrote a function in ASP to reorder the URL parameters in ascending order by name.

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.