Add a little more to the model docs

Add a little more to the model docs

# Batman.Model

For a general explanation of `Batman.Model` and how it works, see [the guide](/docs/models.html).

_Note_: This documentation uses the term _model_ to refer to the class `Model`
or a `Model` subclass, and the term _record_ to refer to one instance of a
model.

## @primaryKey : string

`primaryKey` is a class level configuration option to change which key batman.js uses as the primary key. Change the option using `set`, like so:

    test 'primary key can be set using @set', ->
      class Shop extends Batman.Model
        @set 'primaryKey', 'shop_id'

      equal Shop.get('primaryKey'), 'shop_id'

The `primaryKey` is what batman.js uses to compare instances to see if they represent the same domain-level object: if two records have the same value at the key specified by `primaryKey`, only one will be in the identity map. The key specified by `primaryKey` is also used by the associations system when determining if a record is related to another record, and by the remote storage adapters to generate URLs for records.

_Note_: The default primaryKey is 'id'.

## @storageKey : string

`storageKey` is a class level option which gives the storage adapters something to interpolate into their specific key generation schemes. In the case of `LocalStorage` or `SessionStorage` adapters, the `storageKey` defines what namespace to store this record under in the `localStorage` or `sessionStorage` host objects, and with the case of the `RestStorage` family of adapters, the `storageKey` assists in URL generation. See the documentation for the storage adapter of your choice for more information.

The default `storageKey` is `null`.

## @persist(mechanism : StorageAdapter) : StorageAdapter

`@persist` is how a `Model` subclass is told to persist itself by means of a `StorageAdapter`. `@persist` accepts either a `StorageAdapter` class or instance and will return either the instantiated class or the instance passed to it for further modification.

    test 'models can be told to persist via a storage adapter', ->
      class Shop extends Batman.Model
        @resourceName: 'shop'
        @persist TestStorageAdapter

      record = new Shop
      ok record.hasStorage()

    test '@persist returns the instantiated storage adapter', ->
      adapter = false
      class Shop extends Batman.Model
        @resourceName: 'shop'
        adapter = @persist TestStorageAdapter

      ok adapter instanceof Batman.StorageAdapter

    test '@persist accepts already instantiated storage adapters', ->
      adapter = new Batman.StorageAdapter
      adapter.someHandyConfigurationOption = true
      class Shop extends Batman.Model
        @resourceName: 'shop'
        @persist adapter

      record = new Shop
      ok record.hasStorage()

## @encode(keys...[, encoderObject : [Object|Function]])

`@encode` specifies a list of `keys` a model should expect from and send back to a storage adapter, and any transforms to apply to those attributes as they enter and exit the world of batman.js in the optional `encoderObject`.

The `encoderObject` should have an `encode` and/or a `decode` key which point to functions. The functions accept the "raw" data (the batman.js land value in the case of `encode`, and the backend land value in the case of `decode`), and should return the data suitable for the other side of the link. The functions should have the following signatures:

    encoderObject = {
      encode: (value, key, builtJSON, record) ->
      decode: (value, key, incomingJSON, outgoingObject, record) ->
    }

By default these functions are the identity functions. They apply no transformation. The arguments for `encode` functions are as follows:

 + `value` is the client side value of the `key` on the `record`
 + `key` is the key that `value` is stored under on the `record`. This is useful when passing the same `encoderObject` which needs to pivot on what key is being encoded to different calls to `encode`.
 + `builtJSON` is the object passed to and modified by each encoder, and eventually becomes the return value of the `toJSON` call.
 + `record` is the record on which `toJSON` has been called.

For `decode` functions:

 + `value` is the raw value received from the storage adapter.
 + `key` is the key that `value` is stored under on the incoming data.
 + `incomingJSON` is the object which is being decoded into the `record`. This can be used to create compound key decoders.
 + `outgoingObject` is the object built up by the decoders and mixed into the record.
 + `record` is the record on which `fromJSON` has been called.

The `encode` and `decode` keys can also be false to avoid using the default identity function encoder or decoder.

To encode a `key` under a name which differs from that in the raw data, you can specify the `as` option with the raw key name. The `as` option can be either a string or function.

If you specify the `as` option as a function it will receive the following arguments:

 + `key` is the name which the `value` is stored under in the raw data.
 + `value` is the `value` of the `key` which will end up on the `record`.
 + `data` is the object which is modified by each encoder or decoder.
 + `record` is the record on which `toJSON` or `fromJSON` has been called.

_Note_: `Batman.Model` subclasses have no encoders by default, except for one which automatically decodes the `primaryKey` of the model, which is usually `id`. To get any data into or out of your model, you must white-list the keys you expect from the server or storage attribute.

    test '@encode accepts a list of keys which are used during decoding', ->
      class Shop extends Batman.Model
        @resourceName: 'shop'
        @encode 'name', 'url', 'email', 'country'

      json = {name: "Snowdevil", url: "snowdevil.ca"}
      record = new Shop()
      record.fromJSON(json)
      equal record.get('name'), "Snowdevil"

    test '@encode accepts a list of keys which are used during encoding', ->
      class Shop extends Batman.Model
        @resourceName: 'shop'
        @encode 'name', 'url', 'email', 'country'

      record = new Shop(name: "Snowdevil", url: "snowdevil.ca")
      deepEqual record.toJSON(), {name: "Snowdevil", url: "snowdevil.ca"}

    test '@encode accepts custom encoders', ->
      class Shop extends Batman.Model
        @resourceName: 'shop'
        @encode 'name',
          encode: (name) -> name.toUpperCase()

      record = new Shop(name: "Snowdevil")
      deepEqual record.toJSON(), {name: "SNOWDEVIL"}

    test '@encode accepts custom decoders', ->
      class Shop extends Batman.Model
        @resourceName: 'shop'
        @encode 'name',
          decode: (name) -> name.replace('_', ' ')

      record = new Shop()
      record.fromJSON {name: "Snow_devil"}
      equal record.get('name'), "Snow devil"

    test '@encode can be passed an encoderObject with false to prevent the default encoder or decoder', ->
      class Shop extends Batman.Model
        @resourceName: 'shop'
        @encode 'name', {encode: false, decode: (x) -> x}
        @encode 'url'

      record = new Shop()
      record.fromJSON {name: "Snowdevil", url: "snowdevil.ca"}
      equal record.get('name'), 'Snowdevil'
      equal record.get('url'), "snowdevil.ca"
      deepEqual record.toJSON(), {url: "snowdevil.ca"}, 'The name key is absent because of encode: false'

    test '@encode accepts an as option to encode a key under a name which differs from that in the raw data', ->
      class Shop extends Batman.Model
        @resourceName: 'shop'
        @encode 'countryCode',
          as: 'country_code'
          encode: @defaultEncoder.encode
          decode: @defaultEncoder.decode

      record = new Shop(countryCode: 'SE')
      deepEqual record.toJSON(), {country_code: 'SE'}

Some more handy examples:

    test '@encode can be used to turn comma separated values into arrays', ->
      class Post extends Batman.Model
        @resourceName: 'post'
        @encode 'tags',
          decode: (string) -> string.split(', ')
          encode: (array) -> array.join(', ')

      record = new Post()
      record.fromJSON({tags: 'new, hot, cool'})
      deepEqual record.get('tags'), ['new', 'hot', 'cool']
      deepEqual record.toJSON(), {tags: 'new, hot, cool'}

    test '@encode can be used to turn arrays into sets', ->
      class Post extends Batman.Model
        @resourceName: 'post'
        @encode 'tags',
          decode: (array) -> new Batman.Set(array...)
          encode: (set) -> set.toArray()

      record = new Post()
      record.fromJSON({tags: ['new', 'hot', 'cool']})
      ok record.get('tags') instanceof Batman.Set
      deepEqual record.toJSON(), {tags: ['new', 'hot', 'cool']}

    test '@encode accepts the as option as a function', ->
      class Shop extends Batman.Model
        @resourceName: 'shop'
        @encode 'countryCode',
          as: (key) -> Batman.helpers.underscore(key)
          encode: @defaultEncoder.encode
          decode: @defaultEncoder.decode

      record = new Shop(countryCode: 'SE')
      deepEqual record.toJSON(), {country_code: 'SE'}

## @validate(keys...[, options : [Object|Function]])

Validations allow a model to be marked as `valid` or `invalid` based on a set of programmatic rules. By validating a model's data before it gets to the server we can provide immediate feedback to the user about what they have entered and forgo waiting on a round trip to the server. `validate` allows the attachment of validations to the model on particular keys, where the validation is either a built in one (invoked by use of options to pass to them) or a custom one (invoked by use of a custom function as the second argument).

_Note_: Validation in batman.js is always asynchronous, despite the fact that none of the validations may use an asynchronous operation to check for validity. This is so that the API is consistent regardless of the validations used.

Built in validators are attached by calling `@validate` with options designating how to calculate the validity of the key:

    test '@validate accepts options to check for validity', ->
      QUnit.expect(0)
      class Post extends Batman.Model
        @resourceName: 'post'
        @validate 'title', 'body', {presence: true}

The built in validation options are listed below:

 + `presence : boolean`: Assert that the string value is existent (not undefined or null) and has length greater than 0.
 + `numeric : true`: Assert that the value is or can be coerced into a number using `parseFloat`.
 + `greaterThan : number`: Assert that the value is greater than the given number.
 + `greaterThanOrEqualTo : number`: Assert that the value is greater than or equal to the given number.
 + `equalTo : number`: Assert that the value is equal to the given number.
 + `lessThan : number`: Assert that the value is less than the given number.
 + `lessThanOrEqualTo : number`: Assert that the value is less than or equal to the given number.
 + `minLength : number`: Assert that the value's `length` property is greater than the given number.
 + `maxLength : number`: Assert that the value's `length` property is less than the given number.
 + `length : number`: Assert that the value's `length` property is exactly the given number.
 + `lengthWithin : [number, number]` or `lengthIn : [number, number]`: Assert that the value's `length` property is within the ranger specified by the given array of two numbers, where the first number is the lower bound and the second number is the upper bound.
 + `inclusion : in : [list, of, acceptable, values]`: Assert that the value is equal to one of the values in an array.
 + `exclusion : in : [list, of, unacceptable, values]`: Assert that the value is not equal to any of the values in an array.

Custom validators should have the signature `(errors, record, key, callback)`. The arguments are as follows:

 + `errors`: an `ErrorsSet` instance which expects to have `add` called on it to add errors to the model
 + `record`: the record being validated
 + `key`: the key to which the validation has been attached
 + `callback`: a function to call once validation has been completed. Calling this function is __mandatory__.

See [`Model::validate`](/docs/api/batman.model.html#prototype_function_validate) for information on how to get a particular record's validity.

## @loaded : Set

The `loaded` set is available on every model class and holds every model instance seen by the system in order to function as an identity map. Successfully loading or saving individual records or batches of records will result in those records being added to the `loaded` set. Destroying instances will remove records from the identity set.

    test 'the loaded set stores all records seen', ->
      class Post extends Batman.Model
        @resourceName: 'post'
        @persist TestStorageAdapter
        @encode 'name'

      ok Post.get('loaded') instanceof Batman.Set
      equal Post.get('loaded.length'), 0
      post = new Post()
      post.save()
      equal Post.get('loaded.length'), 1

    test 'the loaded adds new records caused by loads and removes records caused by destroys', ->
      class Post extends Batman.Model
        @resourceName: 'post'
        @encode 'name'

      adapter = new TestStorageAdapter(Post)
      adapter.storage =
          'posts1': {name: "One", id:1}
          'posts2': {name: "Two", id:2}

      Post.persist(adapter)
      Post.load()
      equal Post.get('loaded.length'), 2
      post = false
      Post.find(1, (err, result) -> post = result)
      post.destroy()
      equal Post.get('loaded.length'), 1

## @all : Set

The `all` set is an alias to the `loaded` set but with an added implicit `load` on the model. `Model.get('all')` will synchronously return the `loaded` set and asynchronously call `Model.load()` without options to load a batch of records and populate the set originally returned (the `loaded` set) with the records returned by the server.

_Note_: The notion of "all the records" is relative only to the client. It completely depends on the storage adapter in use and any backends which they may contact to determine what comes back during a `Model.load`. This means that if for example your API paginates records, the set found in `all` may hold on the first 50 records instead of the entire backend set.

`all` is useful for listing every instance of a model in a view, and since the `loaded` set will change when the `load` returns, it can be safely bound to.

    asyncTest 'the all set asynchronously fetches records when gotten', ->
      class Post extends Batman.Model
        @resourceName: 'post'
        @encode 'name'

      adapter = new AsyncTestStorageAdapter(Post)
      adapter.storage =
          'posts1': {name: "One", id:1}
          'posts2': {name: "Two", id:2}

      Post.persist(adapter)
      equal Post.get('all.length'), 0, "The synchronously returned set is empty"
      delay ->
        equal Post.get('all.length'), 2, "After the async load the set is populated"

## @clear() : Set

`Model.clear()` empties that `Model`'s identity map. This is useful for tests and other unnatural situations where records new to the system are guaranteed to be as such.

    test 'clearing a model removes all records from the identity map', ->
      class Post extends Batman.Model
        @resourceName: 'post'
        @encode 'name'

      adapter = new TestStorageAdapter(Post)
      adapter.storage =
          'posts1': {name: "One", id:1}
          'posts2': {name: "Two", id:2}
      Post.persist(adapter)
      Post.load()
      equal Post.get('loaded.length'), 2
      Post.clear()
      equal Post.get('loaded.length'), 0, "After clear() the loaded set is empty"

## @find(id, callback : Function) : Model

`Model.find()` retrieves a record with the specified `id` from the storage adapter and calls back with an error if one occurred and the record if the operation was successful. `find` delegates to the storage adapter the `Model` has been `@persist`ed with, so it is up to the storage adapter's semantics to determine what type of errors may return and the timeline on which the callback may be called. The `callback` is a required function which should adopt the node style callback signature which accepts two arguments: an error, and the record asked for. `find` returns an "unloaded" record which, following the load completion, will be populated with the data from the storage adapter.

_Note_: `find` gives two results to calling code: one immediately, and one later. `find` returns a record synchronously as it is called and calls back with a record, and importantly these two records are __not__ guaranteed to be the same instance. This is because batman.js maps the identities of incoming and outgoing records such that there is only ever one canonical instance representing a record, which is useful so bindings are always bound to the same thing. In practice, this means that calling code should use the record `find` calls back with if anything is going to bind to that object, which is most of the time. The returned record however remains useful for state inspection and bookkeeping.

    asyncTest '@find calls back the requested model if no error occurs', ->
      class Post extends Batman.Model
        @resourceName: 'post'
        @encode 'name'
        @persist AsyncTestStorageAdapter,
          storage:
            'posts2': {name: "Two", id:2}

      post = Post.find 2, (err, result) ->
        throw err if err
        post = result
      equal post.get('name'), undefined
      delay ->
        equal post.get('name'), "Two"

_Note_: `find` must be passed a callback function. This is for two reasons: calling code must be aware that `find`'s return value is not necessarily the canonical instance, and calling code must be able to handle errors.

    asyncTest '@find calls back with the error if an error occurs', ->
      class Post extends Batman.Model
        @resourceName: 'post'
        @encode 'name'
        @persist AsyncTestStorageAdapter

      error = false
      post = Post.find 3, (err, result) ->
        error = err
      delay ->
        ok error instanceof Error

## @load(options = {}, callback : Function)

`Model.load()` retrieves an array of records according to the given `options` from the storage adapter and calls back with an error if one occurred and the set of records if the operation was successful. `load` delegates to the storage adapter the `Model` has been `@persist`ed with, so it is up to the storage adapter's semantics to determine what the options do, what kind of errors may arise, and the timeline on which the callback may be called. The `callback` is a required function which should adopt the node style callback signature which accepts two arguments, an error, and the array of records. `load` returns undefined.

For the two main `StorageAdapter`s batman.js provides, the `options` do different things:

- For `Batman.LocalStorage`, `options` act as a filter. The adapter will scan all the records in `localStorage` and return only those records which match all the key/value pairs given in the options.
- For `Batman.RestStorage`, `options` are serialized into query parameters on the `GET` request.

It accepts a callback with two arguments: any error that occurred, and an array of loaded records.

    asyncTest '@load calls back an array of records retrieved from the storage adapter', ->
      class Post extends Batman.Model
        @resourceName: 'post'
        @encode 'name'
        @persist TestStorageAdapter,
          storage:
            'posts1': {name: "One", id:1}
            'posts2': {name: "Two", id:2}

      posts = false
      Post.load (err, result) ->
        throw err if err
        posts = result

      delay ->
        equal posts.length, 2
        equal posts[0].get('name'), "One"

    asyncTest '@load calls back with an empty array if no records are found', ->
      class Post extends Batman.Model
        @resourceName: 'post'
        @encode 'name'
        @persist TestStorageAdapter, storage: []

      posts = false
      Post.load (err, result) ->
        throw err if err
        posts = result

      delay ->
        equal posts.length, 0

## @create(attributes = {}, callback) : Model

`App.Model.create` is a convenience method that is essentially equivalent to
calling `(new App.Model).save()`:

    asyncTest "@create instantiates a new record instance and saves it", ->
      class Post extends Batman.Model
        @resourceName: 'post'
        @encode 'name'
        @persist TestStorageAdapter, storage: []

      # Using new + save:
      record = new Post(name: 'aName')
      record.save()

      # Using create:
      otherRecord = Post.create name: 'aName', ->

      delay ->
        equal record.get('name'), otherRecord.get('name')
        equal record.isNew(), false
        equal otherRecord.isNew(), false

_Note_ : `attributes` is an empty object `{}` by default. This means the single-argument version of `create` accepts the callback, and not the attributes object.

## @findOrCreate(attributes = {}, callback) : Model

## ::%id

A universally accessible accessor to the record's primary key. If the record's
primary key is `id` (the default), getting/setting this accessor simply passes
the call through to `id`, otherwise it proxies the call to the custom primary key.

    asyncTest "id proxies the primary key", ->
      class Post extends Batman.Model
        @primaryKey: 'name'

      post = new Post(name: 'Witty title')
      equal post.get('id'), 'Witty title'

      post.set('id', 'Wittier title')
      equal post.get('name'), 'Wittier title'

## ::%dirtyKeys : Set

The set of keys which have been modified since the last time the record was saved.

## ::%errors : Batman.ErrorsSet

`errors` is a `Batman.ErrorsSet`, which is simply a `Batman.Set` of [`Batman.ValidationError`](/docs/api/batman.validationerror.html)s present on the model instance.

- `user.get('errors')` returns the errors on the `user` record
- `user.get('errors.length')` returns the number of errors, total

You can also access the errors for a specific attribute of the record:

- `user.get('errors.email_address')` returns the errors on the `email_address` attribute
- `user.get('errors.email_address.length')` returns the number of errors on the `email_address` attribute

## @constructor(idOrAttributes = {}) : Model

## ::isNew() : boolean
Returns true if the instance represents a record that hasn't yet been persisted to storage. The default implementation simply checks if `@get('id')` is undefined, but you can override this on your own models.

`isNew` is used to determine whether `record.save()` will perform a `create` action or a `save` action.

## updateAttributes(attributes) : Model

## toString() : string

Returns a string representation suitable for debugging. By default this just contains the model's `resourceName` and `id`

## ::toJSON() : Object

Returns a JavaScript object containing the attributes of the record, using any specified encoders.

    test "toJSON returns a JavaScript object with the record's attributes", ->
      class Criminal extends Batman.Model
        @encode "name", "notorious"

      criminal = new Criminal(name: "Talia al Ghul", notorious: true)
      criminal_json = criminal.toJSON()
      equal criminal_json.name, "Talia al Ghul"
      equal criminal_json.notorious, true

## ::fromJSON() : Model

Loads attributes from a bare object into this instance.

    test 'fromJSON overwrites existing attributes', ->
      class Criminal extends Batman.Model
        @encode "name", "notorious"

      criminal = new Criminal(name: "Dr. Jonathan Crane", notorious: false)
      new_params =
        name: "Scarecrow"
        notorious: true
      criminal.fromJSON(new_params)

      equal criminal.get("notorious"), true
      equal criminal.get("name"), "Scarecrow"

## ::toParam() : value

Returns a representation of the model suitable for use in a URL. By default, this is the record's `id`.

This method is used by the routing system for serializing records into a URL.

## ::hasStorage() : boolean

True when the record has a storage adapter defined.

## ::load(options = {}, callback)
`Load` tries to read the record from its storage adapter. The options object will be passed to the storage adapter when it performs the `read` operation. The callback takes three parameters: error, the loaded record, and the environment. `Load`ing a record clears all errors on that record.

If the read operation fails or if the record is in a state which doesn't permit `load`, (for example, calling `load` on a deleted record) the callback will be invoked with an error.

## ::save(options = {}, callback)
`Save` [validates](http://localhost:4000/docs/api/batman.model.html#prototype_function_validate) the record, and if it passes, fires the corresponding storage operation (defined by the `Batman.StorageAdapter` passed to  [`@persist`](/docs/api/batman.model.html#class_function_persist)). When the storage operation is complete, the callback is invoked with two parameters: any JavaScript error and the record.

If the record [`isNew`](/docs/api/batman.model.html#prototype_function_isnew), `save` performs a `create` operation. Otherwise, it performs a `save` operation.

If the record is not valid, the [validation errors](/docs/api/batman.validationerror.html) will be passed to the first parameter of the callback function and the storage operation will not be performed.

## ::destroy(options = {}, callback)

`Destroy` fires the corresponding storage operation. The callback takes three arguments: JavaScript Error, the record, and the environment. If the operation is successful, the record is removed from its Model's [`loaded`](/docs/api/batman.model.html#class_function_loaded) set.

```coffeescript
criminal = new Criminal name: "The penguin"
criminal.destroy (err, record, env) ->
  if err
    console.log "Oh no! #{record.get('name')} is still on the loose!"
```

If the record's current lifecycle state doesn't allow the `destroy` action, the callback will be invoked with a `Batman.StateMachine.InvalidTransitionError`. For example, this could occur if `destroy` is called on an already-destroyed record.

## ::validate(callback)

`Model::validate` checks the model against the validations declared in the model definition (with [`Model@validate`](/docs/api/batman.model.html#class_function_validate)). This method accepts a callback with two arguments: any JS error that occurred within the validator function, and the set of [`Batman.ValidationError`](/docs/api/batman.validationerror.html)s that the input generated.

For example:

    test "validate(callback) will call the callback only after all keys have been validated", ->
      class Product extends Batman.Model
        @validate 'name', 'price', presence: yes

      newProduct = new Product
      newProduct.validate (javascriptError, validationErrors) ->
        throw javascriptError if javascriptError
        equal validationErrors.length, 2
        equal newProduct.get('errors.length'), 2
        equal newProduct.get('errors.name.length'), 1
        equal newProduct.get('errors.price.length'), 1

# Batman.ValidationError

`Batman.ValidationError`s represent a failure for a model's field to to pass validation.
They are usually accessed by getting a model's [errors](/docs/api/batman.model.html#prototype_accessor_errors).

## ::%fullMessage

Returns the human-readable attribute name and the validation message:

    test "ValidationError should humanize attribute in the full message", ->
      error = new Batman.ValidationError("fooBarBaz", "isn't valid")
      equal error.get('fullMessage'), "Foo bar baz isn't valid"

# Batman.Model

For a general explanation of `Batman.Model` and how it works, see [the guide](/docs/models.html).

_Note_: This documentation uses the term _model_ to refer to the class `Model`
or a `Model` subclass, and the term _record_ to refer to one instance of a
model.

## @primaryKey : string

`primaryKey` is a class level configuration option to change which key batman.js uses as the primary key. Change the option using `set`, like so:

    test 'primary key can be set using @set', ->
      class Shop extends Batman.Model
        @set 'primaryKey', 'shop_id'

      equal Shop.get('primaryKey'), 'shop_id'

The `primaryKey` is what batman.js uses to compare instances to see if they represent the same domain-level object: if two records have the same value at the key specified by `primaryKey`, only one will be in the identity map. The key specified by `primaryKey` is also used by the associations system when determining if a record is related to another record, and by the remote storage adapters to generate URLs for records.

_Note_: The default primaryKey is 'id'.

## @storageKey : string

`storageKey` is a class level option which gives the storage adapters something to interpolate into their specific key generation schemes. In the case of `LocalStorage` or `SessionStorage` adapters, the `storageKey` defines what namespace to store this record under in the `localStorage` or `sessionStorage` host objects, and with the case of the `RestStorage` family of adapters, the `storageKey` assists in URL generation. See the documentation for the storage adapter of your choice for more information.

The default `storageKey` is `null`.

## @persist(mechanism : StorageAdapter) : StorageAdapter

`@persist` is how a `Model` subclass is told to persist itself by means of a `StorageAdapter`. `@persist` accepts either a `StorageAdapter` class or instance and will return either the instantiated class or the instance passed to it for further modification.

    test 'models can be told to persist via a storage adapter', ->
      class Shop extends Batman.Model
        @resourceName: 'shop'
        @persist TestStorageAdapter

      record = new Shop
      ok record.hasStorage()

    test '@persist returns the instantiated storage adapter', ->
      adapter = false
      class Shop extends Batman.Model
        @resourceName: 'shop'
        adapter = @persist TestStorageAdapter

      ok adapter instanceof Batman.StorageAdapter

    test '@persist accepts already instantiated storage adapters', ->
      adapter = new Batman.StorageAdapter
      adapter.someHandyConfigurationOption = true
      class Shop extends Batman.Model
        @resourceName: 'shop'
        @persist adapter

      record = new Shop
      ok record.hasStorage()

## @encode(keys...[, encoderObject : [Object|Function]])

`@encode` specifies a list of `keys` a model should expect from and send back to a storage adapter, and any transforms to apply to those attributes as they enter and exit the world of batman.js in the optional `encoderObject`.

The `encoderObject` should have an `encode` and/or a `decode` key which point to functions. The functions accept the "raw" data (the batman.js land value in the case of `encode`, and the backend land value in the case of `decode`), and should return the data suitable for the other side of the link. The functions should have the following signatures:

    encoderObject = {
      encode: (value, key, builtJSON, record) ->
      decode: (value, key, incomingJSON, outgoingObject, record) ->
    }

By default these functions are the identity functions. They apply no transformation. The arguments for `encode` functions are as follows:

 + `value` is the client side value of the `key` on the `record`
 + `key` is the key that `value` is stored under on the `record`. This is useful when passing the same `encoderObject` which needs to pivot on what key is being encoded to different calls to `encode`.
 + `builtJSON` is the object passed to and modified by each encoder, and eventually becomes the return value of the `toJSON` call.
 + `record` is the record on which `toJSON` has been called.

For `decode` functions:

 + `value` is the raw value received from the storage adapter.
 + `key` is the key that `value` is stored under on the incoming data.
 + `incomingJSON` is the object which is being decoded into the `record`. This can be used to create compound key decoders.
 + `outgoingObject` is the object built up by the decoders and mixed into the record.
 + `record` is the record on which `fromJSON` has been called.

The `encode` and `decode` keys can also be false to avoid using the default identity function encoder or decoder.

To encode a `key` under a name which differs from that in the raw data, you can specify the `as` option with the raw key name. The `as` option can be either a string or function.

If you specify the `as` option as a function it will receive the following arguments:

 + `key` is the name which the `value` is stored under in the raw data.
 + `value` is the `value` of the `key` which will end up on the `record`.
 + `data` is the object which is modified by each encoder or decoder.
 + `record` is the record on which `toJSON` or `fromJSON` has been called.

_Note_: `Batman.Model` subclasses have no encoders by default, except for one which automatically decodes the `primaryKey` of the model, which is usually `id`. To get any data into or out of your model, you must white-list the keys you expect from the server or storage attribute.

    test '@encode accepts a list of keys which are used during decoding', ->
      class Shop extends Batman.Model
        @resourceName: 'shop'
        @encode 'name', 'url', 'email', 'country'

      json = {name: "Snowdevil", url: "snowdevil.ca"}
      record = new Shop()
      record.fromJSON(json)
      equal record.get('name'), "Snowdevil"

    test '@encode accepts a list of keys which are used during encoding', ->
      class Shop extends Batman.Model
        @resourceName: 'shop'
        @encode 'name', 'url', 'email', 'country'

      record = new Shop(name: "Snowdevil", url: "snowdevil.ca")
      deepEqual record.toJSON(), {name: "Snowdevil", url: "snowdevil.ca"}

    test '@encode accepts custom encoders', ->
      class Shop extends Batman.Model
        @resourceName: 'shop'
        @encode 'name',
          encode: (name) -> name.toUpperCase()

      record = new Shop(name: "Snowdevil")
      deepEqual record.toJSON(), {name: "SNOWDEVIL"}

    test '@encode accepts custom decoders', ->
      class Shop extends Batman.Model
        @resourceName: 'shop'
        @encode 'name',
          decode: (name) -> name.replace('_', ' ')

      record = new Shop()
      record.fromJSON {name: "Snow_devil"}
      equal record.get('name'), "Snow devil"

    test '@encode can be passed an encoderObject with false to prevent the default encoder or decoder', ->
      class Shop extends Batman.Model
        @resourceName: 'shop'
        @encode 'name', {encode: false, decode: (x) -> x}
        @encode 'url'

      record = new Shop()
      record.fromJSON {name: "Snowdevil", url: "snowdevil.ca"}
      equal record.get('name'), 'Snowdevil'
      equal record.get('url'), "snowdevil.ca"
      deepEqual record.toJSON(), {url: "snowdevil.ca"}, 'The name key is absent because of encode: false'

    test '@encode accepts an as option to encode a key under a name which differs from that in the raw data', ->
      class Shop extends Batman.Model
        @resourceName: 'shop'
        @encode 'countryCode',
          as: 'country_code'
          encode: @defaultEncoder.encode
          decode: @defaultEncoder.decode

      record = new Shop(countryCode: 'SE')
      deepEqual record.toJSON(), {country_code: 'SE'}

Some more handy examples:

    test '@encode can be used to turn comma separated values into arrays', ->
      class Post extends Batman.Model
        @resourceName: 'post'
        @encode 'tags',
          decode: (string) -> string.split(', ')
          encode: (array) -> array.join(', ')

      record = new Post()
      record.fromJSON({tags: 'new, hot, cool'})
      deepEqual record.get('tags'), ['new', 'hot', 'cool']
      deepEqual record.toJSON(), {tags: 'new, hot, cool'}

    test '@encode can be used to turn arrays into sets', ->
      class Post extends Batman.Model
        @resourceName: 'post'
        @encode 'tags',
          decode: (array) -> new Batman.Set(array...)
          encode: (set) -> set.toArray()

      record = new Post()
      record.fromJSON({tags: ['new', 'hot', 'cool']})
      ok record.get('tags') instanceof Batman.Set
      deepEqual record.toJSON(), {tags: ['new', 'hot', 'cool']}

    test '@encode accepts the as option as a function', ->
      class Shop extends Batman.Model
        @resourceName: 'shop'
        @encode 'countryCode',
          as: (key) -> Batman.helpers.underscore(key)
          encode: @defaultEncoder.encode
          decode: @defaultEncoder.decode

      record = new Shop(countryCode: 'SE')
      deepEqual record.toJSON(), {country_code: 'SE'}

## @validate(keys...[, options : [Object|Function]])

Validations allow a model to be marked as `valid` or `invalid` based on a set of programmatic rules. By validating a model's data before it gets to the server we can provide immediate feedback to the user about what they have entered and forgo waiting on a round trip to the server. `validate` allows the attachment of validations to the model on particular keys, where the validation is either a built in one (invoked by use of options to pass to them) or a custom one (invoked by use of a custom function as the second argument).

_Note_: Validation in batman.js is always asynchronous, despite the fact that none of the validations may use an asynchronous operation to check for validity. This is so that the API is consistent regardless of the validations used.

Built in validators are attached by calling `@validate` with options designating how to calculate the validity of the key:

    test '@validate accepts options to check for validity', ->
      QUnit.expect(0)
      class Post extends Batman.Model
        @resourceName: 'post'
        @validate 'title', 'body', {presence: true}

The built in validation options are listed below:

 + `presence : boolean`: Assert that the string value is existent (not undefined or null) and has length greater than 0.
 + `numeric : true`: Assert that the value is or can be coerced into a number using `parseFloat`.
 + `greaterThan : number`: Assert that the value is greater than the given number.
 + `greaterThanOrEqualTo : number`: Assert that the value is greater than or equal to the given number.
 + `equalTo : number`: Assert that the value is equal to the given number.
 + `lessThan : number`: Assert that the value is less than the given number.
 + `lessThanOrEqualTo : number`: Assert that the value is less than or equal to the given number.
 + `minLength : number`: Assert that the value's `length` property is greater than the given number.
 + `maxLength : number`: Assert that the value's `length` property is less than the given number.
 + `length : number`: Assert that the value's `length` property is exactly the given number.
 + `lengthWithin : [number, number]` or `lengthIn : [number, number]`: Assert that the value's `length` property is within the ranger specified by the given array of two numbers, where the first number is the lower bound and the second number is the upper bound.
 + `inclusion : in : [list, of, acceptable, values]`: Assert that the value is equal to one of the values in an array.
 + `exclusion : in : [list, of, unacceptable, values]`: Assert that the value is not equal to any of the values in an array.

Custom validators should have the signature `(errors, record, key, callback)`. The arguments are as follows:

 + `errors`: an `ErrorsSet` instance which expects to have `add` called on it to add errors to the model
 + `record`: the record being validated
 + `key`: the key to which the validation has been attached
 + `callback`: a function to call once validation has been completed. Calling this function is __mandatory__.

See [`Model::validate`](/docs/api/batman.model.html#prototype_function_validate) for information on how to get a particular record's validity.

## @loaded : Set

The `loaded` set is available on every model class and holds every model instance seen by the system in order to function as an identity map. Successfully loading or saving individual records or batches of records will result in those records being added to the `loaded` set. Destroying instances will remove records from the identity set.

    test 'the loaded set stores all records seen', ->
      class Post extends Batman.Model
        @resourceName: 'post'
        @persist TestStorageAdapter
        @encode 'name'

      ok Post.get('loaded') instanceof Batman.Set
      equal Post.get('loaded.length'), 0
      post = new Post()
      post.save()
      equal Post.get('loaded.length'), 1

    test 'the loaded adds new records caused by loads and removes records caused by destroys', ->
      class Post extends Batman.Model
        @resourceName: 'post'
        @encode 'name'

      adapter = new TestStorageAdapter(Post)
      adapter.storage =
          'posts1': {name: "One", id:1}
          'posts2': {name: "Two", id:2}

      Post.persist(adapter)
      Post.load()
      equal Post.get('loaded.length'), 2
      post = false
      Post.find(1, (err, result) -> post = result)
      post.destroy()
      equal Post.get('loaded.length'), 1

## @all : Set

The `all` set is an alias to the `loaded` set but with an added implicit `load` on the model. `Model.get('all')` will synchronously return the `loaded` set and asynchronously call `Model.load()` without options to load a batch of records and populate the set originally returned (the `loaded` set) with the records returned by the server.

_Note_: The notion of "all the records" is relative only to the client. It completely depends on the storage adapter in use and any backends which they may contact to determine what comes back during a `Model.load`. This means that if for example your API paginates records, the set found in `all` may hold on the first 50 records instead of the entire backend set.

`all` is useful for listing every instance of a model in a view, and since the `loaded` set will change when the `load` returns, it can be safely bound to.

    asyncTest 'the all set asynchronously fetches records when gotten', ->
      class Post extends Batman.Model
        @resourceName: 'post'
        @encode 'name'

      adapter = new AsyncTestStorageAdapter(Post)
      adapter.storage =
          'posts1': {name: "One", id:1}
          'posts2': {name: "Two", id:2}

      Post.persist(adapter)
      equal Post.get('all.length'), 0, "The synchronously returned set is empty"
      delay ->
        equal Post.get('all.length'), 2, "After the async load the set is populated"

## @clear() : Set

`Model.clear()` empties that `Model`'s identity map. This is useful for tests and other unnatural situations where records new to the system are guaranteed to be as such.

    test 'clearing a model removes all records from the identity map', ->
      class Post extends Batman.Model
        @resourceName: 'post'
        @encode 'name'

      adapter = new TestStorageAdapter(Post)
      adapter.storage =
          'posts1': {name: "One", id:1}
          'posts2': {name: "Two", id:2}
      Post.persist(adapter)
      Post.load()
      equal Post.get('loaded.length'), 2
      Post.clear()
      equal Post.get('loaded.length'), 0, "After clear() the loaded set is empty"

## @find(id, callback : Function) : Model

`Model.find()` retrieves a record with the specified `id` from the storage adapter and calls back with an error if one occurred and the record if the operation was successful. `find` delegates to the storage adapter the `Model` has been `@persist`ed with, so it is up to the storage adapter's semantics to determine what type of errors may return and the timeline on which the callback may be called. The `callback` is a required function which should adopt the node style callback signature which accepts two arguments: an error, and the record asked for. `find` returns an "unloaded" record which, following the load completion, will be populated with the data from the storage adapter.

_Note_: `find` gives two results to calling code: one immediately, and one later. `find` returns a record synchronously as it is called and calls back with a record, and importantly these two records are __not__ guaranteed to be the same instance. This is because batman.js maps the identities of incoming and outgoing records such that there is only ever one canonical instance representing a record, which is useful so bindings are always bound to the same thing. In practice, this means that calling code should use the record `find` calls back with if anything is going to bind to that object, which is most of the time. The returned record however remains useful for state inspection and bookkeeping.

    asyncTest '@find calls back the requested model if no error occurs', ->
      class Post extends Batman.Model
        @resourceName: 'post'
        @encode 'name'
        @persist AsyncTestStorageAdapter,
          storage:
            'posts2': {name: "Two", id:2}

      post = Post.find 2, (err, result) ->
        throw err if err
        post = result
      equal post.get('name'), undefined
      delay ->
        equal post.get('name'), "Two"

_Note_: `find` must be passed a callback function. This is for two reasons: calling code must be aware that `find`'s return value is not necessarily the canonical instance, and calling code must be able to handle errors.

    asyncTest '@find calls back with the error if an error occurs', ->
      class Post extends Batman.Model
        @resourceName: 'post'
        @encode 'name'
        @persist AsyncTestStorageAdapter

      error = false
      post = Post.find 3, (err, result) ->
        error = err
      delay ->
        ok error instanceof Error

## @load(options = {}, callback : Function)

`Model.load()` retrieves an array of records according to the given `options` from the storage adapter and calls back with an error if one occurred and the set of records if the operation was successful. `load` delegates to the storage adapter the `Model` has been `@persist`ed with, so it is up to the storage adapter's semantics to determine what the options do, what kind of errors may arise, and the timeline on which the callback may be called. The `callback` is a required function which should adopt the node style callback signature which accepts two arguments, an error, and the array of records. `load` returns undefined.

For the two main `StorageAdapter`s batman.js provides, the `options` do different things:

- For `Batman.LocalStorage`, `options` act as a filter. The adapter will scan all the records in `localStorage` and return only those records which match all the key/value pairs given in the options.
- For `Batman.RestStorage`, `options` are serialized into query parameters on the `GET` request.

It accepts a callback with two arguments: any error that occurred, and an array of loaded records.

    asyncTest '@load calls back an array of records retrieved from the storage adapter', ->
      class Post extends Batman.Model
        @resourceName: 'post'
        @encode 'name'
        @persist TestStorageAdapter,
          storage:
            'posts1': {name: "One", id:1}
            'posts2': {name: "Two", id:2}

      posts = false
      Post.load (err, result) ->
        throw err if err
        posts = result

      delay ->
        equal posts.length, 2
        equal posts[0].get('name'), "One"

    asyncTest '@load calls back with an empty array if no records are found', ->
      class Post extends Batman.Model
        @resourceName: 'post'
        @encode 'name'
        @persist TestStorageAdapter, storage: []

      posts = false
      Post.load (err, result) ->
        throw err if err
        posts = result

      delay ->
        equal posts.length, 0

## @create(attributes = {}, callback) : Model

`App.Model.create` is a convenience method that is essentially equivalent to
calling `(new App.Model).save()`:

    asyncTest "@create instantiates a new record instance and saves it", ->
      class Post extends Batman.Model
        @resourceName: 'post'
        @encode 'name'
        @persist TestStorageAdapter, storage: []

      # Using new + save:
      record = new Post(name: 'aName')
      record.save()

      # Using create:
      otherRecord = Post.create name: 'aName', ->

      delay ->
        equal record.get('name'), otherRecord.get('name')
        equal record.isNew(), false
        equal otherRecord.isNew(), false

_Note_ : Attributes is an empty object `{}` by default. This means the single-argument version accepts the callback, and not the attributes object.

## @findOrCreate(attributes = {}, callback) : Model

## id : value

## dirtyKeys : Set

## ::%errors : Batman.ErrorsSet

`errors` is a `Batman.ErrorsSet`, which is simply a `Batman.Set` of [`Batman.ValidationError`](/docs/api/batman.validationerror.html)s present on the model instance.

- `user.get('errors')` returns the errors on the `user` record
- `user.get('errors.length')` returns the number of errors, total

You can also access the errors for a specific attribute of the record:

- `user.get('errors.email_address')` returns the errors on the `email_address` attribute
- `user.get('errors.email_address.length')` returns the number of errors on the `email_address` attribute

## constructor(idOrAttributes = {}) : Model

## ::isNew() : boolean
Returns whether or not the instance represents a record that hasn't yet been persisted to the server. The default implementation simply checks if `@get('id')` is undefined, but you could override this on your own models.

It is used to determine whether `record.save()` will perform a `create` action or a `save` action.

## updateAttributes(attributes) : Model

## toString() : string

## ::toJSON() : Object

Returns a JavaScript object containing the attributes of the record, using any specified encoders.

    test "toJSON returns a JavaScript object with the record's attributes", ->
      class Criminal extends Batman.Model
        @encode "name", "notorious"

      criminal = new Criminal(name: "Talia al Ghul", notorious: true)
      criminal_json = criminal.toJSON()
      equal criminal_json.name, "Talia al Ghul"
      equal criminal_json.notorious, true

## ::fromJSON() : Model

Reloads attributes of a record from a JavaScript object.

    test 'fromJSON overwrites existing attributes', ->
      class Criminal extends Batman.Model
        @encode "name", "notorious"

      criminal = new Criminal(name: "Dr. Jonathan Crane", notorious: false)
      new_params =
        name: "Scarecrow"
        notorious: true
      criminal.fromJSON(new_params)

      equal criminal.get("notorious"), true
      equal criminal.get("name"), "Scarecrow"

## toParam() : value

## state() : string

## hasStorage() : boolean

## ::load(options = {}, callback)
`Load` tries to read the record from its storage adapter. The options object will be passed to the storage adapter when it performs the `read` operation. The callback takes three parameters: error, the loaded record, and the environment. `Load`ing a record clears all errors on that record.

If the read operation fails or if the record is in a state which doesn't permit `load`, (for example, calling `load` on a deleted record) the callback will be invoked with an error.

## ::save(options = {}, callback)
`Save` [validates](http://localhost:4000/docs/api/batman.model.html#prototype_function_validate) the record, and if it passes, fires the corresponding storage operation (defined by the `Batman.StorageAdapter` passed to  [`@persist`](/docs/api/batman.model.html#class_function_persist)). When the storage operation is complete, the callback is invoked with two parameters: any JavaScript error and the record.

If the record [`isNew`](/docs/api/batman.model.html#prototype_function_isnew), `save` performs a `create` operation. Otherwise, it performs a `save` operation.

If the record is not valid, the [validation errors](/docs/api/batman.validationerror.html) will be passed to the first parameter of the callback function and the storage operation will not be performed.

## ::destroy(options = {}, callback)

`Destroy` fires the corresponding storage operation. The callback takes three arguments: JavaScript Error, the record, and the environment. If the operation is successful, the record is removed from its Model's [`loaded`](/docs/api/batman.model.html#class_function_loaded) set.

```coffeescript
criminal = new Criminal name: "The penguin"
criminal.destroy (err, record, env) ->
  if err
    console.log "Oh no! #{record.get('name')} is still on the loose!"
```

If the record's current lifecycle state doesn't allow the `destroy` action, the callback will be invoked with a `Batman.StateMachine.InvalidTransitionError`. For example, this could occur if `destroy` is called on an already-destroyed record.

## ::validate(callback)

`Model::validate` checks the model against the validations declared in the model definition (with [`Model@validate`](/docs/api/batman.model.html#class_function_validate)). This method accepts a callback with two arguments: any JS error that occurred within the validator function, and the set of [`Batman.ValidationError`](/docs/api/batman.validationerror.html)s that the input generated.

For example:

    test "validate(callback) will call the callback only after all keys have been validated", ->
      class Product extends Batman.Model
        @validate 'name', 'price', presence: yes

      newProduct = new Product
      newProduct.validate (javascriptError, validationErrors) ->
        throw javascriptError if javascriptError
        equal validationErrors.length, 2
        equal newProduct.get('errors.length'), 2
        equal newProduct.get('errors.name.length'), 1
        equal newProduct.get('errors.price.length'), 1

# Batman.ValidationError

`Batman.ValidationError`s represent a failure for a model's field to to pass validation.
They are usually accessed by getting a model's [errors](/docs/api/batman.model.html#prototype_accessor_errors).

## ::%fullMessage

Returns the human-readable attribute name and the validation message:

    test "ValidationError should humanize attribute in the full message", ->
      error = new Batman.ValidationError("fooBarBaz", "isn't valid")
      equal error.get('fullMessage'), "Foo bar baz isn't valid"


Break into multiple lines to prevent overflow and broken highlighting

# Batman.View Bindings

Batman's view bindings are how data gets shown and collected from the user. They center on the notion of "bindings": that the view representation and the JavaScript land value are always guaranteed to be in sync, such that when one changes, the other will reflect it.

## How to use bindings

Bindings are declared as attributes on nodes under the `data` namespace. In practice, it looks like this:

```html
<div data-bind="name"></div>
```

This instantiates a binding on the `div` node which will update the node's `innerHTML` with the value found at the `name` keypath in the current context. Whenever the `name` key changes, the div's `innerHTML` will update to the new value.

Nodes can have multiple bindings:

```html
<p data-bind="body" data-showif="isPublished"></p>
```

or attribute bindings:

```html
<p data-bind-id="currentID"></p>
```

and bindings can be on inputs which the user can change:

```html
<input type="text" data-bind="title"></input>
```

When the `title` property changes on the JavaScript object this `input` is bound to, the `input`'s value will be updated. When the user types into the `input` (and `change` or `keyup` events are triggered), the `title` property in JavaScript land will be updated.

## Binding Keypaths

A `keypath` is the value of the HTML attribute a binding references. Importantly, keypaths can have multiple segments:

```html
<p data-bind="order.customer.name"></p>
```

The keypath in the above HTML is `order.customer.name`. When you create a binding to a keypath like this (with dots separating segments), the binding will update the HTML value when _any_ of those segments change. In the above example, this means the `p` tag's `innerHTML` will be updated when:

 1. the order changes,
 2. the order's customer changes,
 3. or the order's customer's name changes.

This is important because it means you can rely on a binding to "just work" when anything it depends on changes. If say you had a `<select>` on the page which changed the `order`'s `customer` property, bindings which bind to `order.customer.name` will update each time you change that select to reflect the new customer's name.

## Binding Contexts

All bindings render in a context. Binding contexts, known internally to Batman as `RenderContext`s, are objects which emulate the notion of variable scope in JavaScript code. When a controller action renders, it passes a context to the view consisting of itself, the `App`, and an object with a `window` key pointing to the host `window` object.

## Keypath Filters

Bindings can bind to filtered keypaths:

```html
<p data-bind="post.body | truncate 100"></p>
```

The above `<p>` will have 100 characters worth of the post's body. Whenever the post's body changes, it will be retruncated and the `<p>`'s `innerHTML` will be updated.

Filter chains can be arbitrarily long:

```html
<span data-bind="knight.title | prepend 'Sir' | append ', the honourable'."></span>
```

and filter chains can use other keypaths as arguments to the filters:

```html
<span data-bind="person.name | prepend ' ' | prepend person.title"></span>
```

The above `<span>`'s `innerHTML` will be updated whenever the person's name or title changes.

#### Two Way Bindings and Filters

Note that filtered keypaths cannot propagate DOM land changes because values can't always be "unfiltered". For example, if we bind an input to the truncated version of a string:

```html
<input data-bind="post.body | truncate 100"></input>
```

The `<input>`'s value can be updated when the `post.body` property changes but if a user types into this input field, they will edit the truncated body. If Batman updated the `post.body` property with the contents of the input, all characters which had been truncated will be lost to the nether. To avoid this loss of information and inconsistency, bindings to filtered keypaths will _only update from JavaScript land to HTML_, and never vice versa.

## Keypath Literals

Keypaths also support a select few literals within them. Numbers, strings, and booleans can be passed as arguments to filters or used as the actual value of the keypath.

The following are all valid, albeit contrived, bindings:

```html
<!-- String literal used as an argument -->
<p data-bind="body | append ' ... '"></p>

<!-- Boolean literal used as an argument -->
<p data-showif="shouldShow | default true"></p>

<!-- Number literal used as an argument -->
<p data-bind="body | truncate 100"></p>

<!-- String literal used as the value -->
<p data-bind="'Hardcoded'"></p>

<!-- Boolean literal used as the value -->
<p data-showif="true"></p>
```

## data-bind

`data-bind` creates a two way binding between a property on a `Batman.Object` and an HTML element. Bindings created via `data-bind` will update the HTML element with the value of the JS land property as soon as they are created and each time the property changes after, and if the HTML element can be observed for changes, it will update the JS land property with the value from the HTML.

`data-bind` will change its behaviour depending on what kind of tag it is attached to:

 + `<input type="checkbox">`: the binding will edit the `checked` property of the checkbox and populate the keypath with a boolean.
 + `<input type="text">` and similar, `<textarea`>: the binding will edit the `value` property of the input and populate the keypath with the string found at `value`.
 + `<input type="file">`: the binding will _not_ edit the `value` property of the input, but it will update the keypath with a host `File` object or objects if the node has the `multiple` attribute.
 + `<select>`: the binding will edit the `selected` property of each `<option>` tag within the `<select>` matching the property at the keypath. If the `<select>` has the multiple attribute, the value at the keypath can be an array of selected `<option>` values. You can also use `data-bind-selected` bindings on the individual options to toggle option selectedness.
 + All other tags: the binding will edit the `innerHTML` property of the tag and will not populate the keypath.

`data-bind` can also be used to bind an attribute of a node to a JavaScript property. Since attributes can't be observed for changes, this is a one way binding which will never update the JavaScript land property. Specify which attribute to bind using the "double dash" syntax like so: `data-bind-attribute="some.keypath"`. For example, to bind the `placeholder` attribute of an input, use `data-bind-placeholder`.

```html
<input type="text" data-bind-placeholder="'Specify a subtitle for product ' | append product.name">
```

_Note_: `data-bind` will not update a JavaScript property if filters are used in the keypath.

## data-source

`data-source` creates a one way binding which propagates only changes from JavaScript land to the DOM, and never vice versa. `data-source` has the same semantics with regards to how it operates on different tags as `data-bind`, but it will only ever update the DOM and never the JavaScript land property.

For example, the HTML below will never update the `title` property on the product, even if the user changes it. Each time the `title` attribute changes from a `set` in JavaScript land, the value of the input will be updated to the new value of `title`, erasing any potential changes that have been made to the value of the input by the user.

```html
<input type="text" data-source="product.title">
```

_Note_: `data-source-attribute` is equivalent to `data-bind-attribute`, since the former is defined as never making JS land changes, and the latter is unable to.

## data-target

`data-target` creates a one way binding which propagates only changes from the DOM to JavaScript land, and never vice versa. `data-target` has the same semantics with regards to how it operates on different tags as `data-bind`, but it will never update the DOM even if the JavaScript land value changes.

_Note_: `data-target-attribute` is unavailable, because DOM changes to node attributes can't be monitored.

## data-showif / data-hideif

`data-showif` and `data-hideif` bind to keypaths and show or hide the node they appear on based on the truthiness of the result. `data-showif` will show a node if the given keypath evaluates to something truthy, and `data-hideif` will leave a node visible until its given keypath becomes truthy, at which point the node will be hidden. `data-showif` and `data-hideif` show and hide nodes by adding `display: none !important;` to the node's `style` attribute.

For example, if the HTML below is rendered where the keypath `product.published` evaluated to true, the `<button>` will be visible.

```html
<button data-showif="product.published">Unpublish Product</button>
```

This is the Batman equivalent of a templating language's `if` construct, where else branches are implemented using the opposite binding.

```html
<button data-showif="product.published">Unpublish Product</button>
<button data-hideif="product.published">Publish Product</button>
```

## data-addclass / data-removeclass

`data-addclass` and `data-removeclass` bindings can be used to conditionally add or remove a class from a node based on a boolean keypath. Specify the class to add using the "double dash" syntax; for example,`data-addclass-big="some.keypath"` on a node will add the "big" class to that node's classes if `some.keypath` is truthy. `data-removeclass` will remove a class (usually one which is present in the HTML) if the keypath passed to it is truthy.

The outer span in the HTML below will have an "error" class when the `product.errors.length` keypath evaluates to anything other than 0, since 0 is falsy and other numbers are truthy.

```html
<p data-addclass-error="product.errors.length">
  This product has <span data-bind="product.errors.length"></span> errors.
</p>
```

## data-foreach

`data-foreach` is used to loop over an iterable object in Batman views. `data-foreach` duplicates the node it occurs on for each item in the collection found at the keypath given to it, and renders each duplicated node with that node's object from the collection by putting it in the context under a name passed to it using the "double dash" syntax.

The `<option>` node below will be duplicated for each item in the `Set` at the `products` keypath.

```html
<select>
  <option data-foreach-product="products" data-bind="product.name"></option>
</select>
```

Batman will execute the `data-foreach` binding before the `data-bind` on the `<option>` node, which means that the `data-bind` will be processed for each duplicated node with each separate Product in the `products` Set in scope for each separate node. If there were say 3 Products in the `products` set, the HTML would look similar to this once rendered:

```html
<select>
  <option data-bind="product.name">Product A</option>
  <option data-bind="product.name">Product B</option>
  <option data-bind="product.name">Product C</option>
  <!-- end products -->
</select>
```

`data-foreach` can be used to iterate over `Batman.Set`s, and most often should be, because it observes any Sets and will update the DOM with new nodes if items are added to the set, or remove nodes from the DOM if their corresponding nodes are removed from the set. `data-foreach`, like every other binding, is keypath aware, such that if the `Set` instance at the keypath changes, or any previous segment of the keypath changes, `data-foreach` will remove all the nodes currently in the DOM, and add new nodes for each new item in the incoming `Set`.

Sometimes you'll need to add some custom logic to the iteration nodes. For example, a custom `viewDidAppear` handler so you can know whenever a new iteration node appears in the DOM. You can do this by specifying a custom subclass of `Batman.IterationView`.

```html
<ul>
  <li data-foreach-product="products" data-view="ProductIterationView">
    <span data-bind="product.name"></span>
  </li>
</ul>
```

```coffeescript
class MyApp.ProductIterationView extends Batman.IterationView
  viewDidAppear: ->
    $(@get('node')).draggable()
```

_Note_: `data-foreach` expects to find an iterable object at the keypath given to it, and will emit a warning if it finds `undefined`.

_Note_: `data-foreach` expects the passed enumerable to be unique. It creates a map of nodes to items, so every node needs to be able to reference exactly one object. If you simply have a set of values that you're iterating over, you should wrap your values in objects, e.g. `[{value: true}, {value: true}]`.

## data-formfor

`data-formfor` creates a special addition to the context stack to represent an object under edit within a form. Usually this object is a model. Using the double dash syntax, the name for the model to reside under can be specified.

==== Automatic Validation Display

`data-formfor` also has some handy functionality for displaying the result of validating the object under edit in the form. This will only be enabled if the object has an `errors` Set, like `Batman.Models` do.

If a tag matching the relative selector `.errors` is found, it will populate this element with a list of the errors found during validation on the object. The selector for the errors container can be changed by adding a `data-errors-list` attribute with the value of the selector to the form with the `data-formfor` binding on it, or editing `Batman.DOM.FormBinding::defaultErrorsListSelector`.

If value bindings are made using `data-bind` to attributes on the model within the form, automatic `data-addclass-error` bindings will be added to the elements on which the `data-bind` occurs to add the "error" class when the model has errors on the attribute which `data-bind` binds to.

In the HTML below, an automatic `data-addclass-error` will be added to the `<input>` which activates when the `product` model has validation errors on the `name` attribute.

```html
<form data-formfor-product="currentProduct">
  <input type="text" data-bind="product.name"></input>
</form>
```

The class which gets automatically added to inputs binding to invalid attributes can be customized by editing `Batman.DOM.FormBinding::errorClass`.

## data-context

`data-context` bindings add the object found at the key to the context stack, optionally under a key using the double dash syntax.

For example, if a `product` object exists in the current context, the `data-context` binding below will expose its attributes at the root level of the context:

```html
<div data-context="product">
  <span data-bind="name"></span>
  <span data-bind="cost"></span>
</div>
```

Contexts added to the stack can also be scoped under a key using `data-context-`:

```html
<div data-context-currentProduct="product">
  <span data-bind="currentProduct"></span>
  <span data-bind="currentProduct"></span>
</div>
```

This is a useful mechanism for passing local variables to partial views.

## data-event

`data-event` bindings add DOM event listeners to the nodes they exist on which call the function found at the passed keypath. `data-event` bindings use the double dash syntax to specify the name of the event to listen for.

In the HTML below, if the keypath `controller.nextAction` resolves to a function, that function will be executed each time the `<button>` element is clicked.

```html
<button data-event-click="controller.nextAction"></button>
```

Functions which `data-event` calls will be passed the node and the `DOMEvent` object: `(node, event) ->`.

`data-event` supports the following types of events formally and should "do the right thing" when attached to elements which fire these events:

 + click
 + doubleclick
 + change
 + submit

If the event name used doesn't match the above events, the event name used will just fall through and be passed to `window.addEventListener`.

## data-route

`data-route` bindings are used to dispatch a new controller action upon the clicking of the node they bind to. `data-route` expects to find either a string or a `NamedRouteQuery` at the keypath passed to it. With this route, it will add an event handler to the `click` action of the element which dispatches the route and prevents the default action of the DOMEvent. `data-route` will also populate the `href` attribute if it occurs on an `<a>` tag so that other functons like "Copy Link Address" and Alt+Click continue to work on the link.

The first way to use `data-route` is by passing it a string, which can be built using filters or an accessor, but the preferred way is to use the `NamedRouteQuery`. These objects are generated for you by starting keypaths at the `App.routes` property. All `Batman.App`s have a `routes` property which holds a nested list of all the routes, which you descend into by passing various key segments and objects. Since the `App` object is present in the default context stack, `data-route` keypaths can just start with `routes`.

For example, assume the following routes definition in the current `Batman.App`:

```coffeescript
class Alfred extends Batman.App
  @resources 'todos'
```

This means that routes like `/todos` and `/todos/:id` exist. To route to the collection action, use the plural name of the resource:

```html
<a data-route="routes.todos"></a>
```

To route to an individual todo things get a bit more complicated. If we have a Todo model with ID# `42` in the context as `todo`, use the `get` filter shorthand on the `NamedRouteQuery` returned by `routes.todos` to generate a member route:

```html
<a data-route="routes.todos[todo]"></a>
```

Underneath, this is calling `Alfred.get('routes.todos').get(todo)`; the todo object is being passed as a key to the `NamedRouteQuery`, which knows how to generate a member route when given a record. The above HTML when rendered will look like this:

```html
<a data-route="routes.todos[todo]" href="/todos/42"></a>
```

This syntax can be extended to nested routes. If we have nested routes, we can use chained gets to generated nested routes

```coffeescript
class Tracker extends Batman.App
  @resources 'villains', ->
    @resources 'crimes'
```

Routes for collection and member crimes should look like `/villains/:villain_id/crimes` and `/villains/:villain_id/crimes/:id` respectively. Assuming the presence of a `villain` and a `crime` in the context, chained `get`s on `NamedRouteQuery`s achieve this:

```html
<!-- Collection of crimes for a particular villain -->
<a data-route="routes.villains[villain].crimes"></a>
<!-- One crime of a particular villain -->
<a data-route="routes.villains[villain].crimes[crime]"></a>
```

_Note_: `data-route` bindings route only to internal dispatch, and not external links. Use a regular `<a>` tag to link away from the application.

## data-view

`data-view` bindings attach custom `Batman.View` instances or instantiate custom `View` subclasses to / on a node. `data-view` expects either a `Batman.View` instance or subclass at the keypath passed to it. If an instance is passed, it will `set` the `node` property of the view to the node the `data-view` occurs on. If a class is passed, that class will be instantiated with the context the `data-view` binding executed in and with the node it occurred upon. See `Batman.View` for more information on custom Views and their uses.

_Note_: `data-view` bindings will bind to the passed keypath until it exists, that is to say until the value of it is not `undefined`. After the `View` has been set up, the `data-view` binding will remove itself and stop observing the keypath.

## data-partial

`data-partial` pulls in a partial template and renders it in the current context of the node the `data-partial` occurs in. `data-partial` expects the name of the view to render in the value of the HTML attribute. __Warning__: This value is not a keypath. The HTML attribute's value is interpreted as a string, and the template which resides at that view path will be rendered.

If we have this HTML at `views/villains/_stub.html` in our app:

```html
<span data-bind="villain.name"></span>
```

and in `views/villains/show.html` we have this HTML:

```html
<h1>A villain!</h1>
<div data-partial="villains/_stub"></div>
```

the contents of the `stub` partial will be inserted and rendered in the `<div>` above.

## data-mixin

## data-defineview

## data-renderif

`data-renderif` defers parsing of a node's child bindings until its keypath updates to true. `data-renderif` should generally be combined with a `data-showif` or `data-insertif` to prevent it from being visible until it is ready.

Deferring rendering can help prevent portions of the page updating many times while data is being loaded. It can also allow you to prevent features that are not yet ready from being used.

## data-yield

`data-yield` specifies that this node should be a render target for any view renderings that specify they should be rendered into a yield with this name. For example, `data-yield="myYieldNode"` can be rendered into by using `new Batman.View(contentFor: 'myYieldNode')`. The special case of `data-yield="main"` will be the render target for any view rendered by a controller action. This can mean the implicit render that happens by default at the end of a controller action or by explicitly calling `@render` inside a controller.

You can also specify a render target inside your HTML using `data-contentfor`.

```html
<div data-yield="main"></div>
```

## data-contentfor

`data-contentfor` specifies that the content of this node should be rendered into a `yield` with the corresponding name.

```html
<div data-contentfor="header"><h1 data-bind="title"></h1></div>
<div data-yield="header"></div>
```

# Batman.View Filters

## raw(value) : string

The `raw` filter renders the unescaped value.

```html
<span data-bind="someHTMLyString | raw"></span>
```

## get(value, key) : value

## value[key] : value

Shorthand for the `get` filter.

## equals(left, right) : boolean

## not(value) : boolean

## matches(value, string) : boolean

## truncate(value, length, end = '...') : string

## default(value, defaultValue) : value

## prepend(value, string) : string

## append(value, string) : string

## replace(value, searchString, replaceString[, flags]) : string

## downcase(value) : string

## upcase(value) : string

## pluralize(value, count) : string

## humanize(string) : string

## join(value, separator = '') : string

## sort(value) : value

## map(iterable) : value

## has(iterable, item) : boolean

## first(iterable) : value

## meta(value, keypath) : value

## interpolate(string, valuesObject) : string

## withArguments(function, curriedArguments...) : function

## routeToAction(model, action) : string

## escape(value) : string

# Batman.View Bindings

Batman's view bindings are how data gets shown and collected from the user. They center on the notion of "bindings": that the view representation and the JavaScript land value are always guaranteed to be in sync, such that when one changes, the other will reflect it.

## How to use bindings

Bindings are declared as attributes on nodes under the `data` namespace. In practice, it looks like this:

```html
<div data-bind="name"></div>
```

This instantiates a binding on the `div` node which will update the node's `innerHTML` with the value found at the `name` keypath in the current context. Whenever the `name` key changes, the div's `innerHTML` will update to the new value.

Nodes can have multiple bindings:

```html
<p data-bind="body" data-showif="isPublished"></p>
```

or attribute bindings:

```html
<p data-bind-id="currentID"></p>
```

and bindings can be on inputs which the user can change:

```html
<input type="text" data-bind="title"></input>
```

When the `title` property changes on the JavaScript object this `input` is bound to, the `input`'s value will be updated. When the user types into the `input` (and `change` or `keyup` events are triggered), the `title` property in JavaScript land will be updated.

## Binding Keypaths

A `keypath` is the value of the HTML attribute a binding references. Importantly, keypaths can have multiple segments:

```html
<p data-bind="order.customer.name"></p>
```

The keypath in the above HTML is `order.customer.name`. When you create a binding to a keypath like this (with dots separating segments), the binding will update the HTML value when _any_ of those segments change. In the above example, this means the `p` tag's `innerHTML` will be updated when:

 1. the order changes,
 2. the order's customer changes,
 3. or the order's customer's name changes.

This is important because it means you can rely on a binding to "just work" when anything it depends on changes. If say you had a `<select>` on the page which changed the `order`'s `customer` property, bindings which bind to `order.customer.name` will update each time you change that select to reflect the new customer's name.

## Binding Contexts

All bindings render in a context. Binding contexts, known internally to Batman as `RenderContext`s, are objects which emulate the notion of variable scope in JavaScript code. When a controller action renders, it passes a context to the view consisting of itself, the `App`, and an object with a `window` key pointing to the host `window` object.

## Keypath Filters

Bindings can bind to filtered keypaths:

```html
<p data-bind="post.body | truncate 100"></p>
```

The above `<p>` will have 100 characters worth of the post's body. Whenever the post's body changes, it will be retruncated and the `<p>`'s `innerHTML` will be updated.

Filter chains can be arbitrarily long:

```html
<span data-bind="knight.title | prepend 'Sir' | append ', the honourable'."></span>
```

and filter chains can use other keypaths as arguments to the filters:

```html
<span data-bind="person.name | prepend ' ' | prepend person.title"></span>
```

The above `<span>`'s `innerHTML` will be updated whenever the person's name or title changes.

#### Two Way Bindings and Filters

Note that filtered keypaths cannot propagate DOM land changes because values can't always be "unfiltered". For example, if we bind an input to the truncated version of a string:

```html
<input data-bind="post.body | truncate 100"></input>
```

The `<input>`'s value can be updated when the `post.body` property changes but if a user types into this input field, they will edit the truncated body. If Batman updated the `post.body` property with the contents of the input, all characters which had been truncated will be lost to the nether. To avoid this loss of information and inconsistency, bindings to filtered keypaths will _only update from JavaScript land to HTML_, and never vice versa.

## Keypath Literals

Keypaths also support a select few literals within them. Numbers, strings, and booleans can be passed as arguments to filters or used as the actual value of the keypath.

The following are all valid, albeit contrived, bindings:

```html
<!-- String literal used as an argument -->
<p data-bind="body | append ' ... '"></p>

<!-- Boolean literal used as an argument -->
<p data-showif="shouldShow | default true"></p>

<!-- Number literal used as an argument -->
<p data-bind="body | truncate 100"></p>

<!-- String literal used as the value -->
<p data-bind="'Hardcoded'"></p>

<!-- Boolean literal used as the value -->
<p data-showif="true"></p>
```

## data-bind

`data-bind` creates a two way binding between a property on a `Batman.Object` and an HTML element. Bindings created via `data-bind` will update the HTML element with the value of the JS land property as soon as they are created and each time the property changes after, and if the HTML element can be observed for changes, it will update the JS land property with the value from the HTML.

`data-bind` will change its behaviour depending on what kind of tag it is attached to:

 + `<input type="checkbox">`: the binding will edit the `checked` property of the checkbox and populate the keypath with a boolean.
 + `<input type="text">` and similar, `<textarea`>: the binding will edit the `value` property of the input and populate the keypath with the string found at `value`.
 + `<input type="file">`: the binding will _not_ edit the `value` property of the input, but it will update the keypath with a host `File` object or objects if the node has the `multiple` attribute.
 + `<select>`: the binding will edit the `selected` property of each `<option>` tag within the `<select>` matching the property at the keypath. If the `<select>` has the multiple attribute, the value at the keypath can be an array of selected `<option>` values. You can also use `data-bind-selected` bindings on the individual options to toggle option selectedness.
 + All other tags: the binding will edit the `innerHTML` property of the tag and will not populate the keypath.

`data-bind` can also be used to bind an attribute of a node to a JavaScript property. Since attributes can't be observed for changes, this is a one way binding which will never update the JavaScript land property. Specify which attribute to bind using the "double dash" syntax like so: `data-bind-attribute="some.keypath"`. For example, to bind the `placeholder` attribute of an input, use `data-bind-placeholder`.

```html
<input type="text" data-bind-placeholder="'Specify a subtitle for product ' | append product.name">
```

_Note_: `data-bind` will not update a JavaScript property if filters are used in the keypath.

## data-source

`data-source` creates a one way binding which propagates only changes from JavaScript land to the DOM, and never vice versa. `data-source` has the same semantics with regards to how it operates on different tags as `data-bind`, but it will only ever update the DOM and never the JavaScript land property.

For example, the HTML below will never update the `title` property on the product, even if the user changes it. Each time the `title` attribute changes from a `set` in JavaScript land, the value of the input will be updated to the new value of `title`, erasing any potential changes that have been made to the value of the input by the user.

```html
<input type="text" data-source="product.title">
```

_Note_: `data-source-attribute` is equivalent to `data-bind-attribute`, since the former is defined as never making JS land changes, and the latter is unable to.

## data-target

`data-target` creates a one way binding which propagates only changes from the DOM to JavaScript land, and never vice versa. `data-target` has the same semantics with regards to how it operates on different tags as `data-bind`, but it will never update the DOM even if the JavaScript land value changes.

_Note_: `data-target-attribute` is unavailable, because DOM changes to node attributes can't be monitored.

## data-showif / data-hideif

`data-showif` and `data-hideif` bind to keypaths and show or hide the node they appear on based on the truthiness of the result. `data-showif` will show a node if the given keypath evaluates to something truthy, and `data-hideif` will leave a node visible until its given keypath becomes truthy, at which point the node will be hidden. `data-showif` and `data-hideif` show and hide nodes by adding `display: none !important;` to the node's `style` attribute.

For example, if the HTML below is rendered where the keypath `product.published` evaluated to true, the `<button>` will be visible.

```html
<button data-showif="product.published">Unpublish Product</button>
```

This is the Batman equivalent of a templating language's `if` construct, where else branches are implemented using the opposite binding.

```html
<button data-showif="product.published">Unpublish Product</button>
<button data-hideif="product.published">Publish Product</button>
```

## data-addclass / data-removeclass

`data-addclass` and `data-removeclass` bindings can be used to conditionally add or remove a class from a node based on a boolean keypath. Specify the class to add using the "double dash" syntax; for example,`data-addclass-big="some.keypath"` on a node will add the "big" class to that node's classes if `some.keypath` is truthy. `data-removeclass` will remove a class (usually one which is present in the HTML) if the keypath passed to it is truthy.

The outer span in the HTML below will have an "error" class when the `product.errors.length` keypath evaluates to anything other than 0, since 0 is falsy and other numbers are truthy.

```html
<span data-addclass-error="product.errors.length">This product has <span data-bind="product.errors.length"></span> errors.</button>
```

## data-foreach

`data-foreach` is used to loop over an iterable object in Batman views. `data-foreach` duplicates the node it occurs on for each item in the collection found at the keypath given to it, and renders each duplicated node with that node's object from the collection by putting it in the context under a name passed to it using the "double dash" syntax.

The `<option>` node below will be duplicated for each item in the `Set` at the `products` keypath.

```html
<select>
  <option data-foreach-product="products" data-bind="product.name"></option>
</select>
```

Batman will execute the `data-foreach` binding before the `data-bind` on the `<option>` node, which means that the `data-bind` will be processed for each duplicated node with each separate Product in the `products` Set in scope for each separate node. If there were say 3 Products in the `products` set, the HTML would look similar to this once rendered:

```html
<select>
  <option data-bind="product.name">Product A</option>
  <option data-bind="product.name">Product B</option>
  <option data-bind="product.name">Product C</option>
  <!-- end products -->
</select>
```

`data-foreach` can be used to iterate over `Batman.Set`s, and most often should be, because it observes any Sets and will update the DOM with new nodes if items are added to the set, or remove nodes from the DOM if their corresponding nodes are removed from the set. `data-foreach`, like every other binding, is keypath aware, such that if the `Set` instance at the keypath changes, or any previous segment of the keypath changes, `data-foreach` will remove all the nodes currently in the DOM, and add new nodes for each new item in the incoming `Set`.

Sometimes you'll need to add some custom logic to the iteration nodes. For example, a custom `viewDidAppear` handler so you can know whenever a new iteration node appears in the DOM. You can do this by specifying a custom subclass of `Batman.IterationView`.

```html
<ul>
  <li data-foreach-product="products" data-view="ProductIterationView">
    <span data-bind="product.name"></span>
  </li>
</ul>
```

```coffeescript
class MyApp.ProductIterationView extends Batman.IterationView
  viewDidAppear: ->
    $(@get('node')).draggable()
```

_Note_: `data-foreach` expects to find an iterable object at the keypath given to it, and will emit a warning if it finds `undefined`.

_Note_: `data-foreach` expects the passed enumerable to be unique. It creates a map of nodes to items, so every node needs to be able to reference exactly one object. If you simply have a set of values that you're iterating over, you should wrap your values in objects, e.g. `[{value: true}, {value: true}]`.

## data-formfor

`data-formfor` creates a special addition to the context stack to represent an object under edit within a form. Usually this object is a model. Using the double dash syntax, the name for the model to reside under can be specified.

==== Automatic Validation Display

`data-formfor` also has some handy functionality for displaying the result of validating the object under edit in the form. This will only be enabled if the object has an `errors` Set, like `Batman.Models` do.

If a tag matching the relative selector `.errors` is found, it will populate this element with a list of the errors found during validation on the object. The selector for the errors container can be changed by adding a `data-errors-list` attribute with the value of the selector to the form with the `data-formfor` binding on it, or editing `Batman.DOM.FormBinding::defaultErrorsListSelector`.

If value bindings are made using `data-bind` to attributes on the model within the form, automatic `data-addclass-error` bindings will be added to the elements on which the `data-bind` occurs to add the "error" class when the model has errors on the attribute which `data-bind` binds to.

In the HTML below, an automatic `data-addclass-error` will be added to the `<input>` which activates when the `product` model has validation errors on the `name` attribute.

```html
<form data-formfor-product="currentProduct">
  <input type="text" data-bind="product.name"></input>
</form>
```

The class which gets automatically added to inputs binding to invalid attributes can be customized by editing `Batman.DOM.FormBinding::errorClass`.

## data-context

`data-context` bindings add the object found at the key to the context stack, optionally under a key using the double dash syntax.

For example, if a `product` object exists in the current context, the `data-context` binding below will expose its attributes at the root level of the context:

```html
<div data-context="product">
  <span data-bind="name"></span>
  <span data-bind="cost"></span>
</div>
```

Contexts added to the stack can also be scoped under a key using `data-context-`:

```html
<div data-context-currentProduct="product">
  <span data-bind="currentProduct"></span>
  <span data-bind="currentProduct"></span>
</div>
```

This is a useful mechanism for passing local variables to partial views.

## data-event

`data-event` bindings add DOM event listeners to the nodes they exist on which call the function found at the passed keypath. `data-event` bindings use the double dash syntax to specify the name of the event to listen for.

In the HTML below, if the keypath `controller.nextAction` resolves to a function, that function will be executed each time the `<button>` element is clicked.

```html
<button data-event-click="controller.nextAction"></button>
```

Functions which `data-event` calls will be passed the node and the `DOMEvent` object: `(node, event) ->`.

`data-event` supports the following types of events formally and should "do the right thing" when attached to elements which fire these events:

 + click
 + doubleclick
 + change
 + submit

If the event name used doesn't match the above events, the event name used will just fall through and be passed to `window.addEventListener`.

## data-route

`data-route` bindings are used to dispatch a new controller action upon the clicking of the node they bind to. `data-route` expects to find either a string or a `NamedRouteQuery` at the keypath passed to it. With this route, it will add an event handler to the `click` action of the element which dispatches the route and prevents the default action of the DOMEvent. `data-route` will also populate the `href` attribute if it occurs on an `<a>` tag so that other functons like "Copy Link Address" and Alt+Click continue to work on the link.

The first way to use `data-route` is by passing it a string, which can be built using filters or an accessor, but the preferred way is to use the `NamedRouteQuery`. These objects are generated for you by starting keypaths at the `App.routes` property. All `Batman.App`s have a `routes` property which holds a nested list of all the routes, which you descend into by passing various key segments and objects. Since the `App` object is present in the default context stack, `data-route` keypaths can just start with `routes`.

For example, assume the following routes definition in the current `Batman.App`:

```coffeescript
class Alfred extends Batman.App
  @resources 'todos'
```

This means that routes like `/todos` and `/todos/:id` exist. To route to the collection action, use the plural name of the resource:

```html
<a data-route="routes.todos"></a>
```

To route to an individual todo things get a bit more complicated. If we have a Todo model with ID# `42` in the context as `todo`, use the `get` filter shorthand on the `NamedRouteQuery` returned by `routes.todos` to generate a member route:

```html
<a data-route="routes.todos[todo]"></a>
```

Underneath, this is calling `Alfred.get('routes.todos').get(todo)`; the todo object is being passed as a key to the `NamedRouteQuery`, which knows how to generate a member route when given a record. The above HTML when rendered will look like this:

```html
<a data-route="routes.todos[todo]" href="/todos/42"></a>
```

This syntax can be extended to nested routes. If we have nested routes, we can use chained gets to generated nested routes

```coffeescript
class Tracker extends Batman.App
  @resources 'villains', ->
    @resources 'crimes'
```

Routes for collection and member crimes should look like `/villains/:villain_id/crimes` and `/villains/:villain_id/crimes/:id` respectively. Assuming the presence of a `villain` and a `crime` in the context, chained `get`s on `NamedRouteQuery`s achieve this:

```html
<!-- Collection of crimes for a particular villain -->
<a data-route="routes.villains[villain].crimes"></a>
<!-- One crime of a particular villain -->
<a data-route="routes.villains[villain].crimes[crime]"></a>
```

_Note_: `data-route` bindings route only to internal dispatch, and not external links. Use a regular `<a>` tag to link away from the application.

## data-view

`data-view` bindings attach custom `Batman.View` instances or instantiate custom `View` subclasses to / on a node. `data-view` expects either a `Batman.View` instance or subclass at the keypath passed to it. If an instance is passed, it will `set` the `node` property of the view to the node the `data-view` occurs on. If a class is passed, that class will be instantiated with the context the `data-view` binding executed in and with the node it occurred upon. See `Batman.View` for more information on custom Views and their uses.

_Note_: `data-view` bindings will bind to the passed keypath until it exists, that is to say until the value of it is not `undefined`. After the `View` has been set up, the `data-view` binding will remove itself and stop observing the keypath.

## data-partial

`data-partial` pulls in a partial template and renders it in the current context of the node the `data-partial` occurs in. `data-partial` expects the name of the view to render in the value of the HTML attribute. __Warning__: This value is not a keypath. The HTML attribute's value is interpreted as a string, and the template which resides at that view path will be rendered.

If we have this HTML at `views/villains/_stub.html` in our app:

```html
<span data-bind="villain.name"></span>
```

and in `views/villains/show.html` we have this HTML:

```html
<h1>A villain!</h1>
<div data-partial="villains/_stub"></div>
```

the contents of the `stub` partial will be inserted and rendered in the `<div>` above.

## data-mixin

## data-defineview

## data-renderif

`data-renderif` defers parsing of a node's child bindings until its keypath updates to true. `data-renderif` should generally be combined with a `data-showif` or `data-insertif` to prevent it from being visible until it is ready.

Deferring rendering can help prevent portions of the page updating many times while data is being loaded. It can also allow you to prevent features that are not yet ready from being used.

## data-yield

`data-yield` specifies that this node should be a render target for any view renderings that specify they should be rendered into a yield with this name. For example, `data-yield="myYieldNode"` can be rendered into by using `new Batman.View(contentFor: 'myYieldNode')`. The special case of `data-yield="main"` will be the render target for any view rendered by a controller action. This can mean the implicit render that happens by default at the end of a controller action or by explicitly calling `@render` inside a controller.

You can also specify a render target inside your HTML using `data-contentfor`.

```html
<div data-yield="main"></div>
```

## data-contentfor

`data-contentfor` specifies that the content of this node should be rendered into a `yield` with the corresponding name.

```html
<div data-contentfor="header"><h1 data-bind="title"></h1></div>
<div data-yield="header"></div>
```

# Batman.View Filters

## raw(value) : string

The `raw` filter renders the unescaped value.

```html
<span data-bind="someHTMLyString | raw"></span>
```

## get(value, key) : value

## value[key] : value

Shorthand for the `get` filter.

## equals(left, right) : boolean

## not(value) : boolean

## matches(value, string) : boolean

## truncate(value, length, end = '...') : string

## default(value, defaultValue) : value

## prepend(value, string) : string

## append(value, string) : string

## replace(value, searchString, replaceString[, flags]) : string

## downcase(value) : string

## upcase(value) : string

## pluralize(value, count) : string

## humanize(string) : string

## join(value, separator = '') : string

## sort(value) : value

## map(iterable) : value

## has(iterable, item) : boolean

## first(iterable) : value

## meta(value, keypath) : value

## interpolate(string, valuesObject) : string

## withArguments(function, curriedArguments...) : function

## routeToAction(model, action) : string

## escape(value) : string