Embed a text/txt file in a Flex/AS3 application

This is actually pretty easy, but it’s not something widely known. Here’s the code:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
            layout="absolute"
            creationComplete="trace(text);">
   <mx:Script>
      <![CDATA[
         [Embed( source="myTextFile.txt", mimeType="application/octet-stream" )]
         public var MyText:Class
         public var text:String=new MyText().toString();
      ]]>
   </mx:Script>
</mx:Application>

So what is this doing?
The embed tag works to keep the file in your swf. It then binds it to the Class defined on the next line. Since it’s an unrecognized file format (Flex supports swf, mp3, jpg, gif, png), Flex wouldn’t know what to do with it, so we specify a mimeType — a description of how to handle this file.
Then, we create a new variable and set its contents to a new instance of the Class, then convert it to a string.
Finally, I’ve set the Application parameter creationComplete to perform a trace of the text variable’s contents. If all is correct, you should see a trace with the txt file’s contents.
EmbedTXTTest

Helpful JSFL Scripts for Indexing the Flash IDE Stage

Get all of the layers in a timeline

By using JSFL, you can use this code to get a list of all of the layers in a timeline. This is returned as an array of named objects whose data is accessible like this:

var layers = getLayers(fl.getDocumentDOM().getTimeline());
layers[0].name

This will return the first layer’s name.

var getLayers = function(timeline){
   var layers = [];
   for(var l in timeline.layers){
      layers.push({
         name:timeline.layers[l].name,
         layer:timeline.layers[l],
         index:l
      });
   }
   return layers;
};

Get all of the keyframes in a layer

By using JSFL, you can use this code to get a list of all of the Keyframes on a layer. This is returned as an array of named objects whose data is accessible like this:

var keyframes = getKeyframes(fl.getDocumentDOM().getTimeline().layers[0]);
keyframes[0].index;

This will return the first keyframe’s index, allowing you to reference it later using layer.frames[index].

var getKeyframes = function(layer){
   var keyframes = [];
   for(var f in layer.frames){
      if (f==layer.frames[f].startFrame){
         keyframes.push({
            frame:layer.frames[f],
            index:f
         });
      }
   }
   return keyframes;
};

Get all of the instances in a keyframe

By using JSFL, you can use this code to get a list of all of the instances on a keyframe. This is returned as an array of named objects whose data is accessible like this:

var instances = getInstances(fl.getDocumentDOM().getTimeline().layers[0].frames[0]);
instances[0].index;

This will return the first instance’s index, allowing you to reference it later using frame.instances[index].

var getInstances = function(keyframe){
   var instances = [];
   for(var e in keyframe.elements){
      if(keyframe.elements[e].elementType == 'instance'){
         if(keyframe.elements[e].libraryItem.itemType != 'compiled clip'){
            instances.push({
               instance:keyframe.elements[e], 
               index:e
            });
         }
      }
   }
   return instances;
};

JSFL and compiled clips

I’ve run into a number of issues trying to reconcile JSFL and compiled clips. Some of the features of a library object are unavailable when inspecting a compiled clip, leading to the wonderful JavaScript Errors we’ve come to love.

The particular oddity I’ve been wrestling with is that CompiledClipInstance objects don’t have a timeline, so if I try and walk the display list, digging into items as I find them, when I hit one of these, the reference to instance.timeline throws an error. The only solution is to exclude these kinds of items from your search.