Introduction to Collections

Categories:Working with Flash

Overview

Flash has a relatively large list of items in its object hierarchy, but the most relevant to the everyday JSFL coder might be:

  • Documents
  • Library Items
  • Layers
  • Frames
  • Elements

Often when writing JSFL these object types will be available to use in Arrays (document.selection, library.items, layer.frames), and the usual approach for the developer is write loop code as needed, then run arbitrary JSFL on each item to update its state.

// get items
    var items = document.library.getSelectedItems();

// rename items
    for(var i = 0; i < items.length; i++)
    {
        items[i].name = 'Item_' + xjsfl.utils.pad(i, 2);
    }

Whilst that is fine in principle, it's not a very OO way of thinking about the problem, nor does it promote code reuse, or extension.

Enter Collections

Collections allow you to run code on multiple objects in a much cleaner and more object-oriented manner:

collection.rename('Item_##');

They are very similar to Arrays, in the fact that they contain elements that are iterated over, yet they have some important differences:

  • Looping code is encapsulated inside the Collection, making the public API clean
  • Collection elements are not directly accessed; rather public methods are used to update them
  • Collection methods return the Collection object itself, so method calls on Collection instances can be chained
  • Collection functionality can be extended by adding new methods to the prototype

xJSFL currently ships with two collection types (more may be added in future) that encapsulate everyday functionality into easy to use Collection methods.

Collections are created with the new operator, and convert native Arrays into xJSFL Collections quite easily, which are immediately available to have methods called on them:

// create collection
    var items      = $library.getSelectedItems();
    var collection = new ItemCollection(items);

// rename items
    collection.rename('Item_##');

Not only that, but as Collection methods are chainable, you can run multiple methods in an OO manner:

// select items and run various operations
    $$(':selected')
        .rename('Item_##')
        .update()
        .select();

You needn't worry if you have completely custom code to run on items within a collection. Every Collection type has an each() method that allows you to pass in a callback function of your own:

// define the callback
    function callback(element, index, elements){ ... }

// run a custom function over the collection elements
    collection.each(callback);

As you can see, it's just as flexible as the looped approach, but is more object-oriented.

How do Collection methods work internally?

To explain a little more about these mysterious methods on the ItemCollection instance, each method is simply a function on the ItemCollection prototype itself, and is responsible for updating the items within the instance it is attached to:

ItemCollection.prototype.rename = function(pattern)
{
    // loop over items and rename them according to the pattern
        for each(var element in this.elements) { ... }

    // return this, for chaining
        return this;
}

What this means in practice is that each Collection method takes full responsibility for updating the items within the collection, and the developer need only be responsible for passing in the correct parameters.

Some last points about Collections

A few last points regarding Collections:

  • Collections will work on multiple or single items, so if you want to update a single item, just pass it in as you would an Array
  • If you find yourself using custom code regularly, consider adding a custom Collection method as described above
  • Collections are only one way to handle updating items. Don't feel you have to use Collections if it's not suitable

Next steps

 

Comments are closed.