Nested elements
  • friedfried May 2012
    Hi there,
    I have been messing around with JSFL and xJSFL for about a week now. Going through the documentation and finding my way around. The reason for doing so is basically to streamline my workflow. The current project I'm working on requires me to open files, optimise bitmaps, create movieclips from elements and add scripts.
    The files are exported from Indesign as XFl files (CS4). Here is the code I have so far, some are snippets found on the net and mostly vanilla JSFL.
    var files = [];
    var assetPath = "file:////Users/.../"
    var pathToFLA = "file:////Users/.../";
    //TODO - investigate xjsfl opening XFL files? Seems to not work correctly.
    var folder = new Folder(assetPath).each(
    var doc = fl.openDocument("file:///" + files[0].path)
    var mc = $("*").select();
    function checkNames(item)
    	//sets compression type of each bitmap in the library
    	item.compressionType = 'photo';
    function optimiseRaster()
    	//creates an item collection array of the bmp's in the library
    	var collection = $$(":bitmap");
    	//save the file
    function nestedCollection()
    function saveFile()
    	//TODO - get the file name and use it to name the save file
    	var docName =;
    	var append = "youth_1.fla"
    	var docURI = pathToFLA + append;
    function publishFile()
    	var profileXML = document.exportPublishProfileString('Default');
    	profileXML = profileXML.replace("1", "0");
    	profileXML = profileXML.replace("1", "0");
    	profileXML = profileXML.replace("1", "0");
    	var findString = "";
    	var startIndex = profileXML.indexOf(findString) + findString.length;
    	findString = "";
    	var endIndex = profileXML.indexOf(findString);
    	var curName = profileXML.substring(startIndex, endIndex);
    	var publishPath = "../swf/" +".fla","");
    	trace("This file is publishing to " + publishPath  + ".swf")
    	profileXML = profileXML.replace(curName,publishPath);
    //TODO - add layer script
    function addLayer()


    Firstly, how could I optimise this code a bit, any suggestions would be much appreciated.

    Secondly, How do I access nested elements? I have been struggling with this. I don't fully understand Iterators and have been getting errors when working through the tutorials. I have to access the elements inside the main movieclip because they are placed in the correct position. If I convert them to movieclips in the library, I would have to place them stage and check x and y positions and these differ from file to file.

    Thank you and sorry for the long post. Also, xJSFL is a great framework, just need to get my head around it all :D
  • DaveDave May 2012

    Hey fried,

    Did all your code paste in correctly there? Sometimes TinyMCE editor pastes in HTML when it should be text. Take a look and I will happily help you optimise what you have :)

    Sorry the docs are not currently finished. This is top of the list at the moment but real life keeps getting in the way!

  • friedfried May 2012

    Hi Dave,

    thanks for the speedy reply.

    I have cleaned up the code. Up to this point, everything works. It opens the XFL file, changes the compression settings of the bitmaps in the library, saves the file as an .fla and publishes the swf file. I still need to convert the bitmaps on stage to movieclips, and this is where I've hit a brick wall, because they are nested.

    Any help would be great!!

    Thank you.

    *Edit* On lines 58-60, TinyMCE seems to have removed the tags in the code.

  • DaveDave May 2012

    Feel free to email me a file, or maybe upload a Gist if would make it easier

  • friedfried May 2012

    Email sent.

    thank you.

  • DaveDave July 2012

    Hey Fred,

    Here's my (commented) rework of your code:

    xjsfl.init(this, ['Utils', 'URI']);

    // callback functions
    function convertToSymbol(element)
    var name = element.libraryItem.shortName;
    $selection = element;
    $dom.convertToSymbol('movie clip', name, 'top left');

    function processItem()
    Context.create().frame.actionScript = '// import classes.*;\n';

    // process
    function process(uris)
    // variables
    var processed = [];

    // process
    for each(var uri in uris)
    // debug
    format('Opening "{uri}" ...', uri);

    // process
    var doc = fl.openDocument(uri);
    // rename the clip on stage

    // update bitmaps
    .attr('compressionType', 'photo');

    // update the main movieclip

    // move newly created movieclips

    // file name variables
    var docName = 'youth_' + String(processed.length + 1).pad(2, 0) + '.fla';
    var swfPath = '../swf/' + docName.replace('.fla', '.swf');
    var flaURI = new URI('fla/' + docName);

    // save file
    format('Saving "{uri}" ...', flaURI.path);
    fl.saveDocument($dom, flaURI);

    // publish
    var profile = new PublishProfile();
    profile.file.flashPath = swfPath;
    profile.file.html = false;

    // close

    // add path to processed list

    // debug
    inspect(processed, 'The following file(s) were created');

    // variables
    var assetPath = 'assets/';
    var flaPath = 'swf/';

    // various ways to get files
    var uris = Utils.glob(assetPath + '*.xfl');
    var files = new Folder(assetPath).filter('*.xfl');
    var uriList = new URIList(assetPath + '*.xfl');

    // main

    FYI, my folder structure is:


    Things to note:

    • Much less use of functions
    • More elegant ways to get a list of URIs
    • Use of collection method attr() to update item properties
    • Use of collection.move() to tidy the library
    • Nesting handled in processitem() and convertToSymbol()
    • Use of new PublishProfile class

    I may actually update PublishProfile so you can hand the .fla filename in, then have it automatically update the correct swf extension.

    FYI, if you don't need the DOM in a particular operation (adding a script to frame, for example) you don't need to edit or exec() items. You can simply just reference the item's timeline (this is better performance-wise with lots of clips):

    function processItem(item)
    var index = item.timeline.addNewLayer('actions');
    item.timeline.layers[index].frames[0].actionScript = '// import classes.*;\n'; // etc...

    Also, there's no need to do a find and replace on a string of XML as you can just create an XML instance and set the values directly using dot-notation.

    Hope that helps anyway!

  • friedfried July 2012

    Thanks Dave, much appreciated. 

    The code I created a few months back was working perfectly. Will definitely look at implementing this for perfomance and better codeing practices though.

    xJSFL has cut our workload by almmost 80% :D Takes care of all the all the repetitive tasks.

    Congratulations on the release!!

  • DaveDave July 2012

    Hey, that's great news! You'll find another mail in your in box. Would love to know more about that :)

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Sign In with OpenID Sign In with Google Sign In with Twitter

Sign In Apply for Membership