Fork me on GitHub

AFrameJS

- Javascript MVC Library

Not Another DOM Manipulation Library!

AFrameJS is an MVC application development library, not a DOM manipulation library! AFrameJS leaves the DOM manipulation to jQuery, MooTools, or Prototype, instead providing the parts necessary to create MVC applications.

MVC is a programming paradigm that has been common in other languages for many years. In MVC, Models represent data and its operations. Views are the presentation of the data contained in a model. Controllers are the glue that bind the two together. MVC separates these three concepts, there is no mixing as is commonly found in web apps today. The benefits of MVC are numerous, but the main goal is to reduce the mental load for the developer. Modules focus on one goal at a time. This allows for smaller modules, easier testing, a higher chance of code re-use.

As web development matures, MVC based applications are becoming increasingly common. AFrameJS is being developed to fill the need of having a true MVC framework to develop applications with. Backbone and Knockout-JS are two similar libraries that address this need, now AFrameJS does too.

Quick Example

Presented below is a simple MVC application that combines many of AFrameJS' concepts. Models are created and contained in a Collection and then a List of Views presents the data contained in the models. AFrameJS's special object construct mechanism is used, allowing the developer to use object Plugins.
// The "main" Controller.

// Define the "layout" of model using a SchemaConfig.
var friendSchemaConfig = {
    name: { type: 'text' }
};

// Use a collection to keep track of the friend models.  When data items are
// inserted into collection, models will be created automatically using the
// layout defined in the friendSchemaConfig
var friendsCollection = AFrame.CollectionArray.create( {
    // Whenever data is inserted into the collection, create a model for the
    //  data using the layout defined in friendSchemaConfig.
    plugins: [ [ AFrame.CollectionPluginModel, {
        schema: friendSchemaConfig
    } ] ]
} );

// This is a list of friends.  It will display the data held by each of Friend models.
// The list is bound to the friendsCollection, any time a friend is added or removed
// from the collection, the list will be automatically updated.
var friendsList = AFrame.List.create( {
    target: '#friendList',
    listElementFactory: function( model, index ) {
        // whenever a model is inserted into the collection, create a list item
        //  using the data from the model.
        return AFrame.DOM.createElement( 'li', model.get( 'name' ) );
    },
    // Bind the list to the collection, causing the list to update automatically
    //  whenever friends are added or removed from the collection.
    plugins: [ [ AFrame.ListPluginBindToCollection, {
            collection: friendsCollection
        }
    ] ]
} );

// Once the user enters a name, insert the new "friend" data into the friendsCollection.
// A friend Model will be created, and the list will be updated - all automatically.
$( '#add-friend' ).click( function( event ) {
       var friend_name = prompt( "Who is your friend?" );
       friendsCollection.insert( { name: friend_name } );
} );
            

See the code in action

Friends:

While this example is contrived, it gives a brief example of what AFrameJS can do with a minimal amount of code. We have one main controller, a collection (representing Models) and a List(representing Views).

Overview

AFrameJS provides base level components necessary to start creating full MVC style applications.

At its core, AFrameJS is an event-driven system - anybody who has worked with DOM events will immediately understand how events work. The library takes advantage of Javascript's incredible flexibility - it is an OO library that uses Aspect Oriented and functional styles when appropriate.

AFrameJS is DOM library agnostic, meaning it can be used with any DOM library. All DOM manipulation within the library is done using DOM adapters, currently there are adapters for jQuery, MooTools and Prototype.

Pre-packaged and minified versions of AFrameJS are found at GitHub.

MVC in AFrameJS

Models

In AFrameJS, a Model is made up of a DataContainer and a Schema. A DataContainer is the object that holds data. A Schema acts as both a template and a filter when working with data objects. Models combine the power of both of these.

Models are often times part of a larger collection. Javascript provides two basic Collections, a hash or an array. AFrameJS provides two data collections as well, CollectionHash and CollectionArray.

Views

A Display in AFrameJS is a View in MVC. There are several types of Displays, but the basic Display provides very basic DOM and DOM event functionality. A Field provides two pieces of functionality, input and output. When used as input, a Field can get input from the user, validate the data, clean up the data, and display helpful hints when there are problems. A Form is a composite of Fields. A DataForm takes this one step further and binds a form to a DataContainer allowing changes in input to automatically update its corresponding model when all fields are valid.

Just as models are parts of a larger collection, often times Displays need to be part of a larger List.

Controllers

There has to be some fun in programming. You get to write whatever controllers you want.

Plugins

AFrameJS provides strong Observable(PubSub/events) and Plugin systems. Observables make it easy to listen for specific events that happen on an object, anybody who has worked with DOM Events already has an understanding of how Observables work. Plugins are a way of extending the functionality of an object through composition instead of inheritance - it combines the events, mixins, and decorators of other languages. Plugins make it easy for a small piece of functionality to be written once and be shared across several seemingly unrelated classes. Plugins also make configuring an object incredibly flexible. Instead of writing one gigantic class that does 15 different things, one small base class can be written and then all peripheral functionality can be placed into plugins. Developing this way makes testing and debugging much easier. It also means if an object no longer needs a piece of functionality, it can be thrown away without affecting other parts of the code.

The underlying principles of development in AFrame are:

Using AFrame

Get either a compiled version of the library or download the source from GitHub.

Try the Mobile Notes demo. No data is ever sent to the server, but in Chrome/Safari/Opera or your iPhone/iPad/Android devices, your notes persist across browser sessions!

Check out the tutorial for code examples of how to use the various components.

Read over the API documentation for nitty gritty details.

Examine and trace through the Unit Tests to see AFrame in action.

JS String toLocaleLowerCase