style, content, Batman --> batman.js

style, content, Batman --> batman.js

# Batman.Model Associations
batman.js associations are modeled after [ActiveRecord Associations](http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html). There are 3 types of assocations available on `Batman.Model`: [`hasMany`](/docs/api/batman.model_associations.html#class_function_hasmany), [`belongsTo`](/docs/api/batman.model_associations.html#class_function_belongsto), and [`hasOne`](/docs/api/batman.model_associations.html#class_function_hasone). batman.js also supports polymorphic associations through the use of [polymorphic-specific options](/docs/api/batman.model_associations.html#polymorphic_association_options).

To add associations to your models, declare them in your model definition. Association functions take a label (string) and options (Object). The label names the association and is used to provide smart defaults for several options. All available options are [detailed below](/docs/api/batman.model_associations.html#association_options).

For example:

```coffeescript
class App.ParentItem extends Batman.Model
  @hasMany 'childItems', inverseOf: 'parentItem', encoderKey: 'children'

class App.ChildItem extends Batman.Model
  @belongsTo 'parentItem', inverseOf: 'childItem'
```

Then, associated records will be available via accessors:

```coffeescript
  parent = new App.ParentItem
  child = new App.ChildItem

  child.set('parentItem', parent)
  child.get('parentItem') # => parent
```

or,

```coffeescript
  parent = new App.ParentItem
  child = new App.ChildItem
  secondChild = new App.ChildItem
  parent.get('childItems').add(child)
  parent.get('childItems').add(secondChild)
  parent.get('childItems') # => Batman.AssociationSet
  parent.get('childItems.length') # => 2
```

## @hasMany(label : string [, options : Object])
`hasMany` expresses a one-to-many relationship on a `Batman.Model`.

## @hasOne(label : string [, options : Object])
`hasOne` expresses a one-to-one relationship on a `Batman.Model` when this model contains the primary key (eg, `id`) and does not contain the foreign key. If this model contains the foreign key, use `belongsTo` instead.

## @belongsTo(label : string [, options : Object])
`belongsTo` expresses a one-to-one relationship on a `Batman.Model` when this model contains the foreign key (eg, `parent_id`). If the other model contains the foreign key, use `hasOne` instead. It often expresses inverse of a `hasMany` or `hasOne` association. You can declare this with the `inverseOf` option (see [options](/docs/api/batman.model_associations.html#association_options) below) so that both sides of the association are loaded from JSON.

## Batman.AssocationProxy

Association accessors won't always return a `Batman.AssociationSet` or `Batman.Model`. Generally they will return a `Batman.AssocationProxy` named after the association type, such as `Batman.BelongsToAssociationProxy` or `Batman.HasOneAssociationProxy`.

## ::load(callback : Function)
Called to load the associated record from storage, setting it as  [`target`](/docs/api/batman.model_associations.html#prototype_accessor_target). If a callback is passed, it is called with two arguments: any error and the loaded record. Also, when this function finishes, it sets [`loaded`](/docs/api/batman.model_associations.html#prototype_accessor_loaded) to `true` and fires `loaded` on the record.

## ::toJSON() : Object
Returns a [stringifiable JavaScript object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify#toJSON_behavior) for the target record, if the [`target`](/docs/api/batman.model_associations.html#prototype_accessor_target) is present.

## ::%target
The associated record. Getting `target` does not implicitly call `load` on the association.

## ::%loaded
`true` or `false`, whether or not the record has been loaded from storage.

## ::fetchFromLocal()
This method is called by [`load`](/docs/api/batman.model_associations.html#prototype_function_load) to fetch the [`target`](/docs/api/batman.model_associations.html#prototype_accessor_target) record(s). If this method returns a falsy value, then [`fetchFromRemote`](/docs/api/batman.model_associations.html#prototype_function_fetchfromremote) is called.  `Batman.AssocationProxy` subclasses must implement this method.

## ::fetchFromRemote([callback : Function])
If [`fetchFromLocal`](/docs/api/batman.model_associations.html#prototype_function_fetchfromlocal) returns a falsy value, this method is called by [`load`](/docs/api/batman.model_associations.html#prototype_function_load) to fetch the [`target`](/docs/api/batman.model_associations.html#prototype_accessor_target) record(s). The `callback` is called with two arguments: any error and the fetched record(s). `Batman.AssocationProxy` subclasses must implement this method.

## Association Options

##### `primaryKey[= "id"] : string`
The primary key for the association.

##### `foreignKey[= "#{label}_id"] : string`
The foreign key for the association.

##### `saveInline[= true] : boolean`
If true, this model's attributes will be included in the associated model's JSON. This means that when an associated record is saved, this record's attributes will be included in the JSON.  (An alternative might be to include the associations' primary keys in the model's JSON with an [encoder](/docs/api/batman.model.html#class_function_encode).)

##### `autoload[= true] : boolean`
If `true`, batman.js will automatically call `load` when the associated records are accessed. This is useful in view bindings, where binding to the associated records will automatically cause them to be loaded.

##### `nestUrl[= false] : boolean`
If `true`, this model's URL will be nested under the associated model:

```coffeescript
class App.ChildItem extends Batman.Model
  @belongsTo 'parentItem', nestUrl: true

# ...

child = new ChildItem(parent_id: 1, id: 5)
child.url() # => 'parent_items/1/child_items/5'
```

`nestUrl` only applies if the model is persisted with `Batman.RestStorage` (or a subclass).

##### `name : string`
By default, batman.js checks for a model with the singular, camel-case name of association's `label` attached to `Batman.currentApp`. If the associated model's name is different from that, use `name` to specify it.

```coffeescript
class App.ChildItem extends Batman.Model
  @belongsTo 'parentItem' # automatically finds App.ParentItem
  @belongsTo 'alternativeParentItem', name: 'ParentItem' # also finds App.ParentItem
```

##### `inverseOf : string`
The foreign association to set on load. If the associated model has an association with the same name as the `inverseOf` value, it will be populated when data is loaded from storage. For example:

```coffeescript
class App.ParentItem extends Batman.Model
  @hasMany 'childItems', saveInline: true, inverseOf: 'parentItem'

class App.ChildItem extends Batman.Model
  @belongsTo 'parentItem', inverseOf: 'childItems'
```

would allow:

```coffeescript
App.ParentItem.find 1, (err, parent) ->
  children = parent.get('childItems')
  children.get('first.parentItem') == parent # => true

App.ChildItem.find 5, (err, childItem) ->
  childItem.get('parentItem').load (err, parent) ->
    parent.get('childItems').has(childItem) # => true
```

##### `encoderKey[= label] : string`
Key that represents this association's records when in serialized form. For example,

```coffeescript
class App.ParentItem extends Batman.Model
  @hasMany 'childItems', encoderKey: 'children'
```

will correctly decode this JSON:

```javascript
{id: 1, children: [{ id: 5, parent_id: 1 }, {id: 6, parent_id: 1}]}
```

It will also encode the `childItems` as `children` (unless `saveInline` is set to `false`).

##### `namespace[= Batman.currentApp] : string`
batman.js expects to find a model with the given `name` on `Batman.currentApp`. If your model is defined elsewhere, use `namespace` to specify where the model is defined.

```coffeescript
class App.Admin.Person extends Batman.Model
  @belongsTo 'organization', namespace: App.Admin # finds App.Admin.Organization instead of App.Organization
```

## Polymorphic Association Options
batman.js also supports [polymorphic associations](http://guides.rubyonrails.org/association_basics.html#polymorphic-associations). For example:

```coffeescript
class App.Superpower extends Batman.Model
  @encode 'name'
  @belongsTo 'superpowerable', polymorphic: true

class App.Hero extends Batman.Model
  @hasMany 'superpowers', as: 'superpowerable', polymorphic: true

class App.Villain extends Batman.Model
  @hasMany 'superpowers', as: 'superpowerable', polymorphic: true
```
By default, attributes of the polymorphic association will be encoded according to the label. So, `hero.toJSON()` might return:

```javascript
{ id: 1,
  name: 'Superman',
  superpowers: [
    {id: 15, superpowerable_id: 1, superpowerable_type: 'hero', name: 'Super Strength'},
    {id: 16, superpowerable_id: 1, superpowerable_type: 'hero', name: 'Invincibility'},
  ]
}
```

##### `polymorphic[= false] : boolean`
Set to `true` when the association is [polymorphic](http://guides.rubyonrails.org/association_basics.html#polymorphic-associations).

##### `as : string`
Specifies the name of the polymorphic interface.

##### `foreignTypeKey[= "#{label}_type"] : string`
Specifies the field which contains the `type` for a polymorphic record.

##### `encodeForeignTypeKey[=true] : boolean`
Set to `true` when the `foreignTypeKey` should be included in the JSON of the record.

# Batman.Model Associations
Batman associations are modeled after [ActiveRecord Associations](http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html). There are 3 types of assocations available on `Batman.Model`: [`hasMany`](/docs/api/batman.model_associations.html#class_function_hasmany), [`belongsTo`](/docs/api/batman.model_associations.html#class_function_belongsto), and [`hasOne`](/docs/api/batman.model_associations.html#class_function_hasone). Batman also supports polymorphic associations through the use of [polymorphic-specific options](/docs/api/batman.model_associations.html#polymorphic_association_options).

To add associations to your models, declare them in your model definition. Association functions take a label (string) and options (Object). The label names the association and is used to provide smart defaults for several options. All available options are [detailed below](/docs/api/batman.model_associations.html#association_options).

For example:

```coffeescript
class App.ParentItem extends Batman.Model
  @hasMany 'childItems', inverseOf: 'parentItem', encoderKey: 'children'

class App.ChildItem extends Batman.Model
  @belongsTo 'parentItem', inverseOf: 'childItem'
```

Then, associated records will be available via accessors:

```coffeescript
  parent = new App.ParentItem
  child = new App.ChildItem

  child.set('parentItem', parent)
  child.get('parentItem') # => parent
```

or,

```coffeescript
  parent = new App.ParentItem
  child = new App.ChildItem
  secondChild = new App.ChildItem
  parent.get('childItems').add(child)
  parent.get('childItems').add(secondChild)
  parent.get('childItems') # => Batman.AssociationSet
  parent.get('childItems.length') # => 2
```

## @hasMany(label : string [, options : Object])
`hasMany` expresses a one-to-many relationship on a `Batman.Model`.

## @hasOne(label : string [, options : Object])
`hasOne` expresses a one-to-one relationship on a `Batman.Model` when this model contains the primary key (eg, `id`) and does not contain the foreign key. If this model contains the foreign key, use `belongsTo` instead.

## @belongsTo(label : string [, options : Object])
`belongsTo` expresses a one-to-one relationship on a `Batman.Model` when this model contains the foreign key (eg, `parent_id`). If the other model contains the foreign key, use `hasOne` instead.

## Batman.AssocationProxy

Association accessors won't always return a `Batman.AssociationSet` or `Batman.Model`. Generally they will return a `Batman.AssocationProxy` named after the association type, such as `Batman.BelongsToAssociationProxy` or `Batman.HasOneAssociationProxy`.

## ::load(callback : Function)
Called to load the associated record from storage, setting it as  [`target`](/docs/api/batman.model_associations.html#prototype_accessor_target). If a callback is passed, it is called with two arguments: any error and the loaded record. Also, when this function finishes, it sets [`loaded`](/docs/api/batman.model_associations.html#prototype_accessor_loaded) to `true` and fires `loaded` on the record.

## ::toJSON() : Object
Returns JSON for the target record, if the [`target`](/docs/api/batman.model_associations.html#prototype_accessor_target) is present.

## ::%target
The associated record. Getting `target` does not implicitly call `load` on the association.

## ::%loaded
`true` or `false`, whether or not the record has been loaded from storage.

## ::fetchFromLocal()
This method is called by [`load`](/docs/api/batman.model_associations.html#prototype_function_load) to fetch the [`target`](/docs/api/batman.model_associations.html#prototype_accessor_target) record(s). If this method returns a falsy value, then [`fetchFromRemote`](/docs/api/batman.model_associations.html#prototype_function_fetchfromremote) is called.  `Batman.AssocationProxy` subclasses must implement this method.

## ::fetchFromRemote([callback : Function])
If [`fetchFromLocal`](/docs/api/batman.model_associations.html#prototype_function_fetchfromlocal) returns a falsy value, this method is called by [`load`](/docs/api/batman.model_associations.html#prototype_function_load) to fetch the [`target`](/docs/api/batman.model_associations.html#prototype_accessor_target) record(s). The `callback` is called with two arguments: any error and the fetched record(s). `Batman.AssocationProxy` subclasses must implement this method.

## Association Options

##### `primaryKey[= "id"] : string`
The primary key for the association.

##### `foreignKey[= "#{label}_id"] : string`
The foreign key for the association.

##### `saveInline[= true] : boolean`
If true, this model's attributes will be included in the associated model's JSON. This means that when an associated record is saved, this record's attributes will be included in the JSON.

##### `autoload[= true] : boolean`
If `true`, Batman will automatically call `load` when the associated records are accessed. This is useful in view bindings, where binding to the associated records will automatically cause them to be loaded.

##### `nestUrl[= false] : boolean`
If `true`, this model's URL will be nested under the associated model:

```coffeescript
class App.ChildItem extends Batman.Model
  @belongsTo 'parentItem', nestUrl: true

# ...

child = new ChildItem(parent_id: 1, id: 5)
child.url() # => 'parent_items/1/child_items/5'
```

`nestUrl` only applies if the model is persisted with `Batman.RestStorage` (or a subclass).

##### `name : string`
By default, Batman checks for a model with the singular, camel-case name of association's `label` attached to `Batman.currentApp`. If the associated model's name is different from that, use `name` to specify it.

```coffeescript
class App.ChildItem extends Batman.Model
  @belongsTo 'parentItem' # automatically finds App.ParentItem
  @belongsTo 'alternativeParentItem', name: 'ParentItem' # also finds App.ParentItem
```

##### `inverseOf : string`
The foreign association to set on load. If the associated model has an association with the same name as the `inverseOf` value, it will be populated when data is loaded from storage. For example:

```coffeescript
class App.ParentItem extends Batman.Model
  @hasMany 'childItems', saveInline: true, inverseOf: 'parentItem'

class App.ChildItem extends Batman.Model
  @belongsTo 'parentItem', inverseOf: 'childItems'
```

would allow:

```coffeescript
App.ParentItem.find 1, (err, parent) ->
  children = parent.get('childItems')
  children.get('first.parentItem') == parent # => true

App.ChildItem.find 5, (err, childItem) ->
  childItem.get('parentItem').load (err, parent) ->
    parent.get('childItems').has(childItem) # => true
```

##### `encoderKey[= label] : string`
Key where attributes for associated records will be found.

```coffeescript
class App.ParentItem extends Batman.Model
  @hasMany 'childItems', encoderKey: 'children'
```

will correctly decode this JSON:

```javascript
{id: 1, children: [{ id: 5, parent_id: 1 }, {id: 6, parent_id: 1}]}
```

It will also encode the `childItems` as `children` (unless `saveInline` is set to `false`).

##### `namespace[= Batman.currentApp] : string`
Batman expects to find a model with the given `name` on `Batman.currentApp`. If your model is defined elsewhere, use `namespace` to specify where the model is defined.

```coffeescript
class App.Admin.Person extends Batman.Model
  @belongsTo 'organization', namespace: App.Admin # finds App.Admin.Organization instead of App.Organization
```

## Polymorphic Association Options
Batman also supports [polymorphic associations](http://guides.rubyonrails.org/association_basics.html#polymorphic-associations). For example:

```coffeescript
class App.Superpower extends Batman.Model
  @encode 'name'
  @belongsTo 'superpowerable', polymorphic: true

class App.Hero extends Batman.Model
  @hasMany 'superpowers', as: 'superpowerable', polymorphic: true

class App.Villain extends Batman.Model
  @hasMany 'superpowers', as: 'superpowerable', polymorphic: true
```
By default, attributes of the polymorphic association will be encoded according to the label. So, `hero.toJSON()` might return:

```javascript
{ id: 1,
  name: 'Superman',
  superpowers: [
    {id: 15, superpowerable_id: 1, superpowerable_type: 'hero', name: 'Super Strength'},
    {id: 16, superpowerable_id: 1, superpowerable_type: 'hero', name: 'Invincibility'},
  ]
}
```

##### `polymorphic[= false] : boolean`
Whether the association is [polymorphic](http://guides.rubyonrails.org/association_basics.html#polymorphic-associations).

##### `as : string`
Specifies the name of the polymorphic interface.

##### `foreignTypeKey[= "#{label}_type"] : string`
Specifies the field which contains the `type` for a polymorphic record.

##### `encodeForeignTypeKey[=true] : boolean`
Specifies whether the `foreignTypeKey` should be included in the JSON of the record.


clean up

clean up

# Batman.Model Associations

There are 3 types of assocations available on `Batman.Model`: [`hasMany`](/docs/api/batman.model_associations.html#class_function_hasmany), [`belongsTo`](/docs/api/batman.model_associations.html#class_function_belongsto), and [`hasOne`](/docs/api/batman.model_associations.html#class_function_hasone). They're modeled after [ActiveRecord Associations](http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html). Batman also supports polymorphic associations through the use of [polymorphic-specific options](/docs/api/batman.model_associations.html#polymorphic_association_options).

To add associations to your models, declare them in your model definition. Association functions take a label (string) and options (Object). The label names the association and is used to provide smart defaults for several options. All available options are [detailed below](/docs/api/batman.model_associations.html#association_options).

For example:

```coffeescript
class App.ParentItem extends Batman.Model
  @hasMany 'childItems', inverseOf: 'parentItem', encoderKey: 'children'

class App.ChildItem extends Batman.Model
  @belongsTo 'parentItem', inverseOf: 'childItem'
```

Then, associated records will be available via accessors:

```coffeescript
  parent = new App.ParentItem
  child = new App.ChildItem

  child.set('parentItem', parent)
  child.get('parentItem') # => parent
```

or,

```coffeescript
  parent = new App.ParentItem
  child = new App.ChildItem
  secondChild = new App.ChildItem
  parent.get('childItems').add(child)
  parent.get('childItems').add(secondChild)
  parent.get('childItems') # => Batman.AssociationSet
  parent.get('childItems.length') # => 2
```

## @hasMany(label : string [, options : Object])
`hasMany` expresses a one-to-many relationship on a `Batman.Model`.

## @hasOne(label : string [, options : Object])
`hasOne` expresses a one-to-one relationship on a `Batman.Model` when this model contains the primary key (eg, `id`) and does not contain the foreign key. If this model contains the foreign key, use `belongsTo` instead.

## @belongsTo(label : string [, options : Object])
`belongsTo` expresses a one-to-one relationship on a `Batman.Model` when this model contains the foreign key (eg, `parent_id`). If the other model contains the foreign key, use `hasOne` instead.

## Batman.AssocationProxy

Association accessors won't always return a `Batman.AssociationSet` or `Batman.Model`. Generally they will return a `Batman.AssocationProxy` named after the association type, such as `Batman.BelongsToAssociationProxy` or `Batman.HasOneAssociationProxy`.

## ::load(callback : Function)
Called to load the associated record from storage, setting it as  [`target`](/docs/api/batman.model_associations.html#prototype_accessor_target). If a callback is passed, it is called with two arguments: any error and the loaded record. Also, when this function finishes, it sets [`loaded`](/docs/api/batman.model_associations.html#prototype_accessor_loaded) to `true` and fires `loaded` on the record.

## ::toJSON() : Object
Returns JSON for the target record, if the [`target`](/docs/api/batman.model_associations.html#prototype_accessor_target) is present.

## ::%target
The associated record. Getting `target` does not implicitly call `load` on the association.

## ::%loaded
`true` or `false`, whether or not the record has been loaded from storage.

## ::fetchFromLocal()
This method is called by [`load`](/docs/api/batman.model_associations.html#prototype_function_load) to fetch the [`target`](/docs/api/batman.model_associations.html#prototype_accessor_target) record(s). If this method returns a falsy value, then [`fetchFromRemote`](/docs/api/batman.model_associations.html#prototype_function_fetchfromremote) is called.  `Batman.AssocationProxy` subclasses must implement this method.

## ::fetchFromRemote([callback : Function])
If [`fetchFromLocal`](/docs/api/batman.model_associations.html#prototype_function_fetchfromlocal) returns a falsy value, this method is called by [`load`](/docs/api/batman.model_associations.html#prototype_function_load) to fetch the [`target`](/docs/api/batman.model_associations.html#prototype_accessor_target) record(s). The `callback` is called with two arguments: any error and the fetched record(s). `Batman.AssocationProxy` subclasses must implement this method.

## Association Options

##### `primaryKey[= "id"] : string`
The primary key for the association.

##### `foreignKey[= "#{label}_id"] : string`
The foreign key for the association.

##### `saveInline[= true] : boolean`
If true, this model's attributes will be included in the associated model's JSON. This means that when an associated record is saved, this record's attributes will be included in the JSON.

##### `autoload[= true] : boolean`
If `true`, Batman will automatically call `load` when the associated records are accessed. This is useful in view bindings, where binding to the associated records will automatically cause them to be loaded.

##### `nestUrl[= false] : boolean`
If `true`, this model's URL will be nested under the associated model:

```coffeescript
class App.ChildItem extends Batman.Model
  @belongsTo 'parentItem', nestUrl: true

# ...

child = new ChildItem(parent_id: 1, id: 5)
child.url() # => 'parent_items/1/child_items/5'
```

`nestUrl` only applies if the model is persisted with `Batman.RestStorage` (or a subclass).

##### `name : string`
By default, Batman checks for a model with the singular, camel-case name of association's `label` attached to `Batman.currentApp`. If the associated model's name is different from that, use `name` to specify it.

```coffeescript
class App.ChildItem extends Batman.Model
  @belongsTo 'parentItem' # automatically finds App.ParentItem
  @belongsTo 'alternativeParentItem', name: 'ParentItem' # also finds App.ParentItem
```

##### `inverseOf : string`
The foreign association to set on load. If the associated model has an association with the same name as the `inverseOf` value, it will be populated when data is loaded from storage. For example:

```coffeescript
class App.ParentItem extends Batman.Model
  @hasMany 'childItems', saveInline: true, inverseOf: 'parentItem'

class App.ChildItem extends Batman.Model
  @belongsTo 'parentItem', inverseOf: 'childItems'
```

would allow:

```coffeescript
App.ParentItem.find 1, (err, parent) ->
  children = parent.get('childItems')
  children.get('first.parentItem') == parent # => true

App.ChildItem.find 5, (err, childItem) ->
  childItem.get('parentItem').load (err, parent) ->
    parent.get('childItems').has(childItem) # => true
```

##### `encoderKey[= label] : string`
Key where attributes for associated records will be found.

```coffeescript
class App.ParentItem extends Batman.Model
  @hasMany 'childItems', encoderKey: 'children'
```

will correctly decode this JSON:

```javascript
{id: 1, children: [{ id: 5, parent_id: 1 }, {id: 6, parent_id: 1}]}
```

It will also encode the `childItems` as `children` (unless `saveInline` is set to `false`).

##### `namespace[= Batman.currentApp] : string`
Batman expects to find a model with the given `name` on `Batman.currentApp`. If your model is defined elsewhere, use `namespace` to specify where the model is defined.

```coffeescript
class App.Admin.Person extends Batman.Model
  @belongsTo 'organization', namespace: App.Admin # finds App.Admin.Organization instead of App.Organization
```

## Polymorphic Association Options
Batman also supports [polymorphic associations](http://guides.rubyonrails.org/association_basics.html#polymorphic-associations). For example:

```coffeescript
class App.Superpower extends Batman.Model
  @encode 'name'
  @belongsTo 'superpowerable', polymorphic: true

class App.Hero extends Batman.Model
  @hasMany 'superpowers', as: 'superpowerable', polymorphic: true

class App.Villain extends Batman.Model
  @hasMany 'superpowers', as: 'superpowerable', polymorphic: true
```
By default, attributes of the polymorphic association will be encoded according to the label. So, `hero.toJSON()` might return:

```javascript
{ id: 1,
  name: 'Superman',
  superpowers: [
    {id: 15, superpowerable_id: 1, superpowerable_type: 'hero', name: 'Super Strength'},
    {id: 16, superpowerable_id: 1, superpowerable_type: 'hero', name: 'Invincibility'},
  ]
}
```

##### `polymorphic[= false] : boolean`
Whether the association is [polymorphic](http://guides.rubyonrails.org/association_basics.html#polymorphic-associations).

##### `as : string`
Specifies the name of the polymorphic interface.

##### `foreignTypeKey[= "#{label}_type"] : string`
Specifies the field which contains the `type` for a polymorphic record.

##### `encodeForeignTypeKey[=true] : boolean`
Specifies whether the `foreignTypeKey` should be included in the JSON of the record.

# Batman.Model Associations

There are 3 types of assocations available on `Batman.Model`: [`hasMany`](/docs/api/batman.model_associations.html#class_function_hasmany), [`belongsTo`](/docs/api/batman.model_associations.html#class_function_belongsto), and [`hasOne`](/docs/api/batman.model_associations.html#class_function_hasone). They're modeled after [ActiveRecord Associations](http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html). Batman also supports polymorphic associations through the use of [polymorphic-specific options](/docs/api/batman.model_associations.html#polymorphic_association_options).

To add associations to your models, declare them in your model definition. Association functions take a label (string) and options (Object). The label names the association and is used to provide smart defaults for several options. All available options are [detailed below](/docs/api/batman.model_associations.html#association_options).

For example:

```coffeescript
class App.ParentItem extends Batman.Model
  @hasMany 'childItems', inverseOf: 'parentItem', encoderKey: 'children'

class App.ChildItem extends Batman.Model
  @belongsTo 'parentItem', inverseOf: 'childItem'
```

Then, associated records will be available via accessors:

```coffeescript
  parent = new App.ParentItem
  child = new App.ChildItem

  child.set('parentItem', parent)
  child.get('parentItem') # => parent
```

or,

```coffeescript
  parent = new App.ParentItem
  child = new App.ChildItem
  secondChild = new App.ChildItem
  parent.get('childItems').add(child)
  parent.get('childItems').add(secondChild)
  parent.get('childItems') # => Batman.AssociationSet
  parent.get('childItems.length') # => 2
```

## @hasMany(label : string [, options : Object])
`hasMany` expresses a one-to-many relationship on a `Batman.Model`.

## @hasOne(label : string [, options : Object])
`hasOne` expresses a one-to-one relationship on a `Batman.Model` when this model contains the primary key (eg, `id`) and does not contain the foreign key. If this model contains the foreign key, use `belongsTo` instead.

## @belongsTo(label : string [, options : Object])
`belongsTo` expresses a one-to-one relationship on a `Batman.Model` when this model contains the foreign key (eg, `parent_id`). If the other model contains the foreign key, use `hasOne` instead.

## Batman.AssocationProxy

Association accessors won't always return a `Batman.AssociationSet` or `Batman.Model`. Generally they will return a `Batman.AssocationProxy` named after the association type,
such as `Batman.BelongsToAssociationProxy` or `Batman.HasOneAssociationProxy`.

## ::load(callback : Function)
Called to load the associated record from storage, setting it as  [`target`](/docs/api/batman.model_associations.html#prototype_accessor_target). If a callback is passed, it is called with two arguments: any error and the loaded record. Also, when this function finishes, it sets [`loaded`](/docs/api/batman.model_associations.html#prototype_accessor_loaded) to `true` and fires `loaded` on the record.

## ::toJSON() : Object
Returns JSON for the target record, if the [`target`](/docs/api/batman.model_associations.html#prototype_accessor_target) is present.

## ::%target
The associated record. Getting `target` does not implicitly call `load` on the association.

## ::%loaded
`true` or `false`, Whether or not the record has been loaded from storage.

## ::fetchFromLocal() : Model
This method is called by [`load`](/docs/api/batman.model_associations.html#prototype_function_load) to fetch the [`target`](/docs/api/batman.model_associations.html#prototype_accessor_target) record. If this method returns a falsy value, then [`fetchFromRemote`](/docs/api/batman.model_associations.html#prototype_function_fetchfromremote) is called.  `Batman.AssocationProxy` subclasses must implement this method.

## ::fetchFromRemote() : Model
If [`fetchFromLocal`](/docs/api/batman.model_associations.html#prototype_function_fetchfromlocal) returns a falsy value, this method is called by [`load`](/docs/api/batman.model_associations.html#prototype_function_load) to fetch the [`target`](/docs/api/batman.model_associations.html#prototype_accessor_target) record. `Batman.AssocationProxy` subclasses must implement this method.

## Association Options
All assocations have a common set of options, as well as specific options for each type of relationship.

##### `primaryKey[= "id"] : string`
The primary key for the association.

##### `foreignKey[= "#{label}_id"] : string`
The foreign key for the association.

##### `saveInline[= true] : boolean`
If true, this model's attributes will be included in the associated model's JSON. This means that when an associated record is saved, this record's attributes will be included in the JSON.

##### `autoload[= true] : boolean`
If `true`, Batman will automatically call `load` when the associated records are accessed. This is useful in view bindings, where binding to the associated records will automatically cause them to be loaded.

##### `nestUrl[= false] : boolean`
If `true`, this model's URL will be nested under the associated model:

```coffeescript
class App.ChildItem extends Batman.Model
  @belongsTo 'parentItem', nestUrl: true

# ...

child = new ChildItem(parent_id: 1, id: 5)
child.url() # => 'parent_items/1/child_items/5'
```

`nestUrl` only applies if the model is persisted with `Batman.RestStorage` (or a subclass).

##### `name : string`
By default, Batman checks for a model with this singular, camel-case name of association's `label` attached to `Batman.currentApp`. If the associated model is different from that, use `name` (and/or `namespace` to specify it.

```coffeescript
class App.ChildItem extends Batman.Model
  @belongsTo 'parentItem' # automatically finds App.ParentItem
  @belongsTo 'alternativeParentItem', name: 'ParentItem' # also finds App.ParentItem
```

##### `inverseOf : string`
The foreign association to set on load. If the associated model has an association with the same name as the `inverseOf` value, it will be populated when data is loaded from storage. For example:

```coffeescript
class App.ParentItem extends Batman.Model
  @hasMany 'childItems', saveInline: true, inverseOf: 'parentItem'

class App.ChildItem extends Batman.Model
  @belongsTo 'parentItem', inverseOf: 'childItems'
```

would allow:

```coffeescript
App.ParentItem.find 1, (err, parent) ->
  children = parent.get('childItems')
  children.get('first.parentItem') == parent # => true

App.ChildItem.find 5, (err, childItem) ->
  childItem.get('parentItem').load (err, parent) ->
    parent.get('childItems').has(childItem) # => true
```

##### `encoderKey[= label] : string`
Key where attributes for associated records will be found.

```coffeescript
class App.ParentItem extends Batman.Model
  @hasMany 'childItems', encoderKey: 'children'
```

will correctly decode this JSON:

```javascript
{id: 1, children: [{ id: 5, parent_id: 1 }, {id: 6, parent_id: 1}]}
```

It will also encode the `childItems` as `children` (unless `saveInline` is set to `false`).

##### `namespace[= Batman.currentApp] : string`
Batman expects to find a model with the given `name` on `Batman.currentApp`. If your model is defined elsewhere, use `namespace` to specify where the model is defined.

```coffeescript
class App.Admin.Person extends Batman.Model
  @belongsTo 'organization', namespace: App.Admin # finds App.Admin.Organization instead of App.Organization
```

## Polymorphic Association Options
Batman also supports [polymorphic associations](http://guides.rubyonrails.org/association_basics.html#polymorphic-associations). For example:

```coffeescript
class App.Superpower extends Batman.Model
  @encode 'name'
  @belongsTo 'superpowerable', polymorphic: true

class App.Hero extends Batman.Model
  @hasMany 'superpowers', as: 'superpowerable', polymorphic: true

class App.Villain extends Batman.Model
  @hasMany 'superpowers', as: 'superpowerable', polymorphic: true
```
By default, attributes of the polymorphic association will be encoded according to the label. So, `hero.toJSON()` might return:

```javascript
{ id: 1,
  name: 'Superman',
  superpowers: [
    {id: 15, superpowerable_id: 1, superpowerable_type: 'hero', name: 'Super Strength'},
    {id: 16, superpowerable_id: 1, superpowerable_type: 'hero', name: 'Invincibility'},
  ]
}
```

##### `polymorphic[= false] : boolean`
Whether the association is [polymorphic](http://guides.rubyonrails.org/association_basics.html#polymorphic-associations).

##### `as : string`
Specifies the name of the polymorphic interface.

##### `foreignTypeKey[= "#{label}_type"] : string`
Specifies the field which contains the `type` for a polymorphic record.

##### `encodeForeignTypeKey[=true] : boolean`
Specifies whether the `foreignTypeKey` should be included in the JSON of the record.


Fix typos

Fix typos

# UBER and Hyperdescribe

The goal of this document is to outline how Hyperdescribe would be used to describe a UBER document according to the [current specs](https://rawgithub.com/mamund/media-types/e034e9d9eae7fb4455f25c928cb84cd513f9472c/uber-hypermedia.html). This document will look at the JSON variant of the UBER format.

    _ = require 'underscore'

    cleanItem = (data) ->
      _.reduce data, (total, value, key) ->
        total[key] = value if value? and value.length != 0
        total
      , {}

## Types

Even though UBER really only has one data element, `data`, this data element can be treated differently depending on the context. This section will look at each of these different types along with the conditions for those types and the means to describe them with Hyperdescribe.

### Transitions

In Hyperdescribe, there are two types of transitions:

1. Links
2. Actions

In the UBER spec, though, links and actions are not separated in this way, so this document will specify how it is determined whether an item is a link or an action.

#### Links

Items in UBER that are considered links in Hyperdescribe are items with `read` as the action. If the `@action` attribute is absent and the `@url` attribute is present, the action is assumed to be `read`. Additionally, if the action specified is not listed in the spec, it should be treated as `read`. This is according to the UBER spec.

For an item to be considered a link, it MUST have a `@url` attribute, it MUST NOT have any data, and it MUST be a `read` action.

    #getPropertyName = (data) ->
    #  if data.id? then id else data.name

    hasData = (data, level) ->
      data.data? and data.data?.length != 0

    isReadAction = (data) ->
      (!data.action? or
        data.action == 'read' or
        data.action not in _.keys(availableActions))

    isLink = (data, level) ->
      data.url? and !hasData(data, level) and isReadAction(data)

    mapLink = (data) ->
      linkUrl = if data.model? then data.url + data.model else data.url

      link =
        id: data.id
        name: data.name
        rel: data.rel
        #property: getPropertyName(data)
        transclude: data.transclude
        types: data.accepting
        label: data.value

      link.href = if data.model? then data.url + data.model else data.url
      link.template = true if data.model?

      link

#### Actions

UBER only specifies available actions and also provides a mapping of these actions to their corresponding HTTP verbs (see [section 4.1.1](https://rawgithub.com/mamund/media-types/master/uber-hypermedia.html#_mapping_uber_tt_action_tt_values_to_http_methods)).

    availableActions =
      append: 'POST'
      partial: 'PATCH'
      read: 'GET'
      remove: 'DELETE'
      replace: 'PUT'

Items that are considered actions MUST have an `@action` attribute, MUST have a `@url`, MAY have a `@model`, and MUST use an avaiable action from the spec.

    isAction = (data, level) ->
      data.action? and
        data.url? and
        data.action in _.keys(availableActions)

According to 4.1.1, there are only three actions that modify the body of the message sent:

* append
* partial
* replace

Since `read` actions are handled by links, `remove` is the only action that needs special treatment.

    modifiesBody = [
      'append'
      'partial'
      'replace'
    ]

    parseBodyModel = (model) ->
      items = model.split('&').map (item) ->
        [key, value] = item.split('=')
        { name: key, type: "text", mapsTo: value[1..-2] }

    mapAction = (data) ->
      action =
        name: data.name
        rel: data.rel
        method: availableActions[data.action]
        sendAs: data.sending

If an action is one that does not modify the body, the model is added to the action's `@url` attribute and template is set to `true`, which conveys it is templated action.

      if data.action not in modifiesBody and data.model?
        action.url = data.url + data.model
        action.template = true

If the action does modify the body, the model is parsed and fields are created.

      if data.action in modifiesBody
        action.url = data.url
        action.fields = parseBodyModel(data.model)
      cleanItem(action)

### Properties

An item that is considered a property of a resource MUST have a `@value`, MUST NOT be at the root level (or in other words, MUST be a child element), MUST NOT be a transition, and MUST NOT have a `@data` attribute.

    isTransition = (data, level) ->
      isLink(data, level) or isAction(data, level)

    isProperty = (data, level) ->
      data.value? and level != 0 and !isTransition(data, level) and !hasData(data, level)

Currently, with regards to mapping to Hyperdescribe, the only relevant values will be `@name` and `@value`.

    mapProperty = (data) ->
      cleanItem
        name: data.name
        value: data.value

### Resources

An item considered a resource MUST NOT have an `@action` attribute and MUST have a `@data` attribute. Like the `data` element in UBER, Hyperdescribe can handle nested resources.

    isResource = (data, level) ->
      !data.action? and hasData(data, level)

Mapping a resource from UBER to Hyperdescribe requires finding all of the links, actions, and properties, along with all nested resources. Once those are all found, they can then be mapped to how

    mapResource = (data, level) ->
      links = data.data.filter (d) -> isLink(d, level)
      actions = data.data.filter (d) -> isAction(d, level)
      resources = data.data.filter (d) -> isResource(d, level)
      properties = data.data.filter (d) -> isProperty(d, level)

      hLinks = links.map (link) -> mapLink(link)
      hActions = actions.map (action) -> mapAction(action)
      hResources = resources.map (resource) -> mapResource(resource, level + 1)
      hProperties = properties.map (property) -> mapProperty(property)

      cleanItem
        name: data.name
        links: hLinks
        actions: hActions
        resources: hResources
        properties: hProperties

## UBER Document

Mapping an UBER document to Hyperdescribe requires treating the root `@uber` element as a resource. Since each resource can have nested resources, Hyperdescribe should map each resource recursively.

    mapUberDocument = module.exports = (uber) -> mapResource(uber.uber, 0)

## Issues

1. There is currently no way to tell whether a nested link should be a property of the resource (e.g. the `avatarUrl` in the example in the spec) or just a normal link.
2. Is there any way to specify schema.org information for an UBER document?

# UBER and Hyperdescribe

The goal of this document is to outline how Hyperdescribe would be used to describe a UBER document according to the [current specs](https://rawgithub.com/mamund/media-types/e034e9d9eae7fb4455f25c928cb84cd513f9472c/uber-hypermedia.html). This document will look at the JSON variant of the UBER format.

    _ = require 'underscore'

    cleanItem = (data) ->
      _.reduce data, (total, value, key) ->
        total[key] = value if value? and value.length != 0
        total
      , {}

## Types

Even though UBER really only has one data element, `data`, this data element can be treated differently depending on the context. This section will look at each of these different types along with the conditions for those types and the means to describe them with Hyperdescribe.

### Transitions

In Hyperdescribe, there are two types of transitions:

1. Links
2. Actions

In the UBER spec, though, links and actions are not separated in this way, so this document will specify how it is determined whether an item is a link or an action.

#### Links

Items in UBER that are considered links in Hyperdescribe are items with `read` as the action. If the `@action` attribute is absent and the `@url` attribute is present, the action is assumed to be `read`. Additionally, if the action specified is not listed in the spec, it should be treated as `read`. This is according to the UBER spec.

For an item to be considered a link, it MUST have a `@url` attribute, it MUST NOT have any data, and it MUST be a `read` action.

    #getPropertyName = (data) ->
    #  if data.id? then id else data.name

    hasData = (data, level) ->
      data.data? and data.data?.length != 0

    isReadAction = (data) ->
      (!data.action? or
        data.action == 'read' or
        data.action not in _.keys(availableActions))

    isLink = (data, level) ->
      data.url? and !hasData(data, level) and isReadAction(data)

    mapLink = (data) ->
      linkUrl = if data.model? then data.url + data.model else data.url

      link =
        id: data.id
        name: data.name
        rel: data.rel
        #property: getPropertyName(data)
        transclude: data.transclude
        types: data.accepting
        label: data.value

      link.href = if data.model? then data.url + data.model else data.url
      link.template = true if data.model?

      link

#### Actions

UBER only specifies available actions and also provides a mapping of these actions to their corresponding HTTP verbs (see [section 4.1.1](https://rawgithub.com/mamund/media-types/master/uber-hypermedia.html#_mapping_uber_tt_action_tt_values_to_http_methods)).

    availableActions =
      append: 'POST'
      partial: 'PATCH'
      read: 'GET'
      remove: 'DELETE'
      replace: 'PUT'

Items that are considered actions MUST have an `@action` attribute, MUST have a `@url`, MAY have a `@model`, and MUST use an avaiable action from the spec.

    isAction = (data, level) ->
      data.action? and
        data.url? and
        data.action in _.keys(availableActions)

According to 4.1.1, there are only three actions that modify the body of the message sent:

* append
* partial
* replace

Since `read` actions are handled by links, `remove` is the only action that needs special treatment.

    modifiesBody = [
      'append'
      'partial'
      'replace'
    ]

    parseBodyModel = (model) ->
      items = model.split('&').map (item) ->
        [key, value] = item.split('=')
        { name: key, type: "text", mapsTo: value[1..-2] }

    mapAction = (data) ->
      action =
        name: data.name
        rel: data.rel
        method: availableActions[data.action]
        sendAs: data.sending

If an action is one that does not modify the body, the model is added to the action's `@url` attribute and template is set to `true`, which conveys it is templated action.

      if data.action not in modifiesBody and data.model?
        action.url = data.url + data.model
        action.template = true

If the action does modify the body, the model is parsed and fields are created. This will be treated as

      if data.action in modifiesBody
        action.url = data.url
        action.fields = parseBodyModel(data.model)
      cleanItem(action)

### Properties

An item that is considered a property of a resource MUST have a `@value`, MUST NOT be at the root level, MUST NOT be a transition, and MUST NOT have data.

    isTransition = (data, level) ->
      isLink(data, level) or isAction(data, level)

    isProperty = (data, level) ->
      data.value? and level != 0 and !isTransition(data, level) and !hasData(data, level)

Currently, with regards to mapping to Hyperdescribe, the only relevant values will be `@name` and `@value`.

    mapProperty = (data) ->
      cleanItem
        name: data.name
        value: data.value

### Resources

An item considered a resource MUST NOT have an `@action` attribute and MUST have a `@data` attribute. Like the `data` element in UBER, Hyperdescribe can handle nested resources.

    isResource = (data, level) ->
      !data.action? and hasData(data, level)

Mapping a resource from UBER to Hyperdescribe requires finding all of the links, actions, and properties, along with all nested resources. Once those are all found, they can then be mapped to how

    mapResource = (data, level) ->
      links = data.data.filter (d) -> isLink(d, level)
      actions = data.data.filter (d) -> isAction(d, level)
      resources = data.data.filter (d) -> isResource(d, level)
      properties = data.data.filter (d) -> isProperty(d, level)

      hLinks = links.map (link) -> mapLink(link)
      hActions = actions.map (action) -> mapAction(action)
      hResources = resources.map (resource) -> mapResource(resource, level + 1)
      hProperties = properties.map (property) -> mapProperty(property)

      cleanItem
        name: data.name
        links: hLinks
        actions: hActions
        resources: hResources
        properties: hProperties

## UBER Document

Mapping an UBER document to Hyperdescribe requires treating the root `@uber` element as a resource. Since each resource can have nested resources, Hyperdescribe should map each resource recursively.

    mapUberDocument = module.exports = (uber) -> mapResource(uber.uber, 0)

## Issues

1. There is currently no way to tell whether a nested link should be a property of the resource (e.g. the `avatarUrl` in the example in the spec) or just a normal link.
2. Is there any way to specify schema.org information for an UBER document?


Fix a comment

Fix a comment

Keyboard Input
==============

We first collect an event stream of all keyboard events sent to the
page.

    keyboardEvents = $(document).asEventStream('keydown')
                                .map('.keyCode')

We keep a map of keycodes to internal names.

    keyMap =
        48: 'view-0',
        49: 'view-1',
        50: 'view-2',
        51: 'view-3',
        52: 'view-4',
        53: 'view-5',
        54: 'view-6',
        55: 'view-7',
        56: 'view-8',
        57: 'view-9',
        75: 'kill', # k
        84: 'load-debug', # t

We then have a stream of keyboard events coming in based on that
map, discarding those that are not present as well as bounces.

    window.Keyboard = keyboardEvents.map( (k) -> keyMap[k] )
                                    .filter( (x) -> x? )
                                    .debounce(150)

Judge Selection
---------------

The keys 1-6 are used to select between display on the judge's desk.

We keep a property here to select between them.

    displayMap =
        'view-1': 'match-display'
        'view-2': 'match-sched'
        'view-3': 'league-state'
        'view-4': 'knockout-state'
        'view-5': 'next-match'
        'view-6': 'day-sched'

    window.JudgeSelection = window.Keyboard.map( (k) -> displayMap[k] )
                                           .filter( (x) -> x? )
                                           .toProperty('match-display')
                                           .skipDuplicates()

Keyboard Input
==============

We first collect an event stream of all keyboard events sent to the
page.

    keyboardEvents = $(document).asEventStream('keydown')
                                .map('.keyCode')

We keep a map of keycodes to internal names.

    keyMap =
        48: 'view-0',
        49: 'view-1',
        50: 'view-2',
        51: 'view-3',
        52: 'view-4',
        53: 'view-5',
        54: 'view-6',
        55: 'view-7',
        56: 'view-8',
        57: 'view-9',
        75: 'kill', # k
        84: 'load-debug', # t

We then have a stream of keyboard events coming in based on that
map, discarding those that are not present as well as bounces.

    window.Keyboard = keyboardEvents.map( (k) -> keyMap[k] )
                                    .filter( (x) -> x? )
                                    .debounce(150)

Judge Selection
---------------

The keys 1-4 are used to select between display on the judge's desk.

We keep a property here to select between them.

    displayMap =
        'view-1': 'match-display'
        'view-2': 'match-sched'
        'view-3': 'league-state'
        'view-4': 'knockout-state'
        'view-5': 'next-match'
        'view-6': 'day-sched'

    window.JudgeSelection = window.Keyboard.map( (k) -> displayMap[k] )
                                           .filter( (x) -> x? )
                                           .toProperty('match-display')
                                           .skipDuplicates()


Improve documentation such that it shows properly on GitHub

heterarchy
==========

Adds multiple inheritance support to CoffeeScript (and JavaScript).
It uses the C3 linearization algorithm as described in the [famous
Dylan paper](http://192.220.96.201/dylan/linearization-oopsla96.html).

    {head, tail, map, find, some, without, isEmpty, every, memoize, reject,
     partial, isEqual} =
        require 'underscore'

    assert = (value, error=undefined) ->
        if not value
           throw new Error(if error? then error else "Assertion failed")

Multiple inheritance
--------------------

The **multi** function takes a list of classes and returns a *special*
class object that merges the class hierarchies, as linearized by the
C3 algorithm. Limitations of the approach are:

- `instanceof` does not always work as expected. For example:

  > ```coffee
  > class A
  > class B extends A
  > class C extends A
  > class D extends multi B, C
  > assert new D not instanceof B
  > ```

  Instead, one should use the provided `isinstance` function.

- Some of the bases of a multi-inherited hierarchy are *frozen* when
  the sub-class is defined -- i.e. later modifications to the
  superclass are not visible to the subclass or its instances.  For
  example, in the previous heterarchy:

  > ```coffee
  > B::newProperty = 42
  > assert D::newProperty == undefined
  > ```

The `multi` function memoizes its results such that identity is
maintained, implying `multi X, Y is multi X, Y`.

    exports.multi = (bases...) ->
        generate merge map(bases, mro).concat [bases]

This takes a list of classes representing a hierarchy (from most to
least derived) and generates a single-inheritance hierarchy that
behaves like a class that would be have such a hierarchy.

    generate = memoize (linearization) ->
        next = head linearization
        if isEqual linearization, hierarchy next
            next
        else
            class result extends generate tail linearization
                __mro__: linearization
                constructor: reparent next, @, next::constructor
                copyOwn next, @
                copyOwn next::, @::, partial reparent, next, @

This utility lets us copy own properties of a *from* object that are
not own properties of a *to* object into the *to* object, optionally
transformed via a projection function.

    copyOwn = (from, to, project = (x) -> x) ->
        for own key, value of from
            if not to.hasOwnProperty key
                to[key] = project value
        to

Methods in CoffeeScript call super directly, so we have to change the
`__super__` attribute of the original class during the scope of the
method so it calls the right super of the linearization.  Also,
programmers don't call super in constructor of root classes --indeed
doing so would rise an error-- so we have to inject such a call when
there are classes after these in the linearization.  The **reparent**
function takes care of all these and given an original class, and the
new class that is replacing it a linearized heterarchy, returns a
wrapped copy of a value of the former that is suitable for replacing
it in the later.

    reparent = (oldklass, newklass, value) ->
        if value not instanceof Function
            value
        else if value == oldklass::constructor and inherited(oldklass) == Object
            superctor = inherited(newklass)::constructor
            ->
                superctor.apply @, arguments
                value.apply @, arguments
        else
            newsuper = inherited(newklass)::
            oldsuper = oldklass.__super__
            ->
                oldklass.__super__ = newsuper
                try
                    value.apply @, arguments
                finally
                    oldklass.__super__ = oldsuper

This is the C3 linearization algorithm, as translated from the
original paper.

    merge = (inputs) ->
        while not isEmpty inputs
            next = find (map inputs, head), (candidate) ->
                every inputs, (input) -> candidate not in tail input
            assert next?, "Inconsistent multiple inheritance"
            inputs = reject map(inputs, (lst) -> without lst, next), isEmpty
            next

Introspection
-------------

The **mro** function returns the method resolution order
(linearization) of a given class:

> ```coffee
> class A
> class B extends A
> class C extends B
> assert mro(C).equals [C, B, A]
> ```

It returns the original classes that were mixed in when used with
mult-inherited classes:

> ```coffee
> class A
> class B extends A
> class C extends A
> class D extends multi B, C
> assert mro(D).equals [D, B, C, A, Object]
> ```

    exports.mro = mro = (cls) ->
        if not cls? or not cls::?
            []
        else if not cls::hasOwnProperty '__mro__'
            cls::__mro__ = [cls].concat mro inherited(cls)
        else
            cls::__mro__

The **inherited** function returns the CoffeeScript superclass of an
object, for example:

> ```coffee
> class A
> class B extends A
> assert inherited(B) == A
> ```

Note that for multiple inherited classes, this returns the mixed
object, not the next class in the MRO, as in:

> ```coffee
> class C extends multi A, B
> assert inherited(C) == multi(A, B)
> ```

    exports.inherited = inherited = (cls) ->
        Object.getPrototypeOf(cls.prototype)?.constructor

The **hierarchy** returns the CoffeeScript hierarchy of classes of a
given class, including the class itself.  For multiple inherited
classes, it may return speciall classes that were generated to produce
the flattening, as in:

> ```coffee
> class A
> class B extends A
> class C extends A
> class D extends multi B, C
> assert not mro(D).equals hierarchy(D)
> assert hierarchy(D).equals
>     [ D, multi(B, C), inherited(multi B, C), A, Object ]
> ```

    exports.hierarchy = hierarchy = (cls) ->
        if not cls?
            []
        else
            [cls].concat hierarchy inherited cls

The **isinstance** function takes an object and a class or classes and
returns whether the object is an instance of any of those classes. It
is compatible with multi-inherited classes.

    exports.isinstance = (obj, classes...) ->
        exports.issubclass obj?.constructor, classes...

The **issubclass** tells whether a class is a subtype of another type.

    exports.issubclass = (klass, classes...) ->
        linearization = mro klass
        some classes, (cls) -> cls in linearization

License
-------

> Copyright (c) 2013, 2015 Juan Pedro Bolivar Puente <raskolnikov@gnu.org>
>
> Permission is hereby granted, free of charge, to any person obtaining a copy
> of this software and associated documentation files (the "Software"), to deal
> in the Software without restriction, including without limitation the rights
> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
> copies of the Software, and to permit persons to whom the Software is
> furnished to do so, subject to the following conditions:
>
> The above copyright notice and this permission notice shall be included in
> all copies or substantial portions of the Software.
>
> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
> THE SOFTWARE.

heterarchy
==========

Adds multiple inheritance support to CoffeeScript (and JavaScript).
It uses the C3 linearization algorithm as described in the [famous
Dylan paper](http://192.220.96.201/dylan/linearization-oopsla96.html).

    {head, tail, map, find, some, without, isEmpty, every, memoize, reject,
     partial, isEqual} =
        require 'underscore'

    assert = (value, error=undefined) ->
        if not value
           throw new Error(if error? then error else "Assertion failed")

Multiple inheritance
--------------------

The **multi** function takes a list of classes and returns a *special*
class object that merges the class hierarchies, as linearized by the
C3 algorithm. Limitations of the approach are:

- `instanceof` does not always work as expected. For example:

  > class A
  > class B extends A
  > class C extends A
  > class D extends multi B, C
  > assert new D not instanceof B

  Instead, one should use the provided `isinstance` function.

- Some of the bases of a multi-inherited hierarchy are *frozen* when
  the sub-class is defined -- i.e. later modifications to the
  superclass are not visible to the subclass or its instances.  For
  example, in the previous heterarchy:

  > B::newProperty = 42
  > assert D::newProperty == undefined

    exports.multi = (bases...) ->
        generate merge map(bases, mro).concat [bases]

This takes a list of classes representing a hierarchy (from most to
least derived) and generates a single-inheritance hierarchy that
behaves like a class that would be have such a hierarchy.

    generate = memoize (linearization) ->
        next = head linearization
        if isEqual linearization, hierarchy next
            next
        else
            class result extends generate tail linearization
                __mro__: linearization
                constructor: reparent next, @, next::constructor
                copyOwn next, @
                copyOwn next::, @::, partial reparent, next, @

This utility lets us copy own properties of a *from* object that are
not own properties of a *to* object into the *to* object, optionally
transformed via a projection function.

    copyOwn = (from, to, project = (x) -> x) ->
        for own key, value of from
            if not to.hasOwnProperty key
                to[key] = project value
        to

Methods in CoffeeScript call super directly, so we have to change the
`__super__` attribute of the original class during the scope of the
method so it calls the right super of the linearization.  Also,
programmers don't call super in constructor of root classes --indeed
doing so would rise an error-- so we have to inject such a call when
there are classes after these in the linearization.  The **reparent**
function takes care of all these and given an original class, and the
new class that is replacing it a linearized heterarchy, returns a
wrapped copy of a value of the former that is suitable for replacing
it in the later.

    reparent = (oldklass, newklass, value) ->
        if value not instanceof Function
            value
        else if value == oldklass::constructor and inherited(oldklass) == Object
            superctor = inherited(newklass)::constructor
            ->
                superctor.apply @, arguments
                value.apply @, arguments
        else
            newsuper = inherited(newklass)::
            oldsuper = oldklass.__super__
            ->
                oldklass.__super__ = newsuper
                try
                    value.apply @, arguments
                finally
                    oldklass.__super__ = oldsuper

This is the C3 linearization algorithm, as translated from the
original paper.

    merge = (inputs) ->
        while not isEmpty inputs
            next = find (map inputs, head), (candidate) ->
                every inputs, (input) -> candidate not in tail input
            assert next?, "Inconsistent multiple inheritance"
            inputs = reject map(inputs, (lst) -> without lst, next), isEmpty
            next

Introspection
-------------

The **mro** function returns the method resolution order
(linearization) of a given class:

> class A
> class B extends A
> class C extends B
> assert mro(C).equals [C, B, A]

It returns the original classes that were mixed in when used with
mult-inherited classes:

> class A
> class B extends A
> class C extends A
> class D extends multi B, C
> assert mro(D).equals [D, B, C, A, Object]

    exports.mro = mro = (cls) ->
        if not cls? or not cls::?
            []
        else if not cls::hasOwnProperty '__mro__'
            cls::__mro__ = [cls].concat mro inherited(cls)
        else
            cls::__mro__

The **inherited** function returns the CoffeeScript superclass of an
object, for example:

> class A
> class B extends A
> assert inherited(B) == A

Note that for multiple inherited classes, this returns the mixed
object, not the next class in the MRO, as in:

> class C extends multi A, B
> assert inherited(C) == multi(A, B)

    exports.inherited = inherited = (cls) ->
        Object.getPrototypeOf(cls.prototype)?.constructor

The **hierarchy** returns the CoffeeScript hierarchy of classes of a
given class, including the class itself.  For multiple inherited
classes, it may return speciall classes that were generated to produce
the flattening, as in:

> class A
> class B extends A
> class C extends A
> class D extends multi B, C
> assert not mro(D).equals hierarchy(D)
> assert hierarchy(D).equals
>     [ D, multi(B, C), inherited(multi B, C), A, Object ]

    exports.hierarchy = hierarchy = (cls) ->
        if not cls?
            []
        else
            [cls].concat hierarchy inherited cls

The **isinstance** function takes an object and a class or classes and
returns whether the object is an instance of any of those classes. It
is compatible with multi-inherited classes.

    exports.isinstance = (obj, classes...) ->
        exports.issubclass obj?.constructor, classes...

The **issubclass** tells whether a class is a subtype of another type.

    exports.issubclass = (klass, classes...) ->
        linearization = mro klass
        some classes, (cls) -> cls in linearization

License
-------

> Copyright (c) 2013, 2015 Juan Pedro Bolivar Puente <raskolnikov@gnu.org>
>
> Permission is hereby granted, free of charge, to any person obtaining a copy
> of this software and associated documentation files (the "Software"), to deal
> in the Software without restriction, including without limitation the rights
> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
> copies of the Software, and to permit persons to whom the Software is
> furnished to do so, subject to the following conditions:
>
> The above copyright notice and this permission notice shall be included in
> all copies or substantial portions of the Software.
>
> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
> THE SOFTWARE.


improved helpers

improved helpers

List of SVG elements

    Tags =
     svg: 'a altGlyph altGlyphDef altGlyphItem animate animateColor
      animateMotion animateTransform circle clipPath color-profile cursor
      defs desc ellipse feBlend feColorMatrix feComponentTransfer
      feComposite feConvolveMatrix feDiffuseLighting feDisplacementMap
      feDistantLight feFlood feFuncA feFuncB feFuncG feFuncR feGaussianBlur
      feImage feMerge feMergeNode feMorphology feOffset fePointLight
      feSpecularLighting feSpotLight feTile feTurbulence
      filter font font-face font-face-format font-face-name font-face-src
      font-face-uri foreignObject g glyph glyphRef hkern image line
      linearGradient marker mask metadata missing-glyph mpath path pattern
      polygon polyline radialGradient rect script set stop style svg symbol
      text textPath title tref tspan use view vkern switch foreignObject'

List of HTML elements

     html: 'a abbr address article aside audio b bdi bdo blockquote body button
      canvas caption cite code colgroup datalist dd del details dfn div dl dt
      em fieldset figcaption figure footer form h1 h2 h3 h4 h5 h6 head header
      hgroup html i iframe ins kbd label legend li main map mark menu meter
      nav noscript object ol optgroup option output p pre progress q rp rt
      ruby s samp script section select small span strong style sub summary
      sup table tbody td textarea tfoot th thead time title tr u ul video'

     htmlVoid: 'area base br col command embed hr img input keygen link meta
      param source track wbr'

Wrapper for browser API

    Api =
     document: @document

Parse id and class string

    parseIdClass = (str) ->
     res =
      id: null
      class: []

     for c, i in str.split "."
      if c.indexOf("#") is 0
       res.id = c.substr 1
      else if c isnt ""
       if not res.class?
        res.class = [c]
       else
        res.class.push c

     return res

    getParameters = (args) ->
     params =
      idClass: null
      text: null
      attrs: null
      func: null

     for arg, i in args
      switch typeof arg
       when 'function' then params.func = arg
       when 'object' then params.attrs = arg
       when 'string'
        if args.length is 1
         params.text = arg
        else
         c = arg.charAt 0

         if i is 0 and (c is '#' or c is '.')
          params.idClass = parseIdClass arg
         else
          params.text = arg

     return params

#Weya DOM

    weyaDomCreate = ->

Weya object to be passed as `this`

     weya =
      _elem: null

Manipulating dom objects

     setStyles = (elem, styles) ->
      for k, v of styles
       if v?
        elem.style.setProperty k, v
       else
        elem.style.removeProperty k

     setEvents = (elem, events) ->
      for k, v of events
       elem.addEventListener k, v, false

     setAttributes = (elem, attrs) ->
      for k, v of attrs
       switch k
        when 'style' then setStyles elem, v
        when 'on' then setEvents elem, v
        else
         if v?
          elem.setAttribute k, v
         else
          elem.removeAttribute k

     setIdClass = (elem, idClass) ->
      if idClass.id?
       elem.id = idClass.id

      if idClass.class?
       if elem.classList?
        for c in idClass.class
         elem.classList.add c
       else #For older browsers; does not work with svgs
        className = ''
        for c in idClass.class
         className += ' ' if className isnt ''
         className += "#{c}"
        elem.className = className

Append a child element

     append = (ns, name, args) ->
      params = getParameters args

Keep a reference to parent element

      pElem = @_elem

Keep a reference of `elem` to return at the end of the function

      if ns?
       elem = @_elem = Api.document.createElementNS ns, name
      else
       elem = @_elem = Api.document.createElement name

      if params.idClass?
       setIdClass elem, params.idClass

      if params.attrs?
       setAttributes elem, params.attrs

      if pElem?
       pElem.appendChild elem

      if params.func?
       params.func.call this
      else if params.text?
       elem.textContent = params.text

      @_elem = pElem
      return elem

Wrap `append`

     wrapAppend = (ns, name) ->
      ->
       append.call this, ns, name, arguments

Initialize

     for name in Tags.svg.split ' '
      weya[name] = wrapAppend "http://www.w3.org/2000/svg", name

     for name in Tags.html.split ' '
      weya[name] = wrapAppend "http://www.w3.org/1999/xhtml", name

     for name in Tags.htmlVoid.split ' '
      weya[name] = wrapAppend null, name

     return weya

#Weya Markup

    weyaMarkupCreate = ->

Weya object to be passed as `this`

     weya =
      _buf: null
      _indent: 0

Render components

     setStyles = (buf, styles) ->
      buf.push " style=\""
      for k, v of styles
       buf.push "#{k}:#{v};"
      buf.push "\""

     setEvents = (buf, events) ->
      for k, v of events
       buf.push " on#{k}=\"#{v}\""

     setAttributes = (buf, attrs) ->
      for k, v of attrs
       switch k
        when 'style' then setStyles buf, v
        when 'on' then setEvents buf, v
        else
         buf.push " #{k}=\"#{v}\""

     setIndent = (buf, indent) ->
      for i in [0...indent]
       buf.push " "

Append a child element

     append = (ns, name, args) ->
      params = getParameters args

      buf = @_buf

      setIndent buf, @_indent

      buf.push "<#{name}"

      if params.idClass?
       if params.idClass.id?
        buf.push " id=\"#{params.idClass.id}\""
       if params.idClass.class?
        buf.push " class=\"#{params.idClass.class}\""

      if params.attrs?
       setAttributes buf, params.attrs

Can close void elements (element that self close) with a `/>`

      buf.push ">\n"
      @_indent++

      if params.func?
       params.func.call this
      else if params.text?
       setIndent buf, @_indent
       buf.push params.text
       buf.push "\n"

      @_indent--
      setIndent buf, @_indent
      buf.push "</#{name}>\n"

Wrap `append`

     wrapAppend = (ns, name) ->
      ->
       append.call this, ns, name, arguments

Initialize

     for name in Tags.svg.split ' '
      weya[name] = wrapAppend "http://www.w3.org/2000/svg", name

     for name in Tags.html.split ' '
      weya[name] = wrapAppend null, name

     for name in Tags.htmlVoid.split ' '
      weya[name] = wrapAppend null, name

     return weya

#Weya API

    weyaDom = weyaDomCreate()
    weyaMarkup = weyaMarkupCreate()

Create and append to `options.elem`. If `options.context` is provied it can be
accessed via `@$`. If `options.elem` is `null`, the element is created but
not appended.

    @Weya = Weya = (options, func) ->
     weya = weyaDom
     pContext = weya.$
     weya.$ = options.context
     helpersAdded = []

     if options.helpers?
      for name, func of options.helpers
       if not weya[name]?
        added.push name
        weya[name] = func.bind weya

     pElem = weya._elem
     weya._elem = options.elem
     r = func?.call weya
     weya._elem = pElem
     weya.$ = pContext

     for name in helpersAdded
      delete weya[name]

     return r

    Weya.markup = (options, func) ->
     weya = weyaMarkup
     pContext = weya.$
     weya.$ = options.context
     helpersAdded = []

     if options.helpers?
      for name, func of options.helpers
       if not weya[name]?
        added.push name
        weya[name] = func.bind weya

     pBuf = weya._buf
     weya._buf = []
     r = func?.call weya
     buf = weya._buf
     weya._buf = pBuf
     weya.$ = pContext

     for name in helpersAdded
      delete weya[name]

     return buf.join ''

    Weya.setApi = (api) ->
     for k, v of api
      Api[k] = v

    if module?
     module.exports = Weya

List of SVG elements

    Tags =
     svg: 'a altGlyph altGlyphDef altGlyphItem animate animateColor
      animateMotion animateTransform circle clipPath color-profile cursor
      defs desc ellipse feBlend feColorMatrix feComponentTransfer
      feComposite feConvolveMatrix feDiffuseLighting feDisplacementMap
      feDistantLight feFlood feFuncA feFuncB feFuncG feFuncR feGaussianBlur
      feImage feMerge feMergeNode feMorphology feOffset fePointLight
      feSpecularLighting feSpotLight feTile feTurbulence
      filter font font-face font-face-format font-face-name font-face-src
      font-face-uri foreignObject g glyph glyphRef hkern image line
      linearGradient marker mask metadata missing-glyph mpath path pattern
      polygon polyline radialGradient rect script set stop style svg symbol
      text textPath title tref tspan use view vkern switch foreignObject'

List of HTML elements

     html: 'a abbr address article aside audio b bdi bdo blockquote body button
      canvas caption cite code colgroup datalist dd del details dfn div dl dt
      em fieldset figcaption figure footer form h1 h2 h3 h4 h5 h6 head header
      hgroup html i iframe ins kbd label legend li main map mark menu meter
      nav noscript object ol optgroup option output p pre progress q rp rt
      ruby s samp script section select small span strong style sub summary
      sup table tbody td textarea tfoot th thead time title tr u ul video'

     htmlVoid: 'area base br col command embed hr img input keygen link meta
      param source track wbr'

Wrapper for browser API

    Api =
     document: @document

Parse id and class string

    parseIdClass = (str) ->
     res =
      id: null
      class: []

     for c, i in str.split "."
      if c.indexOf("#") is 0
       res.id = c.substr 1
      else if c isnt ""
       if not res.class?
        res.class = [c]
       else
        res.class.push c

     return res

    getParameters = (args) ->
     params =
      idClass: null
      text: null
      attrs: null
      func: null

     for arg, i in args
      switch typeof arg
       when 'function' then params.func = arg
       when 'object' then params.attrs = arg
       when 'string'
        if args.length is 1
         params.text = arg
        else
         c = arg.charAt 0

         if i is 0 and (c is '#' or c is '.')
          params.idClass = parseIdClass arg
         else
          params.text = arg

     return params

#Weya DOM

    weyaDomCreate = ->

Weya object to be passed as `this`

     weya =
      _elem: null

Manipulating dom objects

     setStyles = (elem, styles) ->
      for k, v of styles
       if v?
        elem.style.setProperty k, v
       else
        elem.style.removeProperty k

     setEvents = (elem, events) ->
      for k, v of events
       elem.addEventListener k, v, false

     setAttributes = (elem, attrs) ->
      for k, v of attrs
       switch k
        when 'style' then setStyles elem, v
        when 'on' then setEvents elem, v
        else
         if v?
          elem.setAttribute k, v
         else
          elem.removeAttribute k

     setIdClass = (elem, idClass) ->
      if idClass.id?
       elem.id = idClass.id

      if idClass.class?
       if elem.classList?
        for c in idClass.class
         elem.classList.add c
       else #For older browsers; does not work with svgs
        className = ''
        for c in idClass.class
         className += ' ' if className isnt ''
         className += "#{c}"
        elem.className = className

Append a child element

     append = (ns, name, args) ->
      params = getParameters args

Keep a reference to parent element

      pElem = @_elem

Keep a reference of `elem` to return at the end of the function

      if ns?
       elem = @_elem = Api.document.createElementNS ns, name
      else
       elem = @_elem = Api.document.createElement name

      if params.idClass?
       setIdClass elem, params.idClass

      if params.attrs?
       setAttributes elem, params.attrs

      if pElem?
       pElem.appendChild elem

      if params.func?
       params.func.call this
      else if params.text?
       elem.textContent = params.text

      @_elem = pElem
      return elem

Wrap `append`

     wrapAppend = (ns, name) ->
      ->
       append.call this, ns, name, arguments

Initialize

     for name in Tags.svg.split ' '
      weya[name] = wrapAppend "http://www.w3.org/2000/svg", name

     for name in Tags.html.split ' '
      weya[name] = wrapAppend "http://www.w3.org/1999/xhtml", name

     for name in Tags.htmlVoid.split ' '
      weya[name] = wrapAppend null, name

     return weya

#Weya Markup

    weyaMarkupCreate = ->

Weya object to be passed as `this`

     weya =
      _buf: null
      _indent: 0

Render components

     setStyles = (buf, styles) ->
      buf.push " style=\""
      for k, v of styles
       buf.push "#{k}:#{v};"
      buf.push "\""

     setEvents = (buf, events) ->
      for k, v of events
       buf.push " on#{k}=\"#{v}\""

     setAttributes = (buf, attrs) ->
      for k, v of attrs
       switch k
        when 'style' then setStyles buf, v
        when 'on' then setEvents buf, v
        else
         buf.push " #{k}=\"#{v}\""

     setIndent = (buf, indent) ->
      for i in [0...indent]
       buf.push " "

Append a child element

     append = (ns, name, args) ->
      params = getParameters args

      buf = @_buf

      setIndent buf, @_indent

      buf.push "<#{name}"

      if params.idClass?
       if params.idClass.id?
        buf.push " id=\"#{params.idClass.id}\""
       if params.idClass.class?
        buf.push " class=\"#{params.idClass.class}\""

      if params.attrs?
       setAttributes buf, params.attrs

Can close void elements (element that self close) with a `/>`

      buf.push ">\n"
      @_indent++

      if params.func?
       params.func.call this
      else if params.text?
       setIndent buf, @_indent
       buf.push params.text
       buf.push "\n"

      @_indent--
      setIndent buf, @_indent
      buf.push "</#{name}>\n"

Wrap `append`

     wrapAppend = (ns, name) ->
      ->
       append.call this, ns, name, arguments

Initialize

     for name in Tags.svg.split ' '
      weya[name] = wrapAppend "http://www.w3.org/2000/svg", name

     for name in Tags.html.split ' '
      weya[name] = wrapAppend null, name

     for name in Tags.htmlVoid.split ' '
      weya[name] = wrapAppend null, name

     return weya

#Weya API

    weyaDom = weyaDomCreate()
    weyaMarkup = weyaMarkupCreate()

Create and append to `options.elem`. If `options.context` is provied it can be
accessed via `@$`. If `options.elem` is `null`, the element is created but
not appended.

    @Weya = Weya = (options, func) ->
     weya = weyaDom
     pContext = weya.$
     weya.$ = options.context
     pElem = weya._elem
     weya._elem = options.elem
     r = func?.call weya
     weya._elem = pElem
     weya.$ = pContext
     return r

    Weya.markup = (options, func) ->
     weya = weyaMarkup
     pContext = weya.$
     weya.$ = options.context
     added = []
     setFunc = (name, f) ->
      weya[name] = ->
       f.apply weya, arguments
     if options.helpers?
      for name, f of options.helpers
       if not weya[name]?
        added.push name
        setFunc name, f
     pBuf = weya._buf
     weya._buf = []
     r = func?.call weya
     buf = weya._buf
     weya._buf = pBuf
     weya.$ = pContext
     for name in added
      weya[name] = null
     return buf.join ''

    Weya.setApi = (api) ->
     for k, v of api
      Api[k] = v

    if module?
     module.exports = Weya


indent code 8 spaces instead

indent code 8 spaces instead

# Batman.Request
 Request is an abstraction around XHR requests.  It can be used with a variety of platforms, and is implemented in the platform layer files.

### Platform Request Implmentation Libraries:
  Depending on the platform library the underlying request implementation will change:

 - `batman.jquery.js`: jQuery XHR
 - `batman.solo.js`: Reqwest.js

 _note_ For the tests there are some mocked responses, in a normal non testing situation you would not use these

### How to use Batman Request

Batman.Request can be used a variety of ways.  This is the underlying library that the `rest_storage_adapater` uses to communicate.

In other cases where you want to communicate with a server that isn't your default storage_adapter you would use it like:

    test "Send a simple Batman.Request", ->
      Batman.Request.setupMockedResponse()
      Batman.Request.addMockedResponse( "GET", "http://batmanjs.org", ->{})
      new Batman.Request
        url: "http://batmanjs.org"
        method: "GET"
        success: (result) ->
          ok true

### Lifecycle events

There are a variety of lifecycle events that get fired in a `Request`.  Each of these are passed in as parameters in the options object in the `Request` constructor.

1. `loading()`: fired before `send()` has been called.

        test "Demonstrate the loading event", 1, ->
           new Batman.Request
             url: "http:://batmanjs.org"
             loading: ->
               ok true, "After send but before the request is made"

1. `loaded()`: fired after the request is complete

         test "Demo the loaded event", 1, ->
           Batman.Request.setupMockedResponse()
           Batman.Request.addMockedResponse("GET", "http://batmanjs.org", -> {})
           new Batman.Request
             url: "http://batmanjs.org"
             loaded: ->
               ok true, "Loaded"

1. `error( xhr )`: fired when an error is detected,  `xhr` is the platform defined xhr object with a property named `request` being the `Batman.Request` object.

        test "Demo the error event", 1, ->
          Batman.Request.setupMockedResponse()
          Batman.Request.addMockedResponse("GET", "http://batmanjs.org", -> status: 400)
          new Batman.Request
            url: "http://batmanjs.org"
            error: (xhr) ->
              ok true, "Error"

1. `success ( response )`: fired when a successful request has been made, `response` is the body of the request response.

        test "Demonstrate the success event", 1,  ->
          Batman.Request.setupMockedResponse()
          Batman.Request.addMockedResponse("GET", "http://batmanjs.org", -> response: "foo")
          new Batman.Request
            url: "http://batmanjs.org"
            success: (response) ->
              equal "foo", response

## .status
The response status, only set after `error` or `success`

    test "Demo the error event", 1, ->
     Batman.Request.setupMockedResponse()
     Batman.Request.addMockedResponse("GET", "http://batmanjs.org", -> status: 400)
     new Batman.Request
       url: "http://batmanjs.org"
       error: (xhr) ->
         equal 400, @status

## .response
The response object

    test "Demonstrate the response object", 1, ->
      Batman.Request.setupMockedResponse()
      Batman.Request.addMockedResponse("GET", "http://batmanjs.org", -> response: "foo" )

      new Batman.Request
        url: "http://batmanjs.org"
        success: (response) ->
          equal "foo", JSON.parse(@response)

## .responseHeaders : object
An key/value object with the response headers

    test "responseHeaders", 1, ->
      Batman.Request.setupMockedResponse()
      Batman.Request.addMockedResponse("GET", "http://batmanjs.org", -> responseHeaders: { FOO: "bar" } )

      new Batman.Request
        url: "http://batmanjs.org"
        success: (response) ->
          deepEqual @responseHeaders,{ FOO: "bar" }

## @Request(options : object)

Constructs a new `Batman.Request` with the supplied options

### `options` description

1. `url : String`: A string containing the URL to which the request is sent.  Mandatory

1. `method : String`: The type of request to make eg. `GET`, `POST`.  Default is `GET`.

        test "method test", ->
          Batman.Request.setupMockedResponse()
          Batman.Request.addMockedResponse("POST", "http://batmanjs.org", -> response : { FOO: "BAR" })
          new Batman.Request
            url: "http://batmanjs.org"
            method: "POST"
            data: { some: "data" }
            success: (response) ->
              ok true

1. `data`: Data to be sent to the server. It is converted to a query string, if not already a string. It's appended to the url for GET-requests.

1. `contentType`: the content type to send, defaults to `application/x-www-form-urlencoded`

        test "contentType default", ->
           req = new Batman.Request
           equal req.contentType, "application/x-www-form-urlencoded"

1. `autosend`: controls whether the request will be sent automatically, deafults to `true`

        test "autosend test", ->
          response_sent = false
          Batman.Request.setupMockedResponse()
          Batman.Request.addMockedResponse("GET", "http://batmanjs.org", -> {} )
          req = new Batman.Request
            url: "http://batmanjs.org"
            autosend: false
            success: (response) ->
              response_sent = true
          ok !response_sent
          req.send()
          ok response_sent

1. `username`: username for authentication

1. `password`: password for authentication

1. `type`: The type of data you're expecting from the server, defaults to `json`

## ::send([data])
If `autosend` is `false`, this will initiate the request.  The data object passed in will take priority over the one specified in the `options` object

    test "request.send()", ->
      beforeResponse = (req, data) ->
        deepEqual data, { other: "thing" }
      Batman.Request.setupMockedResponse()
      Batman.Request.addMockedResponse("GET", "http://batmanjs.org", -> {beforeResponse: beforeResponse} )
      req = new Batman.Request
        url: "http://batmanjs.org"
        autosend: false
        data: { some: "data" }
      req.send( { other: "thing" } )

# Batman.Request
 Request is an abstraction around XHR requests.  It can be used with a variety of platforms, and is implemented in the platform layer files.

### Platform Request Implmentation Libraries:
  Depending on the platform library the underlying request implementation will change:

 - `batman.jquery.js`: jQuery XHR
 - `batman.solo.js`: Reqwest.js

 _note_ For the tests there are some mocked responses, in a normal non testing situation you would not use these

### How to use Batman Request

Batman.Request can be used a variety of ways.  This is the underlying library that the `rest_storage_adapater` uses to communicate.

In other cases where you want to communicate with a server that isn't your default storage_adapter you would use it like:

    test "Send a simple Batman.Request", ->
      Batman.Request.setupMockedResponse()
      Batman.Request.addMockedResponse( "GET", "http://batmanjs.org", ->{})
      new Batman.Request
        url: "http://batmanjs.org"
        method: "GET"
        success: (result) ->
          ok true

### Lifecycle events

There are a variety of lifecycle events that get fired in a `Request`.  Each of these are passed in as parameters in the options object in the `Request` constructor.

1) `loading()`: fired before `send()` has been called.

    test "Demonstrate the loading event", 1, ->
       new Batman.Request
         url: "http:://batmanjs.org"
         loading: ->
           ok true, "After send but before the request is made"

2) `loaded()`: fired after the request is complete

     test "Demo the loaded event", 1, ->
       Batman.Request.setupMockedResponse()
       Batman.Request.addMockedResponse("GET", "http://batmanjs.org", -> {})
       new Batman.Request
         url: "http://batmanjs.org"
         loaded: ->
           ok true, "Loaded"

3) `error( xhr )`: fired when an error is detected,  `xhr` is the platform defined xhr object with a property named `request` being the `Batman.Request` object.

    test "Demo the error event", 1, ->
      Batman.Request.setupMockedResponse()
      Batman.Request.addMockedResponse("GET", "http://batmanjs.org", -> status: 400)
      new Batman.Request
        url: "http://batmanjs.org"
        error: (xhr) ->
          ok true, "Error"

4) `success ( response )`: fired when a successful request has been made, `response` is the body of the request response.

    test "Demonstrate the success event", 1,  ->
      Batman.Request.setupMockedResponse()
      Batman.Request.addMockedResponse("GET", "http://batmanjs.org", -> response: "foo")
      new Batman.Request
        url: "http://batmanjs.org"
        success: (response) ->
          equal "foo", response

## .status
The response status, only set after `error` or `success`

    test "Demo the error event", 1, ->
     Batman.Request.setupMockedResponse()
     Batman.Request.addMockedResponse("GET", "http://batmanjs.org", -> status: 400)
     new Batman.Request
       url: "http://batmanjs.org"
       error: (xhr) ->
         equal 400, @status

## .response
The response object

    test "Demonstrate the response object", 1, ->
      Batman.Request.setupMockedResponse()
      Batman.Request.addMockedResponse("GET", "http://batmanjs.org", -> response: "foo" )

      new Batman.Request
        url: "http://batmanjs.org"
        success: (response) ->
          equal "foo", JSON.parse(@response)

## .responseHeaders : object
An key/value object with the response headers

    test "responseHeaders", 1, ->
      Batman.Request.setupMockedResponse()
      Batman.Request.addMockedResponse("GET", "http://batmanjs.org", -> responseHeaders: { FOO: "bar" } )

      new Batman.Request
        url: "http://batmanjs.org"
        success: (response) ->
          deepEqual @responseHeaders,{ FOO: "bar" }

## @Request(options : object)

Constructs a new `Batman.Request` with the supplied options

### `options` description

1) `url : String`: A string containing the URL to which the request is sent.  Mandatory

2) `method : String`: The type of request to make eg. `GET`, `POST`.  Default is `GET`

    test "method test", ->
      Batman.Request.setupMockedResponse()
      Batman.Request.addMockedResponse("POST", "http://batmanjs.org", -> response : { FOO: "BAR" })
      new Batman.Request
        url: "http://batmanjs.org"
        method: "POST"
        data: { some: "data" }
        success: (response) ->
          ok true

3) `data`: Data to be sent to the server. It is converted to a query string, if not already a string. It's appended to the url for GET-requests.

4) `contentType`: the content type to send, defaults to `application/x-www-form-urlencoded`

    test "contentType default", ->
       req = new Batman.Request
       equal req.contentType, "application/x-www-form-urlencoded"

5) `autosend`: controls whether the request will be sent automatically, deafults to `true`

    test "autosend test", ->
      response_sent = false
      Batman.Request.setupMockedResponse()
      Batman.Request.addMockedResponse("GET", "http://batmanjs.org", -> {} )
      req = new Batman.Request
        url: "http://batmanjs.org"
        autosend: false
        success: (response) ->
          response_sent = true
      ok !response_sent
      req.send()
      ok response_sent

6) `username`: username for authentication

7) `password`: password for authentication

8) `type`: The type of data you're expecting from the server, defaults to `json`

## ::send([data])
If `autosend` is `false`, this will initiate the request.  The data object passed in will take priority over the one specified in the `options` object

    test "request.send()", ->
      beforeResponse = (req, data) ->
        deepEqual data, { other: "thing" }
      Batman.Request.setupMockedResponse()
      Batman.Request.addMockedResponse("GET", "http://batmanjs.org", -> {beforeResponse: beforeResponse} )
      req = new Batman.Request
        url: "http://batmanjs.org"
        autosend: false
        data: { some: "data" }
      req.send( { other: "thing" } )