index.js
function f1(settings) {

  if(!(this instanceof f1)) {

    return new f1(settings);
  }

  settings = settings || {};

  var emitter = this;
  var onUpdate = settings.onUpdate || noop;
  var onState = settings.onState || noop;

  // this is used to generate a "name" for an f1 instance if one isn't given
  numInstances++;

  this.onState = function() {
    emitter.emit.apply(emitter, getEventArgs('state', arguments));

    if(onState) {
      onState.apply(undefined, arguments);
    }
  };

  this.onUpdate = function() {
    emitter.emit.apply(emitter, getEventArgs('update', arguments));

    if(onUpdate) {
      onUpdate.apply(undefined, arguments);
    }
  };

  this.name = settings.name || 'ui_' + numInstances;
  this.isInitialized = false;
  this.data = null; // current animation data
  this.defTargets = null;
  this.defStates = null;
  this.defTransitions = null;
  this.parser = null;

  if(settings.transitions) {
    this.transitions(settings.transitions);
  }

  if(settings.states) {
    this.states(settings.states);
  }

  if(settings.targets) {
    this.targets(settings.targets);
  }

  if(settings.parsers) {
    this.parsers(settings.parsers);
  }

  // kimi is the man who does all the work under the hood
  this.driver = kimi( {

    manualStep: settings.autoUpdate === undefined ? false : !settings.autoUpdate,
    onState: _onState.bind(this),
    onUpdate: _onUpdate.bind(this)
  });
}
function f1(settings) {

  if(!(this instanceof f1)) {

    return new f1(settings);
  }

  settings = settings || {};

  var emitter = this;
  var onUpdate = settings.onUpdate || noop;
  var onState = settings.onState || noop;

  // this is used to generate a "name" for an f1 instance if one isn't given
  numInstances++;

  this.onState = function() {
    emitter.emit.apply(emitter, getEventArgs('state', arguments));

    if(onState) {
      onState.apply(undefined, arguments);
    }
  };

  this.onUpdate = function() {
    emitter.emit.apply(emitter, getEventArgs('update', arguments));

    if(onUpdate) {
      onUpdate.apply(undefined, arguments);
    }
  };

  this.name = settings.name || 'ui_' + numInstances;
  this.isInitialized = false;
  this.data = null; // current animation data
  this.defTargets = null;
  this.defStates = null;
  this.defTransitions = null;
  this.parser = null;

  if(settings.transitions) {
    this.transitions(settings.transitions);
  }

  if(settings.states) {
    this.states(settings.states);
  }

  if(settings.targets) {
    this.targets(settings.targets);
  }

  if(settings.parsers) {
    this.parsers(settings.parsers);
  }

  // kimi is the man who does all the work under the hood
  this.driver = kimi( {

    manualStep: settings.autoUpdate === undefined ? false : !settings.autoUpdate,
    onState: _onState.bind(this),
    onUpdate: _onUpdate.bind(this)
  });
}
function f1 ( settings ) { if ( ! ( this instanceof f1 ) ) { return new f1 ( settings ) ; } settings = settings || { } ; var emitter = this ; var onUpdate = settings . onUpdate || noop ; var onState = settings . onState || noop ; // this is used to generate a "name" for an f1 instance if one isn't given numInstances ++ ; this . onState = function ( ) { emitter . emit . apply ( emitter , getEventArgs ( 'state' , arguments ) ) ; if ( onState ) { onState . apply ( undefined , arguments ) ; } } ; this . onUpdate = function ( ) { emitter . emit . apply ( emitter , getEventArgs ( 'update' , arguments ) ) ; if ( onUpdate ) { onUpdate . apply ( undefined , arguments ) ; } } ; this . name = settings . name || 'ui_' + numInstances ; this . isInitialized = false ; this . data = null ; // current animation data this . defTargets = null ; this . defStates = null ; this . defTransitions = null ; this . parser = null ; if ( settings . transitions ) { this . transitions ( settings . transitions ) ; } if ( settings . states ) { this . states ( settings . states ) ; } if ( settings . targets ) { this . targets ( settings . targets ) ; } if ( settings . parsers ) { this . parsers ( settings . parsers ) ; } // kimi is the man who does all the work under the hood this . driver = kimi ( { manualStep : settings . autoUpdate === undefined ? false : ! settings . autoUpdate , onState : _onState . bind ( this ) , onUpdate : _onUpdate . bind ( this ) } ) ; }
To construct a new `f1` instance you can do it in two ways.

```javascript
ui = f1([ settigns ]);
```
or
```javascript
ui = new f1([ settings ]);
```

To construct an `f1` instance you can pass in an optional settings object. The following are properties you can pass in settings:
```javascript
{
onState: listenerState, // this callback will be called whenever f1 reaches a state
onUpdate: listenerUpdater, // this callback will be called whenever f1 is updating

// you can pass a name for the ui. This is useful when you're using an external tool or want
// to differentiate between f1 instances
name: 'someNameForTheUI',

// this is an object which contains all elements/items that you will be animating
targets: {
bg: bgElement
},

// all states for the ui
// states are the top level object and anything after that are the properties
// for that state
states: {
out: {

bg: { alpha: 0 }
},

idle: {

bg: { alpha: 1 }
}
},

// an array which defines the transitions for the ui
transitions: [
'out', 'idle', // this ui can go from out to idle
'idle', 'out' // and idle to out
],

// an Object contains init and update functions. These will be used
// to initialize your ui elements and apply state to targets during update
parsers: {
init: [ initPosition ],
update: [ applyPosition ]
}
}
```

@param  {Object} [settings] An optional settings Object described above
@chainable
To construct a new f1 instance you can do it in two ways .