changed the methd prefixs

changed the methd prefixs

# Batman Helpers

Batman includes a number of useful, general purpose helper functions and references. They can all be found attached to the `Batman` object and can optionally be exported into the global namespace with a `$` prefix.

## container

`Batman.container` points to either the `window` object if running in the browser, or the `global` object if running in node. This is useful if you want to add something to the global scope in all environments.

## @typeOf(object) : string

`typeOf` determines a more specific type of an `object` than the native `typeof` operator in JavaScript. This is useful for a number of situations like dealing with `Object` promoted strings and numbers, or arrays which look like `object`s to `typeof`. Use `typeOf` when you need more than `"object"` from `typeof`.

_Note_: `typeOf` is substantially slower than `typeof`. `typeOf` works in a somewhat hackish manner by getting the `Object::toString` representation of the object and slicing it to retrieve the name of the constructor.

    test 'typeOf returns "String" for both strings and Object strings', ->
      primitive = "test"
      objectified = new String("test")
      equal typeof primitive, "string"
      equal typeof objectified, "object"
      equal Batman.typeOf(primitive), "String"
      equal Batman.typeOf(objectified), "String"

    test 'typeOf returns Array for arrays', ->
      array = [];
      equal typeof array, "object"
      equal Batman.typeOf(array), "Array"

## @mixin(subject, objects...) : subject

`mixin`, occasionally known elsewhere as `extend` or `merge`, flattens a series of objects onto the subject. Key/value pairs on objects passed as later arguments (arguments with a higher index) take precedence over earlier arguments. Returns the `subject` passed in with the new values.

`mixin` also has special properties that make it different than the canonical `extend` functions:

 1. If the `subject` has a `set` function, `subject.set(key, value)` will be used to apply keys instead of `subject[key] = value`. This means that if the subject is a `Batman.Object`, observers and thus bindings on the object will be notified when other (Batmanified or not) objects are mixed into it.
 2. If a mixed-in `object` has an `initialize` function defined, that function will be called and passed the `subject`. This is useful for custom extension logic, similar to `self.included` in Ruby. For this reason, the keys `initialize` and `uninitialize` are skipped by `mixin`.
 3. `mixin` only iterates over keys for which the `hasOwnProperty` test passes.

_Note_: `mixin` is destructive to (only) the first argument. If you need a non-destructive version of `mixin`, just pass an empty object as the first object, and all keys from the successive arguments will be applied to the empty object.

    test 'mixin merges argument objects', ->
      subject = {}
      deepEqual Batman.mixin(subject, {fit: true}, {fly: true}, {funky: true}), {fit: true, fly: true, funky: true}, "mixin returns the subject"
      deepEqual subject, {fit: true, fly: true, funky: true}, "the subject is modified destructively"

    test 'mixin merges argument objects', ->
      unmodified = {fit: true}
      deepEqual Batman.mixin({}, unmodified, {fly: true}, {funky: true}), {fit: true, fly: true, funky: true}, "mixin returns the subject"
      deepEqual unmodified, {fit: true}, "argument objects are untouched allowing non-destructive merge"

    test 'mixed in objects passed as higher indexed arguments take precedence', ->
      subject = {}
      deepEqual Batman.mixin(subject, {x: 1, y: 1}, {x: 2}), {x: 2, y: 1}

## @unmixin(subject, objects...) : subject

`unmixin` "unmerges" the passed objects from the `subject`. If a key exists on any of the `objects` it will be `delete`d from the `subject`. Returns the `subject`.

`unmixin`, similar to `mixin`, supports calling an `uninitialize` function for each of the `objects` being unmixed in. If an `uninitialize` function exists on each

    test 'unmixin removes keys found on the unmixined objects on the subject', ->
      subject = {fit: true, fly: true, funky: true}
      deepEqual Batman.unmixin(subject, {fit: true}, {fly: true}), {funky: true}, "unmixin returns the subject"
      deepEqual subject, {funky: true}, "the subject is destructively modified."

## @functionName(function) : string

`functionName` returns the name of a given function, if any. Works with Internet Explorer 7/8/9, FireFox, Chrome, and Safari.

    test 'functionName returns the name of a given function', ->
      equal Batman.functionName("".toString), 'toString'

## @isChildOf(parent : HTMLElement, child : HTMLElement) : boolean

`isChildOf` is a simple DOM helper which returns a boolean describing if the passed `child` node can be found in the descendants of the passed `parent` node.

## @setImmediate(callback : Function) : object

`setImmediate` (and its sister `clearImmediate`) are a more efficient version of `setTimeout(callback, 0)`. Due to timer resolution issues, setTimeout passed a timeout of 0 doesn't actually execute the function as soon as the JS execution stack has been emptied, but at minimum 4ms and maxmium 25ms after. For this reason Batman provides a cross browser implementation of `setImmediate` which does its best to call the callback immediately after the stack empties. Batman's `setImmediate` polyfill uses the native version if available, `window.postmessage` trickery if supported, and falls back on `setTimeout(->, 0)`.

`setImmediate` returns a handle which can be passed to `clearImmediate` to cancel the future calling of the callback.

## @clearImmediate(handle)

`clearImmediate` stops the calling of a callback in the future when passed its `handle` (which is returned from the `setImmediate` call used to enqueue it).

## @forEach(iterable : object, iterator : Function[, context : Object])

The `forEach` Batman helper is a universal iteration helper. When passed an `iterable` object, the helper will call the `iterator` (optionally in the `context`) for each item in the `iterable`. The `iterable` can be:

 1. something which has its own `forEach`, in which case the `iterator` will just be passed to `iterable.forEach`.
 2. an array like object, in which case a JavaScript `for(;;)` loop will be used to iterate over each entry
 3. or an object, in which case a JavaScript `for-in` loop will be used to iterate over each entry.

The `forEach` helper is useful for iterating over objects when the type of those objects isn't guaranteed.

    test 'forEach iterates over objects with forEach defined', ->
      results = []
      set = new Batman.SimpleSet('a')
      Batman.forEach(set, (x) -> results.push(x))
      deepEqual results, ['a']

    test 'forEach iterates over array like objects', ->
      results = []
      ArrayLike = ->
      ArrayLike:: = []
      imitation = new ArrayLike
      Array::push.call(imitation, "a")
      Array::push.call(imitation, "b")
      Batman.forEach(imitation, (x) -> results.push(x))
      deepEqual results, ['a', 'b']

    test 'forEach iterates over objects', ->
      result = {}
      object = {x: true}
      Batman.forEach(object, (key, val) -> result[key] = val)
      deepEqual result, object

## @objectHasKey(object, key) : boolean

`objectHasKey` returns a boolean describing the presence of the `key` in the passed `object`. `objectHasKey` delegates to the `object`'s `hasKey` function if present, and otherwise just does a check using the JavaScript `in` operator.

    test 'objectHasKey verifies if a key is present in an object', ->
      subject = {fit: true}
      ok Batman.objectHasKey(subject, 'fit')
      equal Batman.objectHasKey(subject, 'flirty'), false

    test 'objectHasKey verifies if a key is present in an object with `hasKey` defined', ->
      subject = new Batman.SimpleHash {fit: true}
      ok Batman.objectHasKey(subject, 'fit')
      equal Batman.objectHasKey(subject, 'flirty'), false

## @contains(object, item) : boolean

`contains` returns a boolean describing if the given `object` has member `item`. Membership in this context is defined as:

 + the result of `object.has(item)` if the `object` has a `has` function defined
 + the result of `item in object` if the `object` is arraylike
 + the result of the Batman.objectHasKey otherwise

_Note_: When passed an object without a `has` function, `contains` will return `true` if the `object` has `item` as a *`key`*, not as a value at any key.

`contains` is useful for checking item membership when the type of the object can't be relied on.

## @get(object, key) : value

`get` is a general purpose function for retrieving the value from a `key` on an `object` of an indeterminate type. This is useful if code needs to work with both `Batman.Object`s and Plain Old JavaScript Objects. `get` has the following semantics:

 + if the `object` has a `get` function defined, return the result of `object.get(key)`
 + if the object does not have a `get` function defined, use an ephemeral `Batman.Property` to retrieve the key. This is equivalent to `object[key]` for single segment `key`s, but if the `key` is multi-segment (example: 'product.customer.name'), `get` will do nested gets until the either `undefined` or the end of the keypath is reached.

    test 'get returns the value at a key on a POJO', ->
      subject = {fit: true}
      equal Batman.get(subject, 'fit'), true
      equal Batman.get(subject, 'flirty'), undefined

    test 'get returns the value at a key on a Batman.Object', ->
      subject = Batman {fit: true}
      equal Batman.get(subject, 'fit'), true
      equal Batman.get(subject, 'flirty'), undefined

    test 'get returns the value at a deep key on a POJO', ->
      subject = {customer: {name: "Joe"}}
      equal Batman.get(subject, 'customer.name'), "Joe"
      equal Batman.get(subject, 'customer.age'), undefined

    test 'get returns the value at a deep key on a Batman.Object', ->
      subject = Batman {customer: {name: "Joe"}}
      equal Batman.get(subject, 'customer.name'), "Joe"
      equal Batman.get(subject, 'customer.age'), undefined

## @getPath(base, segments) : string

`getPath` returns the hash value denoted by the specified path, which consists of an array of nested hash keys. See examples below for more detail.

    test "takes a base and an array of keys and returns the corresponding nested value", ->
      @complexObject = new Batman.Object
        hash: new Batman.Hash
          foo: new Batman.Object(bar: 'nested value'),
          "foo.bar": 'flat value'
      equal Batman.getPath(@complexObject, ['hash', 'foo', 'bar']), 'nested value'
      equal Batman.getPath(@complexObject, ['hash', 'foo.bar']), 'flat value'
      strictEqual Batman.getPath(@complexObject, ['hash', 'not-foo', 'bar']), undefined

    test "returns just the base if the key array is empty", ->
      @complexObject = new Batman.Object
        hash: new Batman.Hash
          foo: new Batman.Object(bar: 'nested value'),
          "foo.bar": 'flat value'
      strictEqual Batman.getPath(@complexObject, []), @complexObject
      strictEqual Batman.getPath(null, []), null

    test "returns undefined if the base is null-ish", ->
      @complexObject = new Batman.Object
        hash: new Batman.Hash
          foo: new Batman.Object(bar: 'nested value'),
          "foo.bar": 'flat value'
      strictEqual Batman.getPath(null, ['foo']), undefined
      strictEqual Batman.getPath(undefined, ['foo']), undefined

    test "returns falsy values", ->
      @complexObject = new Batman.Object
        hash: new Batman.Hash
          foo: new Batman.Object(bar: 'nested value'),
          "foo.bar": 'flat value'
      strictEqual Batman.getPath(num: 0, ['num']), 0
      strictEqual Batman.getPath(thing: null, ['thing']), null

## @escapeHTML(string) : string

`escapeHTML` takes a string of unknown origin and makes it safe for display on a web page by encoding control characters in HTML into their HTML entities.

*Warning*: Do not rely on `escapeHTML` to purge unsafe data from user submitted content. While `escapeHTML` is applied to every binding's contents by default, it should not be your only line of defence against script injection attacks.

    test 'escapeHTML encodes special characters into HTML entities', ->
      equal Batman.escapeHTML("& < > \" '"), "& < > " '"

# Batman.helpers

`Batman.helpers` is a namespace for Batman's helpful string manipulation helpers.

_Note_: Batman's pluralization functions mirror those of Rails' exactly.

## @ordinalize(value : [number|string]) : string

`ordinalize` converts a given integer into an ordinal string for describing position in a list, like 1st, 2nd, or 20th.

    test 'ordinalize converts numbers to their ordinal form', ->
      equal Batman.helpers.ordinalize(1)     , "1st"
      equal Batman.helpers.ordinalize("2")     , "2nd"
      equal Batman.helpers.ordinalize(1002)  , "1002nd"
      equal Batman.helpers.ordinalize("1003")  , "1003rd"
      equal Batman.helpers.ordinalize(-11)   , "-11th"
      equal Batman.helpers.ordinalize(-1021) , "-1021st"

## @singularize(pluralString : string) : string

`singularize` converts the plural form of a word to a singular form.

    test 'singularize converts plural words to singular words', ->
      equal Batman.helpers.singularize("posts"), "post"
      equal Batman.helpers.singularize("octopi"), "octopus"
      equal Batman.helpers.singularize("sheep"), "sheep"
      equal Batman.helpers.singularize("word"), "word"
      equal Batman.helpers.singularize("CamelOctopi"), "CamelOctopus"

## @pluralize(singularString : string) : string

`pluralize` converts the singular form of a word to the plural form.

    test 'pluralize converts plural words to singular words', ->
      equal Batman.helpers.pluralize("post"), "posts"
      equal Batman.helpers.pluralize("octopus"), "octopi"
      equal Batman.helpers.pluralize("sheep"), "sheep"
      equal Batman.helpers.pluralize("words"), "words"
      equal Batman.helpers.pluralize("CamelOctopus"), "CamelOctopi"

## @camelize(string, [lowercaseFirstLetter = false]) : string

`camelize` converts the passed `string` to UpperCamelCase. If the second argument is passed as `true`, then lowerCamelCase is returned.

    test 'camelize returns the CamelCase version of an under_scored word', ->
      equal Batman.helpers.camelize("batman_object"), "BatmanObject"
      equal Batman.helpers.camelize("batman_object", true), "batmanObject"

## @underscore(string) : string

`underscore` returns the underscored version of a CamelCase word.

    test 'underscore converts CamelCase to under_scores', ->
      equal Batman.helpers.underscore("BatmanObject"), "batman_object"

## @capitalize(string) : string

`capitalize` does a word-wise capitalization of a phrase or word.

    test 'capitalize makes the first letter of each word in the string uppercase', ->
      equal Batman.helpers.capitalize("batmanObject"), "BatmanObject"
      equal Batman.helpers.capitalize("batman object"), "Batman Object"
      equal Batman.helpers.capitalize("AlreadyCapitalized"), "AlreadyCapitalized"

## @trim(string) : string

`trim` trims a string getting rid of extra white space around the string or returning an empty string if it is null.

    test 'trim gets rid of space around a string', ->
      equal Batman.helpers.trim("TrimRight "), "TrimRight"
      equal Batman.helpers.trim(" TrimLeft"), "TrimLeft"
      equal Batman.helpers.trim(" TrimBothSides "), "TrimBothSides"
      equal Batman.helpers.trim("AlreadyTrimmed"), "AlreadyTrimmed"

    test 'trim turns a null or undefined string into an empty string', ->
      equal Batman.helpers.trim(null), ""
      equal Batman.helpers.trim(undefined), ""

## @interpolate(stringOrObject, keys) : string

`interpolate` interpolates a string, filling it in with values matching interpolation keys, similar to printf variants.

    test 'interpolate fills in key values globally in a string', ->
      equal Batman.helpers.interpolate("%{field} must be at least %{count} characters in order for %{field} to be valid", count: "3", field: "name"), "name must be at least 3 characters in order for name to be valid"

    test 'interpolate fills in key values globally in an object-embedded string', ->
      equal Batman.helpers.interpolate({'other': "%{field} must be at least %{count} characters in order for %{field} to be valid"}, count: "3", field: "name"), "name must be at least 3 characters in order for name to be valid"

    test 'interpolate fills in key values globally in an object-embedded string, embedded by key count', ->
      equal Batman.helpers.interpolate({3: "%{field} must be at least %{count} characters in order for %{field} to be valid"}, count: "3", field: "name"), "name must be at least 3 characters in order for name to be valid"

## @humanize(string) : string

`humanize` reformats a string that has a programmatic meaning (camelcased, underscored, "_id" suffixed) to make human-readable by separating concatenated words and/or getting rid of the "_id" suffix.

    test 'humanize replaces underscores and dashes with empty space', ->
      equal Batman.helpers.humanize('underscored_string'), 'Underscored string'
      equal Batman.helpers.humanize('dash-separated-string'), 'Dash separated string'

    test 'humanize splits camel cased words by empty space', ->
      equal Batman.helpers.humanize('CamelCasedString'), 'Camel cased string'

    test 'humanize title-cases the first word', ->
      equal Batman.helpers.humanize('lower case sentence'), 'Lower case sentence'

    test 'humanize lower-cases all words after the first one', ->
      equal Batman.helpers.humanize('Mixed Case SENTENCE'), 'Mixed case sentence'

    test 'humanize gets rid of _id suffix', ->
      equal Batman.helpers.humanize('identifying_string_id'), 'Identifying string'

# Batman Helpers

Batman includes a number of useful, general purpose helper functions and references. They can all be found attached to the `Batman` object and can optionally be exported into the global namespace with a `$` prefix.

## container

`Batman.container` points to either the `window` object if running in the browser, or the `global` object if running in node. This is useful if you want to add something to the global scope in all environments.

## typeOf(object) : string

`typeOf` determines a more specific type of an `object` than the native `typeof` operator in JavaScript. This is useful for a number of situations like dealing with `Object` promoted strings and numbers, or arrays which look like `object`s to `typeof`. Use `typeOf` when you need more than `"object"` from `typeof`.

_Note_: `typeOf` is substantially slower than `typeof`. `typeOf` works in a somewhat hackish manner by getting the `Object::toString` representation of the object and slicing it to retrieve the name of the constructor.

    test 'typeOf returns "String" for both strings and Object strings', ->
      primitive = "test"
      objectified = new String("test")
      equal typeof primitive, "string"
      equal typeof objectified, "object"
      equal Batman.typeOf(primitive), "String"
      equal Batman.typeOf(objectified), "String"

    test 'typeOf returns Array for arrays', ->
      array = [];
      equal typeof array, "object"
      equal Batman.typeOf(array), "Array"

## mixin(subject, objects...) : subject

`mixin`, occasionally known elsewhere as `extend` or `merge`, flattens a series of objects onto the subject. Key/value pairs on objects passed as later arguments (arguments with a higher index) take precedence over earlier arguments. Returns the `subject` passed in with the new values.

`mixin` also has special properties that make it different than the canonical `extend` functions:

 1. If the `subject` has a `set` function, `subject.set(key, value)` will be used to apply keys instead of `subject[key] = value`. This means that if the subject is a `Batman.Object`, observers and thus bindings on the object will be notified when other (Batmanified or not) objects are mixed into it.
 2. If a mixed-in `object` has an `initialize` function defined, that function will be called and passed the `subject`. This is useful for custom extension logic, similar to `self.included` in Ruby. For this reason, the keys `initialize` and `uninitialize` are skipped by `mixin`.
 3. `mixin` only iterates over keys for which the `hasOwnProperty` test passes.

_Note_: `mixin` is destructive to (only) the first argument. If you need a non-destructive version of `mixin`, just pass an empty object as the first object, and all keys from the successive arguments will be applied to the empty object.

    test 'mixin merges argument objects', ->
      subject = {}
      deepEqual Batman.mixin(subject, {fit: true}, {fly: true}, {funky: true}), {fit: true, fly: true, funky: true}, "mixin returns the subject"
      deepEqual subject, {fit: true, fly: true, funky: true}, "the subject is modified destructively"

    test 'mixin merges argument objects', ->
      unmodified = {fit: true}
      deepEqual Batman.mixin({}, unmodified, {fly: true}, {funky: true}), {fit: true, fly: true, funky: true}, "mixin returns the subject"
      deepEqual unmodified, {fit: true}, "argument objects are untouched allowing non-destructive merge"

    test 'mixed in objects passed as higher indexed arguments take precedence', ->
      subject = {}
      deepEqual Batman.mixin(subject, {x: 1, y: 1}, {x: 2}), {x: 2, y: 1}

## unmixin(subject, objects...) : subject

`unmixin` "unmerges" the passed objects from the `subject`. If a key exists on any of the `objects` it will be `delete`d from the `subject`. Returns the `subject`.

`unmixin`, similar to `mixin`, supports calling an `uninitialize` function for each of the `objects` being unmixed in. If an `uninitialize` function exists on each

    test 'unmixin removes keys found on the unmixined objects on the subject', ->
      subject = {fit: true, fly: true, funky: true}
      deepEqual Batman.unmixin(subject, {fit: true}, {fly: true}), {funky: true}, "unmixin returns the subject"
      deepEqual subject, {funky: true}, "the subject is destructively modified."

## functionName(function) : string

`functionName` returns the name of a given function, if any. Works with Internet Explorer 7/8/9, FireFox, Chrome, and Safari.

    test 'functionName returns the name of a given function', ->
      equal Batman.functionName("".toString), 'toString'

## isChildOf(parent : HTMLElement, child : HTMLElement) : boolean

`isChildOf` is a simple DOM helper which returns a boolean describing if the passed `child` node can be found in the descendants of the passed `parent` node.

## setImmediate(callback : Function) : object

`setImmediate` (and its sister `clearImmediate`) are a more efficient version of `setTimeout(callback, 0)`. Due to timer resolution issues, setTimeout passed a timeout of 0 doesn't actually execute the function as soon as the JS execution stack has been emptied, but at minimum 4ms and maxmium 25ms after. For this reason Batman provides a cross browser implementation of `setImmediate` which does its best to call the callback immediately after the stack empties. Batman's `setImmediate` polyfill uses the native version if available, `window.postmessage` trickery if supported, and falls back on `setTimeout(->, 0)`.

`setImmediate` returns a handle which can be passed to `clearImmediate` to cancel the future calling of the callback.

## clearImmediate(handle)

`clearImmediate` stops the calling of a callback in the future when passed its `handle` (which is returned from the `setImmediate` call used to enqueue it).

## forEach(iterable : object, iterator : Function[, context : Object])

The `forEach` Batman helper is a universal iteration helper. When passed an `iterable` object, the helper will call the `iterator` (optionally in the `context`) for each item in the `iterable`. The `iterable` can be:

 1. something which has its own `forEach`, in which case the `iterator` will just be passed to `iterable.forEach`.
 2. an array like object, in which case a JavaScript `for(;;)` loop will be used to iterate over each entry
 3. or an object, in which case a JavaScript `for-in` loop will be used to iterate over each entry.

The `forEach` helper is useful for iterating over objects when the type of those objects isn't guaranteed.

    test 'forEach iterates over objects with forEach defined', ->
      results = []
      set = new Batman.SimpleSet('a')
      Batman.forEach(set, (x) -> results.push(x))
      deepEqual results, ['a']

    test 'forEach iterates over array like objects', ->
      results = []
      ArrayLike = ->
      ArrayLike:: = []
      imitation = new ArrayLike
      Array::push.call(imitation, "a")
      Array::push.call(imitation, "b")
      Batman.forEach(imitation, (x) -> results.push(x))
      deepEqual results, ['a', 'b']

    test 'forEach iterates over objects', ->
      result = {}
      object = {x: true}
      Batman.forEach(object, (key, val) -> result[key] = val)
      deepEqual result, object

## objectHasKey(object, key) : boolean

`objectHasKey` returns a boolean describing the presence of the `key` in the passed `object`. `objectHasKey` delegates to the `object`'s `hasKey` function if present, and otherwise just does a check using the JavaScript `in` operator.

    test 'objectHasKey verifies if a key is present in an object', ->
      subject = {fit: true}
      ok Batman.objectHasKey(subject, 'fit')
      equal Batman.objectHasKey(subject, 'flirty'), false

    test 'objectHasKey verifies if a key is present in an object with `hasKey` defined', ->
      subject = new Batman.SimpleHash {fit: true}
      ok Batman.objectHasKey(subject, 'fit')
      equal Batman.objectHasKey(subject, 'flirty'), false

## contains(object, item) : boolean

`contains` returns a boolean describing if the given `object` has member `item`. Membership in this context is defined as:

 + the result of `object.has(item)` if the `object` has a `has` function defined
 + the result of `item in object` if the `object` is arraylike
 + the result of the Batman.objectHasKey otherwise

_Note_: When passed an object without a `has` function, `contains` will return `true` if the `object` has `item` as a *`key`*, not as a value at any key.

`contains` is useful for checking item membership when the type of the object can't be relied on.

## get(object, key) : value

`get` is a general purpose function for retrieving the value from a `key` on an `object` of an indeterminate type. This is useful if code needs to work with both `Batman.Object`s and Plain Old JavaScript Objects. `get` has the following semantics:

 + if the `object` has a `get` function defined, return the result of `object.get(key)`
 + if the object does not have a `get` function defined, use an ephemeral `Batman.Property` to retrieve the key. This is equivalent to `object[key]` for single segment `key`s, but if the `key` is multi-segment (example: 'product.customer.name'), `get` will do nested gets until the either `undefined` or the end of the keypath is reached.

    test 'get returns the value at a key on a POJO', ->
      subject = {fit: true}
      equal Batman.get(subject, 'fit'), true
      equal Batman.get(subject, 'flirty'), undefined

    test 'get returns the value at a key on a Batman.Object', ->
      subject = Batman {fit: true}
      equal Batman.get(subject, 'fit'), true
      equal Batman.get(subject, 'flirty'), undefined

    test 'get returns the value at a deep key on a POJO', ->
      subject = {customer: {name: "Joe"}}
      equal Batman.get(subject, 'customer.name'), "Joe"
      equal Batman.get(subject, 'customer.age'), undefined

    test 'get returns the value at a deep key on a Batman.Object', ->
      subject = Batman {customer: {name: "Joe"}}
      equal Batman.get(subject, 'customer.name'), "Joe"
      equal Batman.get(subject, 'customer.age'), undefined

## getPath(base, segments) : string

`getPath` returns the hash value denoted by the specified path, which consists of an array of nested hash keys. See examples below for more detail.

    test "takes a base and an array of keys and returns the corresponding nested value", ->
      @complexObject = new Batman.Object
        hash: new Batman.Hash
          foo: new Batman.Object(bar: 'nested value'),
          "foo.bar": 'flat value'
      equal Batman.getPath(@complexObject, ['hash', 'foo', 'bar']), 'nested value'
      equal Batman.getPath(@complexObject, ['hash', 'foo.bar']), 'flat value'
      strictEqual Batman.getPath(@complexObject, ['hash', 'not-foo', 'bar']), undefined

    test "returns just the base if the key array is empty", ->
      @complexObject = new Batman.Object
        hash: new Batman.Hash
          foo: new Batman.Object(bar: 'nested value'),
          "foo.bar": 'flat value'
      strictEqual Batman.getPath(@complexObject, []), @complexObject
      strictEqual Batman.getPath(null, []), null

    test "returns undefined if the base is null-ish", ->
      @complexObject = new Batman.Object
        hash: new Batman.Hash
          foo: new Batman.Object(bar: 'nested value'),
          "foo.bar": 'flat value'
      strictEqual Batman.getPath(null, ['foo']), undefined
      strictEqual Batman.getPath(undefined, ['foo']), undefined

    test "returns falsy values", ->
      @complexObject = new Batman.Object
        hash: new Batman.Hash
          foo: new Batman.Object(bar: 'nested value'),
          "foo.bar": 'flat value'
      strictEqual Batman.getPath(num: 0, ['num']), 0
      strictEqual Batman.getPath(thing: null, ['thing']), null

## escapeHTML(string) : string

`escapeHTML` takes a string of unknown origin and makes it safe for display on a web page by encoding control characters in HTML into their HTML entities.

*Warning*: Do not rely on `escapeHTML` to purge unsafe data from user submitted content. While `escapeHTML` is applied to every binding's contents by default, it should not be your only line of defence against script injection attacks.

    test 'escapeHTML encodes special characters into HTML entities', ->
      equal Batman.escapeHTML("& < > \" '"), "& < > " '"

# Batman.helpers

`Batman.helpers` is a namespace for Batman's helpful string manipulation helpers.

_Note_: Batman's pluralization functions mirror those of Rails' exactly.

## ordinalize(value : [number|string]) : string

`ordinalize` converts a given integer into an ordinal string for describing position in a list, like 1st, 2nd, or 20th.

    test 'ordinalize converts numbers to their ordinal form', ->
      equal Batman.helpers.ordinalize(1)     , "1st"
      equal Batman.helpers.ordinalize("2")     , "2nd"
      equal Batman.helpers.ordinalize(1002)  , "1002nd"
      equal Batman.helpers.ordinalize("1003")  , "1003rd"
      equal Batman.helpers.ordinalize(-11)   , "-11th"
      equal Batman.helpers.ordinalize(-1021) , "-1021st"

## singularize(pluralString : string) : string

`singularize` converts the plural form of a word to a singular form.

    test 'singularize converts plural words to singular words', ->
      equal Batman.helpers.singularize("posts"), "post"
      equal Batman.helpers.singularize("octopi"), "octopus"
      equal Batman.helpers.singularize("sheep"), "sheep"
      equal Batman.helpers.singularize("word"), "word"
      equal Batman.helpers.singularize("CamelOctopi"), "CamelOctopus"

## pluralize(singularString : string) : string

`pluralize` converts the singular form of a word to the plural form.

    test 'pluralize converts plural words to singular words', ->
      equal Batman.helpers.pluralize("post"), "posts"
      equal Batman.helpers.pluralize("octopus"), "octopi"
      equal Batman.helpers.pluralize("sheep"), "sheep"
      equal Batman.helpers.pluralize("words"), "words"
      equal Batman.helpers.pluralize("CamelOctopus"), "CamelOctopi"

## camelize(string, [lowercaseFirstLetter = false]) : string

`camelize` converts the passed `string` to UpperCamelCase. If the second argument is passed as `true`, then lowerCamelCase is returned.

    test 'camelize returns the CamelCase version of an under_scored word', ->
      equal Batman.helpers.camelize("batman_object"), "BatmanObject"
      equal Batman.helpers.camelize("batman_object", true), "batmanObject"

## underscore(string) : string

`underscore` returns the underscored version of a CamelCase word.

    test 'underscore converts CamelCase to under_scores', ->
      equal Batman.helpers.underscore("BatmanObject"), "batman_object"

## capitalize(string) : string

`capitalize` does a word-wise capitalization of a phrase or word.

    test 'capitalize makes the first letter of each word in the string uppercase', ->
      equal Batman.helpers.capitalize("batmanObject"), "BatmanObject"
      equal Batman.helpers.capitalize("batman object"), "Batman Object"
      equal Batman.helpers.capitalize("AlreadyCapitalized"), "AlreadyCapitalized"

## trim(string) : string

`trim` trims a string getting rid of extra white space around the string or returning an empty string if it is null.

    test 'trim gets rid of space around a string', ->
      equal Batman.helpers.trim("TrimRight "), "TrimRight"
      equal Batman.helpers.trim(" TrimLeft"), "TrimLeft"
      equal Batman.helpers.trim(" TrimBothSides "), "TrimBothSides"
      equal Batman.helpers.trim("AlreadyTrimmed"), "AlreadyTrimmed"

    test 'trim turns a null or undefined string into an empty string', ->
      equal Batman.helpers.trim(null), ""
      equal Batman.helpers.trim(undefined), ""

## interpolate(stringOrObject, keys) : string

`interpolate` interpolates a string, filling it in with values matching interpolation keys, similar to printf variants.

    test 'interpolate fills in key values globally in a string', ->
      equal Batman.helpers.interpolate("%{field} must be at least %{count} characters in order for %{field} to be valid", count: "3", field: "name"), "name must be at least 3 characters in order for name to be valid"

    test 'interpolate fills in key values globally in an object-embedded string', ->
      equal Batman.helpers.interpolate({'other': "%{field} must be at least %{count} characters in order for %{field} to be valid"}, count: "3", field: "name"), "name must be at least 3 characters in order for name to be valid"

    test 'interpolate fills in key values globally in an object-embedded string, embedded by key count', ->
      equal Batman.helpers.interpolate({3: "%{field} must be at least %{count} characters in order for %{field} to be valid"}, count: "3", field: "name"), "name must be at least 3 characters in order for name to be valid"

## humanize(string) : string

`humanize` reformats a string that has a programmatic meaning (camelcased, underscored, "_id" suffixed) to make human-readable by separating concatenated words and/or getting rid of the "_id" suffix.

    test 'humanize replaces underscores and dashes with empty space', ->
      equal Batman.helpers.humanize('underscored_string'), 'Underscored string'
      equal Batman.helpers.humanize('dash-separated-string'), 'Dash separated string'

    test 'humanize splits camel cased words by empty space', ->
      equal Batman.helpers.humanize('CamelCasedString'), 'Camel cased string'

    test 'humanize title-cases the first word', ->
      equal Batman.helpers.humanize('lower case sentence'), 'Lower case sentence'

    test 'humanize lower-cases all words after the first one', ->
      equal Batman.helpers.humanize('Mixed Case SENTENCE'), 'Mixed case sentence'

    test 'humanize gets rid of _id suffix', ->
      equal Batman.helpers.humanize('identifying_string_id'), 'Identifying string'


Update functions.litcoffee

Update functions.litcoffee

### This file

The logic in this file builds the date object.

If you compare this file to the ```python/functions.py``` file
you'll notice they are very similiar. That's intentional,
this file was ported over and kept such that it would be somewhat
easy to port changes back and forth.

### Terminology

Because it's so confusing here is a list of the different levels to refer to:

- Groups
  -- This is the capture groups. The lowest level. ```([0-9])``` etc.
  "Day", "Month", etc.
- Expressions
  -- This is an expression with multiple capture groups. They're usually named
  after the person that wrote them. "Greg Burns", etc.

  In Python, Expressions functions have nice named arguments, def expr(Day, Month, Year),
  but Javascript doesn't support this.
- Type
  -- This is a collection of expressions with a common goal.
  Months (Jan, 0-12, January, etc.).
- Patterns
  -- This is a collection of types ```<Month>/<Day>/<Year>```

### Warning

A note about the above list. Types and Groups are commonly mixed up.
I think groups SHOULD be the lowest
(because they are the actual capture *groups* in regular expressions)
but a group of expressions also makes sense.

It's so confusing that there are at least a couple places here that I've
also mixed myself up and probably in the documentation for RE|PARSE as well.

---

I use named tuples in python, and ```_replace``` mirrors the functionality of
```date._replace```.. that is that it returns a copy of the date with only
certain things changed and leaves the old well enough alone.

        _replace = (_old, _new) ->
            year:   if _new.year? then _new.year else _old.year
            month:  if _new.month? then _new.month else _old.month
            day:    if _new.day? then _new.day  else _old.day
            hour:   if _new.hour? then _new.hour else _old.hour
            minute: if _new.minute? then _new.minute else _old.minute
            second: if _new.second? then _new.second else _old.second
            am_pm:  if _new.am_pm? then _new.am_pm else _old.am_pm

I represent lengths of dates (i.e. Thursday, 1-2pm) with a timedelta that goes right
after the date hash in the result array.

In Javascript, I'm just going to represent a timedelta with a hash.
I make a pretty dumb assumption that timedelta will only cross hour/minutes/second boundaries.

        timedelta_from_Date = (start_time, end_time) ->
            seconds_difference = 0
            if start_time.hour? and end_time.hour?
              seconds_difference += 60*60*(end_time.hour - start_time.hour)

              if start_time.minute? and end_time.minute?
                seconds_difference += 60*(end_time.minute - start_time.minute)

                if start_time.second? and end_time.second?
                  seconds_difference += end_time.second - start_time.second

            hours = Math.floor(seconds_difference/60/60)
            minutes = Math.floor(seconds_difference/60) - (hours * 60)
            seconds = seconds_difference - (minutes * 60) - (hours * 60 * 60)

            return {
               timedelta: true
               hours: hours
               minutes: minutes
               seconds: seconds
            }

This is just a helper function

        in_array = (arr, _) -> arr.indexOf(_) != -1

```progressive_match``` is useful for matching abbreviations
and full spellings. Functions like this could be useful
to help parse fuzzy matches in the future (i.e. misspellings of months).

        progressive_match = (string, possibilities) ->
            part = ""
            if not string? then return
            for character in string.toLowerCase()
                part += character
                matches = []
                for month, value of possibilities
                    if month.indexOf(part) > -1
                        matches.push(month)
                if matches.length == 1
                    return possibilities[matches[0]]
### Types

The heading above is the heading in the python source.
I actually don't know if it's referring to collections of expressions
or capture groups.

        month_to_number = (month_string) ->
          months =
              "january": 1
              "february": 2
              "march": 3
              "april": 4
              "may": 5
              "june": 6
              "july": 7
              "august": 8
              "september": 9
              "october": 10
              "november": 11
              "december": 12
           return progressive_match(month_string, months)

        weekday_to_number = (WeekdayString ) ->
            weekday_list = {
                "monday": 0,
                "tuesday": 1,
                "wednesday": 2,
                "thursday": 3,
                "friday": 4,
                "saturday": 5,
                "sunday": 6,
            }
            return progressive_match(WeekdayString, weekday_list)

I serialize am_pm by converting the hours to milliary/24-hour time format.
I also include ```am_pm: 'pm'``` in the date format to show that that transformation
was done. Making that clear helpful because if you get a time like 1, with no ```am_pm```
designation you might want to assume pm and add 12. This is not done in the libary because
date_machine strives for honesty, not guesswork.

        am_pm = (input) ->
            if not input?
              return
            if input.toLowerCase() == "am" then 0
            else if input.toLowerCase() == "pm" then 12

You can see in this function that I try not to repeat logic and use other
functions. In this case I might have been able to simply put time_expression
in the functions hash/object, but in python it makes a difference due to named arguments.
I'm going to leave it as-is for clarity.

        military_time = (MilHour, MilMinute, MilSecond ) ->
            return time_expression(MilHour, MilMinute, MilSecond, undefined)

Here is the ampm conversion. I omit returns when the expressions are simple,
but later on I want to use them as much as possible to make my intentions clear.

        noon = (hour, AMPM) -> hour == 12 and AMPM == 12
        midnight = (hour, AMPM) -> hour == 12 and AMPM == 0

        time_expression = (Hour, Minute, Second, AMPM, SpecialTimeText ) ->
            if not Hour? and not Minute? and not Second? and not AMPM? and not SpecialTimeText?
                return
            if SpecialTimeText
                if SpecialTimeText.toLowerCase() == "noon"
                    return {hour: 12}
                if SpecialTimeText.toLowerCase() == "midnight"
                    return {hour: 0}
            d = {}
            if Hour
                d.hour = Number(Hour)
            if Minute
                d.minute = Number(Minute)
            if Second
                d.second = Number(Second)
            if AMPM?
                if d.hour
                    if noon(d.hour, AMPM)
                        d.hour = 12
                    else if midnight(d.hour, AMPM)
                        d.hour = 0
                    else
                        d.hour = d.hour + AMPM
                d.am_pm = AMPM
            if [d.hour, d.minute, d.second] == [undefined, undefined, undefined]
                return undefined
            return d

        time_and_time = (Hour, Minute, AMPM1, Hour2, Minute2, AMPM2) ->
            if AMPM2?
                AMPM2 = am_pm(AMPM2)
            if not AMPM1? and not AMPM2?
                return [time_expression(Hour, Minute), time_expression(Hour2, Minute2)]
            else if not AMPM1?
                return [time_expression(Hour, Minute, undefined, AMPM2),
                        time_expression(Hour2, Minute2, undefined, AMPM2)]
            else if not AMPM2?
                return [time_expression(Hour, Minute, undefined, AMPM1),
                        time_expression(Hour2, Minute2, undefined, AMPM1)]

        month_type = (input...) ->
            for value in input
                if value?
                    return Number(value)

        date_number = (Day, Abbr) -> if Day? then Number(Day)

        month_number = (MonthNum) -> Number(MonthNum)

        month_num_type = (input) -> Number(input)

        year = (Year) -> if Year? then Number(Year)

Sometimes the value is [undefined, undefined, <value>],
so I need to search for it and find it.

        get_first_defined = (_) ->
          for item in _
            if item?
              return item

### Patterns

There's a some unwrapping values out of arrays here.
Because of the namedarguments issue functions receive a lot more
arrays then in Python and so they need to be unwrapped.

        weekday_range_with_time = (time1, time2, [weekday1], [weekday2], MonthRange) ->
            output = []

            # Get first undefined value
            # Since only one value in list will be defined (if any)
            time1 = get_first_defined(time1)
            time2 = get_first_defined(time2)

            if time1?
                for date in MonthRange
                    output.push(_replace(date, time1))
                    if time2?
                        output.push(_replace(date, time2))
            return output

        weekday_range_with_extra = ( time, and_time, weekday_start, weekday_end, extra_time, extra_weekday, MonthRange) ->
            output = []
            if time?
                for date in MonthRange
                    if date.weekday?
                        if date.weekday in [weekday_start .. weekday_end]
                            output.push(_replace(date, time))
                            if and_time?
                                output.push(_replace(date, and_time))
                        if date.weekday == extra_weekday
                            output.push(_replace(date, extra_time))
            return output

        weekday_range_with_extra_backwards = (extra_time, extra_weekday, time, weekday_start, weekday_end, MonthRange ) ->
            return weekday_range_with_extra(time[0], time[1], weekday_start, weekday_end, extra_time, extra_weekday, MonthRange )

        reverse_basic_text = (time, day, month, year) ->
            return basic_text(time, undefined, undefined, month, day, year)

        basic_text = (time, first_second, weekday, month, day, year) ->
            if not day?
                day = 1
            if (day instanceof Array) and day.length == 1
              day = day[0]
            if (year instanceof Array) and year.length == 1
              year = year[0]
            if not time?
                return {year: year, month: month, day: day}
            else
                year: year
                month: month
                day: day
                hour: time.hour
                minute: time.minute
                second: time.second
                am_pm: time.am_pm

        slash = (month, day, year, time) ->
            return basic_text(time, undefined, undefined, month, day, year)

        month_range = (month, date_a, date_b) ->
            output = []
            for day in [date_a .. date_b]
                output.push(basic_text(undefined, undefined, undefined, month, day, undefined))
            return output

        multi_time = (time1, BasicText) ->
            output = []
            if time1? and BasicText?
                output.push(_replace(BasicText, time1))
                output.push(BasicText)
                return output

        large_repeat_words = ->
            return undefined

        weekday_range_with_time_range = (time1, weekday_range) ->
            output = []
            if time1? and weekday_range?
                range = timedelta_from_Date(_replace(weekday_range[0], time1), weekday_range[0])
                for weekday in weekday_range
                    output.push(_replace(weekday, {hour:time1.hour, minute:time1.minute, am_pm:time1.am_pm}))
                    output.push(range)
                return output

        time_range = (unstrict_time, strict_time, date, reverse) ->
            endtime = date
            starttime = endtime
            if unstrict_time
                starttime = _replace(starttime, {hour:Number(unstrict_time[0])})
                if date.am_pm
                    starttime = _replace(starttime, {hour: starttime.hour + date.am_pm, am_pm:date.am_pm})
            else
                starttime = _replace(starttime, {hour: strict_time.hour, minute: strict_time.minute})

            time_range = timedelta_from_Date(starttime, endtime)
            if reverse
                time_range = timedelta_from_Date(endtime, starttime)
            return [starttime, time_range]

        alt_time_range = (first_second, weekday, month, day, year, time, unstrict_time, strict_time) ->
            return time_range(unstrict_time, strict_time, basic_text(time, first_second, weekday, month, day, year), reverse)

        until_range = (date1, date2) ->
            if date1 and date2
                return [date1, timedelta_from_Date(date1, date2)]

        through_range = (time, weekday1, weekday2, month, date, beginning) ->
            output = []
            if month and date and beginning and weekday1
                ending =
                    month: month
                    day: date
                for day in [beginning.day .. ending.day]
                    temp =
                        month: month
                        day: date
                    if temp.weekday and in_array([weekday1 .. weekday2], temp.weekday)
                        if time
                            output.push(_replace(temp, time))
                        else
                            output.push(temp)
                return output

### The function list

This hash/object matches all the functions with a
string that represents it in the parse tree.

        functions =
            # Groups
            "MonthString": month_to_number,
            "AMPM": am_pm,
            # Expressions
            "Chase Year": year,
            "Chase Date": date_number,
            "Chase Month": month_number,
            "Steve Valaitis": time_expression,
            "Greg Burns": (hour, am_pm) -> time_expression(hour, null, null, am_pm, null),
            "Greg Burns UnstrictTime:": time_expression,
            "Steve Valaitis2": military_time,
            "Steve Valaitis And Time": time_and_time,
            "Text Parts": time_expression,
            "Michael Ash10": weekday_to_number,
            # Types
            "Month": month_type,
            "MonthNum": month_num_type,
            # Patterns
            "LargeRepeatWords": large_repeat_words,
            "BasicText": basic_text,
            "ReverseBasicText": reverse_basic_text,
            "Slash": slash,
            "MonthRange": month_range,
            "MultiTime": multi_time,
            "WeekdayRangeWithTime": weekday_range_with_time,
            "WeekdayRangeWithExtra": weekday_range_with_extra,
            "WeekdayRangeWithExtraBackwards": weekday_range_with_extra_backwards,
            "WeekdayRangeWithTimeRange": weekday_range_with_time_range,
            "UntilRange": until_range,
            "ThroughRange": through_range,
            "TimeRange": time_range,
            "AltTimeRange": alt_time_range,

This is default expression or pattern. ```any``` means
if value is defined, and there is array with even a single defined value then return true.

            "_default": (_) ->
                if any(_) then _ else undefined

```Type``` there is used to mean collection of expressions.
I know that because only one will match, so you just have to find
it and return it.

            "_default_type": (_...) ->
                if _?
                    for item in _
                         if item?
                             return item

            "_default_group": (_...) -> if _[0]? then _[0]

### This file

The logic in this file builds the date object.

If you compare this file to the ```python/functions.py``` file
you'll notice they are very similiar. That's intentional,
this file was ported over and kept such that it would be somewhat
easy to port changes back and forth.

### Terminology

Because it's so confusing here is a list of the different levels to refer to:

- Groups
  -- This is the capture groups. The lowest level. ```([0-9])``` etc.
  "Day", "Month", etc.
- Expressions
  -- This is an expression with multiple capture groups. They're usually named
  after the person that wrote them. "Greg Burns", etc.

  In Python, Expressions functions have nice named arguments, def expr(Day, Month, Year),
  but Javascript doesn't support this.
- Type
  -- This is a collection of expressions with a common goal.
  Months (Jan, 0-12, January, etc.).
- Patterns
  -- This is a collection of types ```<Month>/<Day>/<Year>```

### Warning

A note about the above list. Types and Groups are commonly mixed up.
I think groups SHOULD be the lowest
(because they are the actual capture *groups* in regular expressions)
but a group of expressions also makes sense.

It's so confusing that there are at least a couple places here that I've
also mixed myself up and probably in the documentation for RE|PARSE as well.

---

I use named tuples in python, and _replace mirrors the functionality of
date._replace.. that is that it returns a copy of the date with only
certain things changed and leaves the old well enough alone.

        _replace = (_old, _new) ->
            year:   if _new.year? then _new.year else _old.year
            month:  if _new.month? then _new.month else _old.month
            day:    if _new.day? then _new.day  else _old.day
            hour:   if _new.hour? then _new.hour else _old.hour
            minute: if _new.minute? then _new.minute else _old.minute
            second: if _new.second? then _new.second else _old.second
            am_pm:  if _new.am_pm? then _new.am_pm else _old.am_pm

I represent lengths of dates (i.e. Thursday, 1-2pm) with a timedelta that goes right
after the date hash in the result array.

In Javascript, I'm just going to represent a timedelta with a hash.
I make a pretty dumb assumption that timedelta will only cross hour/minutes/second boundaries.

        timedelta_from_Date = (start_time, end_time) ->
            seconds_difference = 0
            if start_time.hour? and end_time.hour?
              seconds_difference += 60*60*(end_time.hour - start_time.hour)

              if start_time.minute? and end_time.minute?
                seconds_difference += 60*(end_time.minute - start_time.minute)

                if start_time.second? and end_time.second?
                  seconds_difference += end_time.second - start_time.second

            hours = Math.floor(seconds_difference/60/60)
            minutes = Math.floor(seconds_difference/60) - (hours * 60)
            seconds = seconds_difference - (minutes * 60) - (hours * 60 * 60)

            return {
               timedelta: true
               hours: hours
               minutes: minutes
               seconds: seconds
            }

This is just a helper function

        in_array = (arr, _) -> arr.indexOf(_) != -1

```progressive_match``` is useful for matching abbreviations
and full spellings. Functions like this could be useful
to help parse fuzzy matches in the future (i.e. misspellings of months).

        progressive_match = (string, possibilities) ->
            part = ""
            if not string? then return
            for character in string.toLowerCase()
                part += character
                matches = []
                for month, value of possibilities
                    if month.indexOf(part) > -1
                        matches.push(month)
                if matches.length == 1
                    return possibilities[matches[0]]
### Types

The heading above is the heading in the python source.
I actually don't know if it's referring to collections of expressions
or capture groups.

        month_to_number = (month_string) ->
          months =
              "january": 1
              "february": 2
              "march": 3
              "april": 4
              "may": 5
              "june": 6
              "july": 7
              "august": 8
              "september": 9
              "october": 10
              "november": 11
              "december": 12
           return progressive_match(month_string, months)

        weekday_to_number = (WeekdayString ) ->
            weekday_list = {
                "monday": 0,
                "tuesday": 1,
                "wednesday": 2,
                "thursday": 3,
                "friday": 4,
                "saturday": 5,
                "sunday": 6,
            }
            return progressive_match(WeekdayString, weekday_list)

I serialize am_pm by converting the hours to milliary/24-hour time format.
I also include ```am_pm: 'pm'``` in the date format to show that that transformation
was done. Making that clear helpful because if you get a time like 1, with no ```am_pm```
designation you might want to assume pm and add 12. This is not done in the libary because
date_machine strives for honesty, not guesswork.

        am_pm = (input) ->
            if not input?
              return
            if input.toLowerCase() == "am" then 0
            else if input.toLowerCase() == "pm" then 12

You can see in this function that I try not to repeat logic and use other
functions. In this case I might have been able to simply put time_expression
in the functions hash/object, but in python it makes a difference due to named arguments.
I'm going to leave it as-is for clarity.

        military_time = (MilHour, MilMinute, MilSecond ) ->
            return time_expression(MilHour, MilMinute, MilSecond, undefined)

Here is the ampm conversion. I omit returns when the expressions are simple,
but later on I want to use them as much as possible to make my intentions clear.

        noon = (hour, AMPM) -> hour == 12 and AMPM == 12
        midnight = (hour, AMPM) -> hour == 12 and AMPM == 0

        time_expression = (Hour, Minute, Second, AMPM, SpecialTimeText ) ->
            if not Hour? and not Minute? and not Second? and not AMPM? and not SpecialTimeText?
                return
            if SpecialTimeText
                if SpecialTimeText.toLowerCase() == "noon"
                    return {hour: 12}
                if SpecialTimeText.toLowerCase() == "midnight"
                    return {hour: 0}
            d = {}
            if Hour
                d.hour = Number(Hour)
            if Minute
                d.minute = Number(Minute)
            if Second
                d.second = Number(Second)
            if AMPM?
                if d.hour
                    if noon(d.hour, AMPM)
                        d.hour = 12
                    else if midnight(d.hour, AMPM)
                        d.hour = 0
                    else
                        d.hour = d.hour + AMPM
                d.am_pm = AMPM
            if [d.hour, d.minute, d.second] == [undefined, undefined, undefined]
                return undefined
            return d

        time_and_time = (Hour, Minute, AMPM1, Hour2, Minute2, AMPM2) ->
            if AMPM2?
                AMPM2 = am_pm(AMPM2)
            if not AMPM1? and not AMPM2?
                return [time_expression(Hour, Minute), time_expression(Hour2, Minute2)]
            else if not AMPM1?
                return [time_expression(Hour, Minute, undefined, AMPM2),
                        time_expression(Hour2, Minute2, undefined, AMPM2)]
            else if not AMPM2?
                return [time_expression(Hour, Minute, undefined, AMPM1),
                        time_expression(Hour2, Minute2, undefined, AMPM1)]

        month_type = (input...) ->
            for value in input
                if value?
                    return Number(value)

        date_number = (Day, Abbr) -> if Day? then Number(Day)

        month_number = (MonthNum) -> Number(MonthNum)

        month_num_type = (input) -> Number(input)

        year = (Year) -> if Year? then Number(Year)

Sometimes the value is [undefined, undefined, <value>],
so I need to search for it and find it.

        get_first_defined = (_) ->
          for item in _
            if item?
              return item

### Patterns

There's a some unwrapping values out of arrays here.
Because of the namedarguments issue functions receive a lot more
arrays then in Python and so they need to be unwrapped.

        weekday_range_with_time = (time1, time2, [weekday1], [weekday2], MonthRange) ->
            output = []

            # Get first undefined value
            # Since only one value in list will be defined (if any)
            time1 = get_first_defined(time1)
            time2 = get_first_defined(time2)

            if time1?
                for date in MonthRange
                    output.push(_replace(date, time1))
                    if time2?
                        output.push(_replace(date, time2))
            return output

        weekday_range_with_extra = ( time, and_time, weekday_start, weekday_end, extra_time, extra_weekday, MonthRange) ->
            output = []
            if time?
                for date in MonthRange
                    if date.weekday?
                        if date.weekday in [weekday_start .. weekday_end]
                            output.push(_replace(date, time))
                            if and_time?
                                output.push(_replace(date, and_time))
                        if date.weekday == extra_weekday
                            output.push(_replace(date, extra_time))
            return output

        weekday_range_with_extra_backwards = (extra_time, extra_weekday, time, weekday_start, weekday_end, MonthRange ) ->
            return weekday_range_with_extra(time[0], time[1], weekday_start, weekday_end, extra_time, extra_weekday, MonthRange )

        reverse_basic_text = (time, day, month, year) ->
            return basic_text(time, undefined, undefined, month, day, year)

        basic_text = (time, first_second, weekday, month, day, year) ->
            if not day?
                day = 1
            if (day instanceof Array) and day.length == 1
              day = day[0]
            if (year instanceof Array) and year.length == 1
              year = year[0]
            if not time?
                return {year: year, month: month, day: day}
            else
                year: year
                month: month
                day: day
                hour: time.hour
                minute: time.minute
                second: time.second
                am_pm: time.am_pm

        slash = (month, day, year, time) ->
            return basic_text(time, undefined, undefined, month, day, year)

        month_range = (month, date_a, date_b) ->
            output = []
            for day in [date_a .. date_b]
                output.push(basic_text(undefined, undefined, undefined, month, day, undefined))
            return output

        multi_time = (time1, BasicText) ->
            output = []
            if time1? and BasicText?
                output.push(_replace(BasicText, time1))
                output.push(BasicText)
                return output

        large_repeat_words = ->
            return undefined

        weekday_range_with_time_range = (time1, weekday_range) ->
            output = []
            if time1? and weekday_range?
                range = timedelta_from_Date(_replace(weekday_range[0], time1), weekday_range[0])
                for weekday in weekday_range
                    output.push(_replace(weekday, {hour:time1.hour, minute:time1.minute, am_pm:time1.am_pm}))
                    output.push(range)
                return output

        time_range = (unstrict_time, strict_time, date, reverse) ->
            endtime = date
            starttime = endtime
            if unstrict_time
                starttime = _replace(starttime, {hour:Number(unstrict_time[0])})
                if date.am_pm
                    starttime = _replace(starttime, {hour: starttime.hour + date.am_pm, am_pm:date.am_pm})
            else
                starttime = _replace(starttime, {hour: strict_time.hour, minute: strict_time.minute})

            time_range = timedelta_from_Date(starttime, endtime)
            if reverse
                time_range = timedelta_from_Date(endtime, starttime)
            return [starttime, time_range]

        alt_time_range = (first_second, weekday, month, day, year, time, unstrict_time, strict_time) ->
            return time_range(unstrict_time, strict_time, basic_text(time, first_second, weekday, month, day, year), reverse)

        until_range = (date1, date2) ->
            if date1 and date2
                return [date1, timedelta_from_Date(date1, date2)]

        through_range = (time, weekday1, weekday2, month, date, beginning) ->
            output = []
            if month and date and beginning and weekday1
                ending =
                    month: month
                    day: date
                for day in [beginning.day .. ending.day]
                    temp =
                        month: month
                        day: date
                    if temp.weekday and in_array([weekday1 .. weekday2], temp.weekday)
                        if time
                            output.push(_replace(temp, time))
                        else
                            output.push(temp)
                return output

### The function list

This hash/object matches all the functions with a
string that represents it in the parse tree.

        functions =
            # Groups
            "MonthString": month_to_number,
            "AMPM": am_pm,
            # Expressions
            "Chase Year": year,
            "Chase Date": date_number,
            "Chase Month": month_number,
            "Steve Valaitis": time_expression,
            "Greg Burns": (hour, am_pm) -> time_expression(hour, null, null, am_pm, null),
            "Greg Burns UnstrictTime:": time_expression,
            "Steve Valaitis2": military_time,
            "Steve Valaitis And Time": time_and_time,
            "Text Parts": time_expression,
            "Michael Ash10": weekday_to_number,
            # Types
            "Month": month_type,
            "MonthNum": month_num_type,
            # Patterns
            "LargeRepeatWords": large_repeat_words,
            "BasicText": basic_text,
            "ReverseBasicText": reverse_basic_text,
            "Slash": slash,
            "MonthRange": month_range,
            "MultiTime": multi_time,
            "WeekdayRangeWithTime": weekday_range_with_time,
            "WeekdayRangeWithExtra": weekday_range_with_extra,
            "WeekdayRangeWithExtraBackwards": weekday_range_with_extra_backwards,
            "WeekdayRangeWithTimeRange": weekday_range_with_time_range,
            "UntilRange": until_range,
            "ThroughRange": through_range,
            "TimeRange": time_range,
            "AltTimeRange": alt_time_range,

This is default expression or pattern. ```any``` means
if value is defined, and there is array with even a single defined value then return true.

            "_default": (_) ->
                if any(_) then _ else undefined

```Type``` there is used to mean collection of expressions.
I know that because only one will match, so you just have to find
it and return it.

            "_default_type": (_...) ->
                if _?
                    for item in _
                         if item?
                             return item

            "_default_group": (_...) -> if _[0]? then _[0]


Add docs for Batman model associations

Add docs for Batman model associations

# Batman.Model Associations

There are 3 types of assocations available on `Batman.Model`: `hasMany`, `belongsTo`, and `hasOne`.

## Batman.AssocationProxy

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

`Batman.AssociationProxy` defines useful methods such as `@load`, `@toJSON`, `@loadFromLocal`. It also defines accessors such as `%loaded` and `%target`.

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

##### `saveInline[= true] : boolean`
Whether we should save the child objects as part of the parent object's JSON

##### `autoload[= true] : boolean`
 Whether we should load the child objects when loading the parent object.

##### `nestUrl[= false] : boolean`
Whether the child models are persisted beneath the parent models url structure.

##### `name : String`
The name of the child model for the association. (eg. App.Product)

##### `inverseOf : String`
The foreign association to set on load.

##### `encoderKey : String`
The key to encode and decode the assocation into/from JSON.

##### `namespace[= Batman.currentApp] : String`
The location of the model definition for the association.

##### `polymorphic[= false] : boolean`
Whether the association is polymorphic.

## @hasMany(label[, options])
`hasMany` assocations are used for expressing one-to-many relationships on a `Batman.Model`.

- `label : String`
- `options : Object`
  - `primaryKey : String`
  - `foreignKey : String`
  - `as : String`
    - the parent association name on child objects in a polymorphic association

## @hasOne(label[, options])
`hasOne` associations are used for expressing one-to-one relationships on a `Batman.Model`.

- `label : String`
- `options : Object`
  - `primaryKey : String`
  - `foreignKey : String`
  - `as : String`
    - the parent association name on child objects in a polymorphic association

## @belongsTo(label[, options])
`belongsTo` associatons are used fro expressing one-to-one child relationships on a `Batman.Model`.

- `label : String`
- `options : Object`
  - `primaryKey : String`
  - `foreignKey : String`
  - `encodeForeignKey[= true] boolean`
    - whether to encode the foreignKey value when persisting the model