batman-rails 0.15.4 → 0.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +34 -11
- data/lib/batman-rails.rb +6 -0
- data/lib/batman-rails/helpers/define_view_helper.rb +45 -0
- data/lib/batman-rails/version.rb +2 -2
- data/lib/generators/batman/app_generator.rb +10 -0
- data/lib/generators/common.rb +1 -1
- data/lib/templates/rails/controller.rb +7 -1
- data/test/define_view_helper_test.rb +18 -0
- data/vendor/assets/javascripts/batman/batman.i18n.js +140 -0
- data/vendor/assets/javascripts/batman/batman.js +2705 -264
- data/vendor/assets/javascripts/batman/batman.rails.js +6 -2
- data/vendor/assets/javascripts/batman/batman.testing.js +8524 -0
- metadata +8 -3
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA1:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 9c8deae7a6dad1d59f1cb67e92a798e50414598d
         | 
| 4 | 
            +
              data.tar.gz: a7b266ed03e94f18b5db5b585e4de18138e9510a
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: a69ac93e5f28fc771eae9177305d3cc7c821d8a8f15a01220785b1562930f16b0577187f62c54185739cbf82af8ce27b435bc381eee4d795a18c136f276e896e
         | 
| 7 | 
            +
              data.tar.gz: 2bd249704f4a95b3dc1bf3fc4acf8e94a7d09788cf362ff4b01b833a4924a4b0cec9883d16707fa134c972226732413609077ae29d682da5ea2bee6e282f0991
         | 
    
        data/README.md
    CHANGED
    
    | @@ -1,6 +1,6 @@ | |
| 1 1 | 
             
            # Batman::Rails
         | 
| 2 2 |  | 
| 3 | 
            -
            Easily setup and use batman.js (0. | 
| 3 | 
            +
            Easily setup and use batman.js (0.16) with Rails 4
         | 
| 4 4 |  | 
| 5 5 | 
             
            ## Installation
         | 
| 6 6 |  | 
| @@ -15,25 +15,32 @@ And then execute: | |
| 15 15 |  | 
| 16 16 | 
             
            ### Layout and namespacing
         | 
| 17 17 |  | 
| 18 | 
            -
            Running `rails generate batman:app` will | 
| 18 | 
            +
            Running `rails generate batman:app` will:
         | 
| 19 19 |  | 
| 20 | 
            -
             | 
| 21 | 
            -
             | 
| 22 | 
            -
             | 
| 23 | 
            -
             | 
| 24 | 
            -
             | 
| 20 | 
            +
            - create the following directory structure under `app/assets/batman/`:
         | 
| 21 | 
            +
              
         | 
| 22 | 
            +
              ``` 
         | 
| 23 | 
            +
                  - models/
         | 
| 24 | 
            +
                  - views/
         | 
| 25 | 
            +
                  - controllers/
         | 
| 26 | 
            +
                  - html/
         | 
| 27 | 
            +
                  - lib/
         | 
| 28 | 
            +
                  - app_name.coffee # initial setup & requires
         | 
| 29 | 
            +
              ```
         | 
| 25 30 |  | 
| 26 | 
            -
             | 
| 31 | 
            +
            - create a controller & route to server your batman.js app from `/` and serve HTML 
         | 
| 32 | 
            +
            - configure the asset pipeline to precompile `app_name.coffee`
         | 
| 27 33 |  | 
| 28 34 | 
             
            ## Generators
         | 
| 29 | 
            -
             | 
| 30 | 
            -
             | 
| 35 | 
            +
             | 
| 36 | 
            +
            Batman-Rails provides 3 simple generators to help get you started using batman.js with Rails.
         | 
| 37 | 
            +
            The generators will only create client-side code (CoffeeScript).
         | 
| 31 38 |  | 
| 32 39 | 
             
            ### Model Generator
         | 
| 33 40 |  | 
| 34 41 | 
             
                rails generate batman:model
         | 
| 35 42 |  | 
| 36 | 
            -
            This generator creates a batman model inside `app/assets/ | 
| 43 | 
            +
            This generator creates a batman model inside `app/assets/batman/models` to be used to talk to the Rails backend.
         | 
| 37 44 |  | 
| 38 45 | 
             
            ### Controllers
         | 
| 39 46 |  | 
| @@ -67,6 +74,22 @@ Install the gem and generate scaffolding. | |
| 67 74 |  | 
| 68 75 | 
             
            You now have installed the `batman-rails` gem, setup a default directory structure for your frontend batman code. Then you generated the usual Rails server side scaffolding and finally generated Batman.js code to provide a simple single page app.
         | 
| 69 76 |  | 
| 77 | 
            +
            ## Precompiling Views
         | 
| 78 | 
            +
             | 
| 79 | 
            +
            In production, you may want to send all your HTML templates with the first request rather than sending them as-needed. `batman-rails` includes a view helper to do this. Add it to your application layout:
         | 
| 80 | 
            +
             | 
| 81 | 
            +
            ```erb
         | 
| 82 | 
            +
                <%= batman_define_views %>
         | 
| 83 | 
            +
            ```
         | 
| 84 | 
            +
             | 
| 85 | 
            +
            It will gather HTML from `app/assets/batman/html` and interpolate them into JS code to preload `Batman.View.store`. If your HTML is in another directory, pass that directory as an option:
         | 
| 86 | 
            +
             | 
| 87 | 
            +
            ```erb
         | 
| 88 | 
            +
              <%= batman_define_views(path_to_html: "app/assets/templates/">
         | 
| 89 | 
            +
            ```
         | 
| 90 | 
            +
             | 
| 91 | 
            +
            Now it will gather HTML from `app/assets/templates`!
         | 
| 92 | 
            +
             | 
| 70 93 | 
             
            ## Contributing
         | 
| 71 94 |  | 
| 72 95 | 
             
            1. Fork it
         | 
    
        data/lib/batman-rails.rb
    CHANGED
    
    | @@ -1,8 +1,14 @@ | |
| 1 1 | 
             
            require "batman-rails/version"
         | 
| 2 | 
            +
            require "batman-rails/helpers/define_view_helper"
         | 
| 2 3 |  | 
| 3 4 | 
             
            module Batman
         | 
| 4 5 | 
             
              module Rails
         | 
| 5 6 | 
             
                class Engine < ::Rails::Engine
         | 
| 7 | 
            +
                  initializer 'batman_rails.action_controller' do |app|
         | 
| 8 | 
            +
                    ActiveSupport.on_load :action_controller do
         | 
| 9 | 
            +
                      helper Batman::DefineViewHelper
         | 
| 10 | 
            +
                    end
         | 
| 11 | 
            +
                  end
         | 
| 6 12 | 
             
                end
         | 
| 7 13 | 
             
              end
         | 
| 8 14 | 
             
            end
         | 
| @@ -0,0 +1,45 @@ | |
| 1 | 
            +
            module Batman
         | 
| 2 | 
            +
              module DefineViewHelper
         | 
| 3 | 
            +
                def batman_define_views(options={})
         | 
| 4 | 
            +
                  content_tag :script do
         | 
| 5 | 
            +
                    template_js_string = BatmanView.all(self, options).map(&:inline_preload_javascript).join
         | 
| 6 | 
            +
                    raw %Q[(function(){#{template_js_string}})();]
         | 
| 7 | 
            +
                  end
         | 
| 8 | 
            +
                end
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                class BatmanView
         | 
| 11 | 
            +
                  PATH_TO_HTML = "app/assets/batman/html/"
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                  attr_accessor :pathname, :render_context, :path_to_html
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                  def self.all(render_context, options={})
         | 
| 16 | 
            +
                    path_to_html = options[:path_to_html] || PATH_TO_HTML
         | 
| 17 | 
            +
                    glob_path = File.join(path_to_html, "**/*")
         | 
| 18 | 
            +
                    valid_files = Dir.glob(glob_path).select { |pathname| File.file?(pathname) }
         | 
| 19 | 
            +
                    valid_files.collect do |pathname|
         | 
| 20 | 
            +
                      new(pathname, render_context, path_to_html: path_to_html)
         | 
| 21 | 
            +
                    end
         | 
| 22 | 
            +
                  end
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                  def initialize(pathname, render_context, options={})
         | 
| 25 | 
            +
                    @pathname = pathname
         | 
| 26 | 
            +
                    @render_context = render_context
         | 
| 27 | 
            +
                    @path_to_html = options[:path_to_html] || PATH_TO_HTML
         | 
| 28 | 
            +
                  end
         | 
| 29 | 
            +
             | 
| 30 | 
            +
                  def inline_preload_javascript
         | 
| 31 | 
            +
                    %Q{Batman.View.store.set(#{name.to_json}, #{content.to_json});}
         | 
| 32 | 
            +
                  end
         | 
| 33 | 
            +
             | 
| 34 | 
            +
                  private
         | 
| 35 | 
            +
             | 
| 36 | 
            +
                  def name
         | 
| 37 | 
            +
                    pathname.split(path_to_html).last.gsub(/\.html\.[a-z]+$/, '').to_s
         | 
| 38 | 
            +
                  end
         | 
| 39 | 
            +
             | 
| 40 | 
            +
                  def content
         | 
| 41 | 
            +
                    render_context.render(file: pathname)
         | 
| 42 | 
            +
                  end
         | 
| 43 | 
            +
                end
         | 
| 44 | 
            +
              end
         | 
| 45 | 
            +
            end
         | 
    
        data/lib/batman-rails/version.rb
    CHANGED
    
    
| @@ -26,6 +26,10 @@ module Batman | |
| 26 26 | 
             
                        inject_into_file "config/routes.rb", :after => "#{js_application_name}::Application.routes.draw do\n"  do
         | 
| 27 27 | 
             
                          route_catchall
         | 
| 28 28 | 
             
                        end
         | 
| 29 | 
            +
             | 
| 30 | 
            +
                        inject_into_file "config/application.rb", :after => "class Application < Rails::Application\n" do
         | 
| 31 | 
            +
                          precompile_app
         | 
| 32 | 
            +
                        end
         | 
| 29 33 | 
             
                      end
         | 
| 30 34 |  | 
| 31 35 | 
             
                    end
         | 
| @@ -72,6 +76,12 @@ module Batman | |
| 72 76 | 
             
            CODE
         | 
| 73 77 | 
             
                  end
         | 
| 74 78 |  | 
| 79 | 
            +
                  def precompile_app
         | 
| 80 | 
            +
            <<-CODE
         | 
| 81 | 
            +
            \n    config.assets.precompile += ['#{application_name}.js']\n
         | 
| 82 | 
            +
            CODE
         | 
| 83 | 
            +
                  end
         | 
| 84 | 
            +
             | 
| 75 85 | 
             
                  def es5_requires
         | 
| 76 86 | 
             
            <<-CODE
         | 
| 77 87 | 
             
            #= require batman/es5-shim\n
         | 
    
        data/lib/generators/common.rb
    CHANGED
    
    | @@ -51,7 +51,7 @@ module Batman | |
| 51 51 | 
             
                  module ClassMethods
         | 
| 52 52 | 
             
                    def requires_app_name
         | 
| 53 53 | 
             
                      class_option :app_name, :type => :string, :optional => true,
         | 
| 54 | 
            -
                                   :desc => "Name of the Batman app (defaults to the Rails app name"
         | 
| 54 | 
            +
                                   :desc => "Name of the Batman app (defaults to the Rails app name)"
         | 
| 55 55 | 
             
                    end
         | 
| 56 56 | 
             
                  end
         | 
| 57 57 | 
             
                end
         | 
| @@ -1,7 +1,13 @@ | |
| 1 1 | 
             
            class <%= js_app_name %>Controller < ApplicationController
         | 
| 2 2 |  | 
| 3 3 | 
             
              def index
         | 
| 4 | 
            -
                 | 
| 4 | 
            +
                if request.xhr?
         | 
| 5 | 
            +
                  prefix_length = Rails.application.config.assets.prefix.length + 1
         | 
| 6 | 
            +
                  path = request.path[prefix_length..-1]
         | 
| 7 | 
            +
                  render :text => Rails.application.assets[path]
         | 
| 8 | 
            +
                else
         | 
| 9 | 
            +
                  render nothing: true, layout: '<%= app_name %>'
         | 
| 10 | 
            +
                end
         | 
| 5 11 | 
             
              end
         | 
| 6 12 |  | 
| 7 13 | 
             
            end
         | 
| @@ -0,0 +1,18 @@ | |
| 1 | 
            +
            require 'test_helper'
         | 
| 2 | 
            +
            require 'generators/batman/view_generator'
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            class DefineViewHelperTest < ActionView::TestCase
         | 
| 5 | 
            +
              include Batman::DefineViewHelper
         | 
| 6 | 
            +
              tests Batman::DefineViewHelper
         | 
| 7 | 
            +
             | 
| 8 | 
            +
              test "it defaults to looking in app/assets/batman/html" do
         | 
| 9 | 
            +
                File.expects(:join).with("app/assets/batman/html/", "**/*").returns("app/assets/batman/html/**/*")
         | 
| 10 | 
            +
                batman_define_views
         | 
| 11 | 
            +
              end
         | 
| 12 | 
            +
             | 
| 13 | 
            +
              test "it can be given override path" do
         | 
| 14 | 
            +
                File.expects(:join).with("app/assets/batman/templates/", "**/*").returns("app/assets/batman/templates/**/*")
         | 
| 15 | 
            +
                batman_define_views(path_to_html: "app/assets/batman/templates")
         | 
| 16 | 
            +
              end
         | 
| 17 | 
            +
             | 
| 18 | 
            +
            end
         | 
| @@ -0,0 +1,140 @@ | |
| 1 | 
            +
            (function() {
         | 
| 2 | 
            +
              var __hasProp = {}.hasOwnProperty,
         | 
| 3 | 
            +
                __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
         | 
| 4 | 
            +
             | 
| 5 | 
            +
              Batman.I18N = (function(_super) {
         | 
| 6 | 
            +
                __extends(I18N, _super);
         | 
| 7 | 
            +
             | 
| 8 | 
            +
                I18N.defaultLocale = "en";
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                I18N.useFallback = false;
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                I18N.classAccessor('locale', {
         | 
| 13 | 
            +
                  get: function() {
         | 
| 14 | 
            +
                    return this.locale || this.get('defaultLocale');
         | 
| 15 | 
            +
                  },
         | 
| 16 | 
            +
                  set: function(k, v) {
         | 
| 17 | 
            +
                    return this.locale = v;
         | 
| 18 | 
            +
                  },
         | 
| 19 | 
            +
                  unset: function() {
         | 
| 20 | 
            +
                    var x;
         | 
| 21 | 
            +
                    x = this.locale;
         | 
| 22 | 
            +
                    delete this.locale;
         | 
| 23 | 
            +
                    return x;
         | 
| 24 | 
            +
                  }
         | 
| 25 | 
            +
                });
         | 
| 26 | 
            +
             | 
| 27 | 
            +
                I18N.classAccessor('translations', function() {
         | 
| 28 | 
            +
                  return this.get("locales." + (this.get('locale')));
         | 
| 29 | 
            +
                });
         | 
| 30 | 
            +
             | 
| 31 | 
            +
                I18N.classAccessor('defaultTranslations', function() {
         | 
| 32 | 
            +
                  return this.get("locales." + this.defaultLocale);
         | 
| 33 | 
            +
                });
         | 
| 34 | 
            +
             | 
| 35 | 
            +
                I18N.translate = function(key, values) {
         | 
| 36 | 
            +
                  var translation;
         | 
| 37 | 
            +
                  translation = this.get("translations." + key);
         | 
| 38 | 
            +
                  if (this.useFallback) {
         | 
| 39 | 
            +
                    translation || (translation = this.get("defaultTranslations." + key));
         | 
| 40 | 
            +
                  }
         | 
| 41 | 
            +
                  if (translation == null) {
         | 
| 42 | 
            +
                    Batman.developer.warn("Warning, undefined translation " + key + " when in locale " + (this.get('locale')));
         | 
| 43 | 
            +
                    return "";
         | 
| 44 | 
            +
                  }
         | 
| 45 | 
            +
                  if (!values) {
         | 
| 46 | 
            +
                    return translation;
         | 
| 47 | 
            +
                  }
         | 
| 48 | 
            +
                  return Batman.helpers.interpolate(translation, values);
         | 
| 49 | 
            +
                };
         | 
| 50 | 
            +
             | 
| 51 | 
            +
                I18N.enable = function() {
         | 
| 52 | 
            +
                  var _this = this;
         | 
| 53 | 
            +
                  this._oldTranslation = Batman.translate;
         | 
| 54 | 
            +
                  this.locales.set('en', Batman.translate.messages);
         | 
| 55 | 
            +
                  return Batman.translate = function() {
         | 
| 56 | 
            +
                    return _this.translate.apply(_this, arguments);
         | 
| 57 | 
            +
                  };
         | 
| 58 | 
            +
                };
         | 
| 59 | 
            +
             | 
| 60 | 
            +
                I18N.disable = function() {
         | 
| 61 | 
            +
                  return Batman.translate = this._oldTranslation;
         | 
| 62 | 
            +
                };
         | 
| 63 | 
            +
             | 
| 64 | 
            +
                function I18N() {
         | 
| 65 | 
            +
                  Batman.developer.error("Can't instantiate i18n!");
         | 
| 66 | 
            +
                }
         | 
| 67 | 
            +
             | 
| 68 | 
            +
                return I18N;
         | 
| 69 | 
            +
             | 
| 70 | 
            +
              })(Batman.Object);
         | 
| 71 | 
            +
             | 
| 72 | 
            +
              Batman.I18N.LocalesStorage = (function(_super) {
         | 
| 73 | 
            +
                __extends(LocalesStorage, _super);
         | 
| 74 | 
            +
             | 
| 75 | 
            +
                function LocalesStorage() {
         | 
| 76 | 
            +
                  this.isStorage = true;
         | 
| 77 | 
            +
                  this._storage = {};
         | 
| 78 | 
            +
                  LocalesStorage.__super__.constructor.apply(this, arguments);
         | 
| 79 | 
            +
                }
         | 
| 80 | 
            +
             | 
| 81 | 
            +
                LocalesStorage.accessor({
         | 
| 82 | 
            +
                  get: function(k) {
         | 
| 83 | 
            +
                    var _this = this;
         | 
| 84 | 
            +
                    if (!this._storage[k]) {
         | 
| 85 | 
            +
                      this._storage[k] = {};
         | 
| 86 | 
            +
                      new Batman.Request({
         | 
| 87 | 
            +
                        url: "/locales/" + k + ".json",
         | 
| 88 | 
            +
                        success: function(data) {
         | 
| 89 | 
            +
                          return _this.set(k, data[k]);
         | 
| 90 | 
            +
                        },
         | 
| 91 | 
            +
                        error: function(xhr) {
         | 
| 92 | 
            +
                          throw new Error("Couldn't load locale file " + k + "!");
         | 
| 93 | 
            +
                        }
         | 
| 94 | 
            +
                      });
         | 
| 95 | 
            +
                    }
         | 
| 96 | 
            +
                    return this._storage[k];
         | 
| 97 | 
            +
                  },
         | 
| 98 | 
            +
                  set: function(k, v) {
         | 
| 99 | 
            +
                    return this._storage[k] = v;
         | 
| 100 | 
            +
                  },
         | 
| 101 | 
            +
                  unset: function(k) {
         | 
| 102 | 
            +
                    var x;
         | 
| 103 | 
            +
                    x = this._storage[k];
         | 
| 104 | 
            +
                    delete this._storage[k];
         | 
| 105 | 
            +
                    return x;
         | 
| 106 | 
            +
                  }
         | 
| 107 | 
            +
                });
         | 
| 108 | 
            +
             | 
| 109 | 
            +
                return LocalesStorage;
         | 
| 110 | 
            +
             | 
| 111 | 
            +
              })(Batman.Object);
         | 
| 112 | 
            +
             | 
| 113 | 
            +
              Batman.I18N.set('locales', new Batman.I18N.LocalesStorage);
         | 
| 114 | 
            +
             | 
| 115 | 
            +
              Batman.Filters.t = Batman.Filters.translate = function(string, interpolationKeypaths, binding) {
         | 
| 116 | 
            +
                var translated;
         | 
| 117 | 
            +
                if (!binding) {
         | 
| 118 | 
            +
                  binding = interpolationKeypaths;
         | 
| 119 | 
            +
                  interpolationKeypaths = void 0;
         | 
| 120 | 
            +
                }
         | 
| 121 | 
            +
                if (string == null) {
         | 
| 122 | 
            +
                  return "";
         | 
| 123 | 
            +
                }
         | 
| 124 | 
            +
                if (!(binding.key && binding.key.substr(0, 2) === "t.")) {
         | 
| 125 | 
            +
                  translated = Batman.I18N.translate(string);
         | 
| 126 | 
            +
                  if (translated) {
         | 
| 127 | 
            +
                    string = translated;
         | 
| 128 | 
            +
                  }
         | 
| 129 | 
            +
                }
         | 
| 130 | 
            +
                return Batman.Filters.interpolate.call(this, string, interpolationKeypaths, binding);
         | 
| 131 | 
            +
              };
         | 
| 132 | 
            +
             | 
| 133 | 
            +
              Batman.config.translations = true;
         | 
| 134 | 
            +
             | 
| 135 | 
            +
            }).call(this);
         | 
| 136 | 
            +
             | 
| 137 | 
            +
            (function() {
         | 
| 138 | 
            +
             | 
| 139 | 
            +
             | 
| 140 | 
            +
            }).call(this);
         | 
| @@ -12,7 +12,7 @@ | |
| 12 12 | 
             
                })(Batman.Object, mixins, function(){});
         | 
| 13 13 | 
             
              };
         | 
| 14 14 |  | 
| 15 | 
            -
              Batman.version = '0. | 
| 15 | 
            +
              Batman.version = '0.16.0';
         | 
| 16 16 |  | 
| 17 17 | 
             
              Batman.config = {
         | 
| 18 18 | 
             
                pathToApp: '/',
         | 
| @@ -433,6 +433,7 @@ | |
| 433 433 | 
             
                "<": "<",
         | 
| 434 434 | 
             
                ">": ">",
         | 
| 435 435 | 
             
                "\"": """,
         | 
| 436 | 
            +
                "/": "/",
         | 
| 436 437 | 
             
                "'": "'"
         | 
| 437 438 | 
             
              };
         | 
| 438 439 |  | 
| @@ -624,11 +625,11 @@ | |
| 624 625 | 
             
            }).call(this);
         | 
| 625 626 |  | 
| 626 627 | 
             
            (function() {
         | 
| 627 | 
            -
              var Inflector, camelize_rx,  | 
| 628 | 
            +
              var Inflector, camelize_rx, humanize_rx1, humanize_rx2, humanize_rx3, titleize_rx, underscore_rx1, underscore_rx2;
         | 
| 628 629 |  | 
| 629 630 | 
             
              camelize_rx = /(?:^|_|\-)(.)/g;
         | 
| 630 631 |  | 
| 631 | 
            -
               | 
| 632 | 
            +
              titleize_rx = /(^|\s)([a-z])/g;
         | 
| 632 633 |  | 
| 633 634 | 
             
              underscore_rx1 = /([A-Z]+)([A-Z][a-z])/g;
         | 
| 634 635 |  | 
| @@ -636,7 +637,7 @@ | |
| 636 637 |  | 
| 637 638 | 
             
              humanize_rx1 = /_id$/;
         | 
| 638 639 |  | 
| 639 | 
            -
              humanize_rx2 = /_ | 
| 640 | 
            +
              humanize_rx2 = /_|-|\./g;
         | 
| 640 641 |  | 
| 641 642 | 
             
              humanize_rx3 = /^\w/g;
         | 
| 642 643 |  | 
| @@ -675,11 +676,15 @@ | |
| 675 676 | 
             
                underscore: function(string) {
         | 
| 676 677 | 
             
                  return string.replace(underscore_rx1, '$1_$2').replace(underscore_rx2, '$1_$2').replace('-', '_').toLowerCase();
         | 
| 677 678 | 
             
                },
         | 
| 678 | 
            -
                 | 
| 679 | 
            -
                  return string.replace( | 
| 679 | 
            +
                titleize: function(string) {
         | 
| 680 | 
            +
                  return string.replace(titleize_rx, function(m, p1, p2) {
         | 
| 680 681 | 
             
                    return p1 + p2.toUpperCase();
         | 
| 681 682 | 
             
                  });
         | 
| 682 683 | 
             
                },
         | 
| 684 | 
            +
                capitalize: function(string) {
         | 
| 685 | 
            +
                  Batman.developer.deprecated('capitalize', 'Renamed to titleize.');
         | 
| 686 | 
            +
                  return Batman.helpers.titleize(string);
         | 
| 687 | 
            +
                },
         | 
| 683 688 | 
             
                trim: function(string) {
         | 
| 684 689 | 
             
                  if (string) {
         | 
| 685 690 | 
             
                    return string.trim();
         | 
| @@ -709,6 +714,17 @@ | |
| 709 714 | 
             
                  return string.replace(humanize_rx1, '').replace(humanize_rx2, ' ').replace(humanize_rx3, function(match) {
         | 
| 710 715 | 
             
                    return match.toUpperCase();
         | 
| 711 716 | 
             
                  });
         | 
| 717 | 
            +
                },
         | 
| 718 | 
            +
                toSentence: function(array) {
         | 
| 719 | 
            +
                  var itemString, last;
         | 
| 720 | 
            +
                  if (array.length < 3) {
         | 
| 721 | 
            +
                    return array.join(' and ');
         | 
| 722 | 
            +
                  } else {
         | 
| 723 | 
            +
                    last = array.pop();
         | 
| 724 | 
            +
                    itemString = array.join(', ');
         | 
| 725 | 
            +
                    itemString += ", and " + last;
         | 
| 726 | 
            +
                    return itemString;
         | 
| 727 | 
            +
                  }
         | 
| 712 728 | 
             
                }
         | 
| 713 729 | 
             
              };
         | 
| 714 730 |  | 
| @@ -1050,7 +1066,7 @@ | |
| 1050 1066 | 
             
                };
         | 
| 1051 1067 |  | 
| 1052 1068 | 
             
                Event.prototype.allowAndFire = function() {
         | 
| 1053 | 
            -
                  return this.allowAndFireWithContext(this.handlerContext, arguments);
         | 
| 1069 | 
            +
                  return this.allowAndFireWithContext(this.handlerContext(), arguments);
         | 
| 1054 1070 | 
             
                };
         | 
| 1055 1071 |  | 
| 1056 1072 | 
             
                Event.prototype.allowAndFireWithContext = function(context, args) {
         | 
| @@ -1298,7 +1314,7 @@ | |
| 1298 1314 | 
             
                  }
         | 
| 1299 1315 | 
             
                  result = true;
         | 
| 1300 1316 | 
             
                  this.forEach(function() {
         | 
| 1301 | 
            -
                    return result = result && f.apply(ctx, arguments);
         | 
| 1317 | 
            +
                    return result = result && !!f.apply(ctx, arguments);
         | 
| 1302 1318 | 
             
                  });
         | 
| 1303 1319 | 
             
                  return result;
         | 
| 1304 1320 | 
             
                },
         | 
| @@ -1309,7 +1325,7 @@ | |
| 1309 1325 | 
             
                  }
         | 
| 1310 1326 | 
             
                  result = false;
         | 
| 1311 1327 | 
             
                  this.forEach(function() {
         | 
| 1312 | 
            -
                    return result = result || f.apply(ctx, arguments);
         | 
| 1328 | 
            +
                    return result = result || !!f.apply(ctx, arguments);
         | 
| 1313 1329 | 
             
                  });
         | 
| 1314 1330 | 
             
                  return result;
         | 
| 1315 1331 | 
             
                },
         | 
| @@ -1690,7 +1706,24 @@ | |
| 1690 1706 | 
             
                  return obj;
         | 
| 1691 1707 | 
             
                };
         | 
| 1692 1708 |  | 
| 1693 | 
            -
                SimpleHash.prototype.toJSON =  | 
| 1709 | 
            +
                SimpleHash.prototype.toJSON = function() {
         | 
| 1710 | 
            +
                  var key, obj, objectKey, value, values, _ref, _ref1, _ref2;
         | 
| 1711 | 
            +
                  obj = {};
         | 
| 1712 | 
            +
                  _ref = this._storage;
         | 
| 1713 | 
            +
                  for (key in _ref) {
         | 
| 1714 | 
            +
                    value = _ref[key];
         | 
| 1715 | 
            +
                    obj[this.unprefixedKey(key)] = (value != null ? typeof value.toJSON === "function" ? value.toJSON() : void 0 : void 0) || value;
         | 
| 1716 | 
            +
                  }
         | 
| 1717 | 
            +
                  if (this._objectStorage) {
         | 
| 1718 | 
            +
                    _ref1 = this._objectStorage;
         | 
| 1719 | 
            +
                    for (key in _ref1) {
         | 
| 1720 | 
            +
                      values = _ref1[key];
         | 
| 1721 | 
            +
                      _ref2 = values[0], objectKey = _ref2[0], value = _ref2[1];
         | 
| 1722 | 
            +
                      obj[key] = (value != null ? typeof value.toJSON === "function" ? value.toJSON() : void 0 : void 0) || value;
         | 
| 1723 | 
            +
                    }
         | 
| 1724 | 
            +
                  }
         | 
| 1725 | 
            +
                  return obj;
         | 
| 1726 | 
            +
                };
         | 
| 1694 1727 |  | 
| 1695 1728 | 
             
                return SimpleHash;
         | 
| 1696 1729 |  | 
| @@ -1732,6 +1765,14 @@ | |
| 1732 1765 | 
             
                  return this.get(label);
         | 
| 1733 1766 | 
             
                };
         | 
| 1734 1767 |  | 
| 1768 | 
            +
                AssociationCurator.prototype.getAll = function() {
         | 
| 1769 | 
            +
                  var allAssociations, typeSets, _ref;
         | 
| 1770 | 
            +
                  typeSets = this._byTypeStorage.map(function(label, typeSet) {
         | 
| 1771 | 
            +
                    return typeSet;
         | 
| 1772 | 
            +
                  });
         | 
| 1773 | 
            +
                  return allAssociations = (_ref = new Batman.SimpleSet).merge.apply(_ref, typeSets);
         | 
| 1774 | 
            +
                };
         | 
| 1775 | 
            +
             | 
| 1735 1776 | 
             
                AssociationCurator.prototype.reset = function() {
         | 
| 1736 1777 | 
             
                  this.forEach(function(label, association) {
         | 
| 1737 1778 | 
             
                    return association.reset();
         | 
| @@ -1921,6 +1962,14 @@ | |
| 1921 1962 | 
             
                  return merged;
         | 
| 1922 1963 | 
             
                };
         | 
| 1923 1964 |  | 
| 1965 | 
            +
                SimpleSet.prototype.mappedTo = function(key) {
         | 
| 1966 | 
            +
                  var _this = this;
         | 
| 1967 | 
            +
                  this._mappings || (this._mappings = new Batman.SimpleHash);
         | 
| 1968 | 
            +
                  return this._mappings.getOrSet(key, function() {
         | 
| 1969 | 
            +
                    return new Batman.SetMapping(_this, key);
         | 
| 1970 | 
            +
                  });
         | 
| 1971 | 
            +
                };
         | 
| 1972 | 
            +
             | 
| 1924 1973 | 
             
                SimpleSet.prototype.indexedBy = function(key) {
         | 
| 1925 1974 | 
             
                  this._indexes || (this._indexes = new Batman.SimpleHash);
         | 
| 1926 1975 | 
             
                  return this._indexes.get(key) || this._indexes.set(key, new Batman.SetIndex(this, key));
         | 
| @@ -2100,6 +2149,8 @@ | |
| 2100 2149 |  | 
| 2101 2150 | 
             
                Property.prototype.isDead = false;
         | 
| 2102 2151 |  | 
| 2152 | 
            +
                Property.prototype.isBatchingChanges = false;
         | 
| 2153 | 
            +
             | 
| 2103 2154 | 
             
                Property.prototype.registerAsMutableSource = function() {
         | 
| 2104 2155 | 
             
                  return Batman.Property.registerSource(this);
         | 
| 2105 2156 | 
             
                };
         | 
| @@ -2241,7 +2292,9 @@ | |
| 2241 2292 |  | 
| 2242 2293 | 
             
                Property.prototype.sourceChangeHandler = function() {
         | 
| 2243 2294 | 
             
                  var _this = this;
         | 
| 2244 | 
            -
                  this._sourceChangeHandler || (this._sourceChangeHandler =  | 
| 2295 | 
            +
                  this._sourceChangeHandler || (this._sourceChangeHandler = function() {
         | 
| 2296 | 
            +
                    return _this._handleSourceChange();
         | 
| 2297 | 
            +
                  });
         | 
| 2245 2298 | 
             
                  Batman.developer["do"](function() {
         | 
| 2246 2299 | 
             
                    return _this._sourceChangeHandler.property = _this;
         | 
| 2247 2300 | 
             
                  });
         | 
| @@ -2256,7 +2309,7 @@ | |
| 2256 2309 | 
             
                  } else if (!this.isFinal() && !this.hasObservers()) {
         | 
| 2257 2310 | 
             
                    this.cached = false;
         | 
| 2258 2311 | 
             
                    return this._removeHandlers();
         | 
| 2259 | 
            -
                  } else {
         | 
| 2312 | 
            +
                  } else if (!this.isBatchingChanges) {
         | 
| 2260 2313 | 
             
                    return this.refresh();
         | 
| 2261 2314 | 
             
                  }
         | 
| 2262 2315 | 
             
                };
         | 
| @@ -2750,6 +2803,10 @@ | |
| 2750 2803 | 
             
                  definition.invert = true;
         | 
| 2751 2804 | 
             
                  return new Batman.DOM.InsertionBinding(definition);
         | 
| 2752 2805 | 
             
                },
         | 
| 2806 | 
            +
                deferif: function(definition) {
         | 
| 2807 | 
            +
                  definition.invert = true;
         | 
| 2808 | 
            +
                  return new Batman.DOM.DeferredRenderBinding(definition);
         | 
| 2809 | 
            +
                },
         | 
| 2753 2810 | 
             
                renderif: function(definition) {
         | 
| 2754 2811 | 
             
                  return new Batman.DOM.DeferredRenderBinding(definition);
         | 
| 2755 2812 | 
             
                },
         | 
| @@ -2827,9 +2884,9 @@ | |
| 2827 2884 | 
             
                __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
         | 
| 2828 2885 |  | 
| 2829 2886 | 
             
              Batman.DOM.events = {
         | 
| 2830 | 
            -
                 | 
| 2887 | 
            +
                primaryInteractionEvent: function(node, callback, view, eventName, preventDefault) {
         | 
| 2831 2888 | 
             
                  if (eventName == null) {
         | 
| 2832 | 
            -
                    eventName =  | 
| 2889 | 
            +
                    eventName = Batman.DOM.primaryInteractionEventName;
         | 
| 2833 2890 | 
             
                  }
         | 
| 2834 2891 | 
             
                  if (preventDefault == null) {
         | 
| 2835 2892 | 
             
                    preventDefault = true;
         | 
| @@ -2853,6 +2910,15 @@ | |
| 2853 2910 | 
             
                  }
         | 
| 2854 2911 | 
             
                  return node;
         | 
| 2855 2912 | 
             
                },
         | 
| 2913 | 
            +
                click: function(node, callback, view, eventName, preventDefault) {
         | 
| 2914 | 
            +
                  if (eventName == null) {
         | 
| 2915 | 
            +
                    eventName = 'click';
         | 
| 2916 | 
            +
                  }
         | 
| 2917 | 
            +
                  if (preventDefault == null) {
         | 
| 2918 | 
            +
                    preventDefault = true;
         | 
| 2919 | 
            +
                  }
         | 
| 2920 | 
            +
                  return Batman.DOM.events.primaryInteractionEvent(node, callback, view, eventName, preventDefault);
         | 
| 2921 | 
            +
                },
         | 
| 2856 2922 | 
             
                doubleclick: function(node, callback, view) {
         | 
| 2857 2923 | 
             
                  return Batman.DOM.events.click(node, callback, view, 'dblclick');
         | 
| 2858 2924 | 
             
                },
         | 
| @@ -2943,6 +3009,8 @@ | |
| 2943 3009 | 
             
                return true;
         | 
| 2944 3010 | 
             
              };
         | 
| 2945 3011 |  | 
| 3012 | 
            +
              Batman.DOM.primaryInteractionEventName = 'click';
         | 
| 3013 | 
            +
             | 
| 2946 3014 | 
             
            }).call(this);
         | 
| 2947 3015 |  | 
| 2948 3016 | 
             
            (function() {
         | 
| @@ -3001,6 +3069,13 @@ | |
| 3001 3069 | 
             
                event: function(definition) {
         | 
| 3002 3070 | 
             
                  return new Batman.DOM.EventBinding(definition);
         | 
| 3003 3071 | 
             
                },
         | 
| 3072 | 
            +
                track: function(definition) {
         | 
| 3073 | 
            +
                  if (definition.attr === 'view') {
         | 
| 3074 | 
            +
                    return new Batman.DOM.ViewTrackingBinding(definition);
         | 
| 3075 | 
            +
                  } else if (definition.attr === 'click') {
         | 
| 3076 | 
            +
                    return new Batman.DOM.ClickTrackingBinding(definition);
         | 
| 3077 | 
            +
                  }
         | 
| 3078 | 
            +
                },
         | 
| 3004 3079 | 
             
                addclass: function(definition) {
         | 
| 3005 3080 | 
             
                  return new Batman.DOM.AddClassBinding(definition);
         | 
| 3006 3081 | 
             
                },
         | 
| @@ -3211,6 +3286,62 @@ | |
| 3211 3286 | 
             
                  return this._batmanID();
         | 
| 3212 3287 | 
             
                });
         | 
| 3213 3288 |  | 
| 3289 | 
            +
                BatmanObject.delegate = function() {
         | 
| 3290 | 
            +
                  var options, properties, _i,
         | 
| 3291 | 
            +
                    _this = this;
         | 
| 3292 | 
            +
                  properties = 2 <= arguments.length ? __slice.call(arguments, 0, _i = arguments.length - 1) : (_i = 0, []), options = arguments[_i++];
         | 
| 3293 | 
            +
                  if (options == null) {
         | 
| 3294 | 
            +
                    options = {};
         | 
| 3295 | 
            +
                  }
         | 
| 3296 | 
            +
                  if (!options.to) {
         | 
| 3297 | 
            +
                    Batman.developer.warn('delegate must include to option', this, properties);
         | 
| 3298 | 
            +
                  }
         | 
| 3299 | 
            +
                  return properties.forEach(function(property) {
         | 
| 3300 | 
            +
                    return _this.accessor(property, {
         | 
| 3301 | 
            +
                      get: function() {
         | 
| 3302 | 
            +
                        var _ref;
         | 
| 3303 | 
            +
                        return (_ref = this.get(options.to)) != null ? _ref.get(property) : void 0;
         | 
| 3304 | 
            +
                      },
         | 
| 3305 | 
            +
                      set: function(key, value) {
         | 
| 3306 | 
            +
                        var _ref;
         | 
| 3307 | 
            +
                        return (_ref = this.get(options.to)) != null ? _ref.set(property, value) : void 0;
         | 
| 3308 | 
            +
                      },
         | 
| 3309 | 
            +
                      unset: function() {
         | 
| 3310 | 
            +
                        var _ref;
         | 
| 3311 | 
            +
                        return (_ref = this.get(options.to)) != null ? _ref.unset(property) : void 0;
         | 
| 3312 | 
            +
                      }
         | 
| 3313 | 
            +
                    });
         | 
| 3314 | 
            +
                  });
         | 
| 3315 | 
            +
                };
         | 
| 3316 | 
            +
             | 
| 3317 | 
            +
                BatmanObject.classDelegate = function() {
         | 
| 3318 | 
            +
                  var options, properties, _i,
         | 
| 3319 | 
            +
                    _this = this;
         | 
| 3320 | 
            +
                  properties = 2 <= arguments.length ? __slice.call(arguments, 0, _i = arguments.length - 1) : (_i = 0, []), options = arguments[_i++];
         | 
| 3321 | 
            +
                  if (options == null) {
         | 
| 3322 | 
            +
                    options = {};
         | 
| 3323 | 
            +
                  }
         | 
| 3324 | 
            +
                  if (!options.to) {
         | 
| 3325 | 
            +
                    Batman.developer.warn('delegate must include to option', this, properties);
         | 
| 3326 | 
            +
                  }
         | 
| 3327 | 
            +
                  return properties.forEach(function(property) {
         | 
| 3328 | 
            +
                    return _this.classAccessor(property, {
         | 
| 3329 | 
            +
                      get: function() {
         | 
| 3330 | 
            +
                        var _ref;
         | 
| 3331 | 
            +
                        return (_ref = this.get(options.to)) != null ? _ref.get(property) : void 0;
         | 
| 3332 | 
            +
                      },
         | 
| 3333 | 
            +
                      set: function(key, value) {
         | 
| 3334 | 
            +
                        var _ref;
         | 
| 3335 | 
            +
                        return (_ref = this.get(options.to)) != null ? _ref.set(property, value) : void 0;
         | 
| 3336 | 
            +
                      },
         | 
| 3337 | 
            +
                      unset: function() {
         | 
| 3338 | 
            +
                        var _ref;
         | 
| 3339 | 
            +
                        return (_ref = this.get(options.to)) != null ? _ref.unset(property) : void 0;
         | 
| 3340 | 
            +
                      }
         | 
| 3341 | 
            +
                    });
         | 
| 3342 | 
            +
                  });
         | 
| 3343 | 
            +
                };
         | 
| 3344 | 
            +
             | 
| 3214 3345 | 
             
                function BatmanObject() {
         | 
| 3215 3346 | 
             
                  var mixins;
         | 
| 3216 3347 | 
             
                  mixins = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
         | 
| @@ -3250,6 +3381,23 @@ | |
| 3250 3381 | 
             
                  return obj;
         | 
| 3251 3382 | 
             
                };
         | 
| 3252 3383 |  | 
| 3384 | 
            +
                BatmanObject.prototype.batchAccessorChanges = function() {
         | 
| 3385 | 
            +
                  var i, key, properties, property, result, wrappedFunction, _i, _j, _k, _len, _len1;
         | 
| 3386 | 
            +
                  properties = 2 <= arguments.length ? __slice.call(arguments, 0, _i = arguments.length - 1) : (_i = 0, []), wrappedFunction = arguments[_i++];
         | 
| 3387 | 
            +
                  for (i = _j = 0, _len = properties.length; _j < _len; i = ++_j) {
         | 
| 3388 | 
            +
                    key = properties[i];
         | 
| 3389 | 
            +
                    property = properties[i] = this.property(key);
         | 
| 3390 | 
            +
                    property.isBatchingChanges = true;
         | 
| 3391 | 
            +
                  }
         | 
| 3392 | 
            +
                  result = wrappedFunction.call(this);
         | 
| 3393 | 
            +
                  for (_k = 0, _len1 = properties.length; _k < _len1; _k++) {
         | 
| 3394 | 
            +
                    property = properties[_k];
         | 
| 3395 | 
            +
                    property.isBatchingChanges = false;
         | 
| 3396 | 
            +
                    property.refresh();
         | 
| 3397 | 
            +
                  }
         | 
| 3398 | 
            +
                  return result;
         | 
| 3399 | 
            +
                };
         | 
| 3400 | 
            +
             | 
| 3253 3401 | 
             
                return BatmanObject;
         | 
| 3254 3402 |  | 
| 3255 3403 | 
             
              })(Object);
         | 
| @@ -3274,7 +3422,7 @@ | |
| 3274 3422 | 
             
                  this.parseTree(this.node);
         | 
| 3275 3423 | 
             
                }
         | 
| 3276 3424 |  | 
| 3277 | 
            -
                bindingSortOrder = ["defineview", "foreach", "renderif", "view", "formfor", "context", "bind", "source", "target"];
         | 
| 3425 | 
            +
                bindingSortOrder = ["defineview", "foreach", "renderif", "view", "formfor", "context", "bind", "source", "target", "track", "event"];
         | 
| 3278 3426 |  | 
| 3279 3427 | 
             
                viewBackedBindings = ["foreach", "renderif", "formfor", "context"];
         | 
| 3280 3428 |  | 
| @@ -3407,7 +3555,7 @@ | |
| 3407 3555 | 
             
                    });
         | 
| 3408 3556 | 
             
                  } else {
         | 
| 3409 3557 | 
             
                    return Batman.t('errors.format', {
         | 
| 3410 | 
            -
                      attribute: Batman.helpers.humanize(this.attribute),
         | 
| 3558 | 
            +
                      attribute: Batman.helpers.humanize(Batman.ValidationError.singularizeAssociated(this.attribute)),
         | 
| 3411 3559 | 
             
                      message: this.message
         | 
| 3412 3560 | 
             
                    });
         | 
| 3413 3561 | 
             
                  }
         | 
| @@ -3420,6 +3568,15 @@ | |
| 3420 3568 | 
             
                  });
         | 
| 3421 3569 | 
             
                }
         | 
| 3422 3570 |  | 
| 3571 | 
            +
                ValidationError.singularizeAssociated = function(attribute) {
         | 
| 3572 | 
            +
                  var i, parts, _i, _ref;
         | 
| 3573 | 
            +
                  parts = attribute.split(".");
         | 
| 3574 | 
            +
                  for (i = _i = 0, _ref = parts.length - 1; _i < _ref; i = _i += 1) {
         | 
| 3575 | 
            +
                    parts[i] = Batman.helpers.singularize(parts[i]);
         | 
| 3576 | 
            +
                  }
         | 
| 3577 | 
            +
                  return parts.join(" ");
         | 
| 3578 | 
            +
                };
         | 
| 3579 | 
            +
             | 
| 3423 3580 | 
             
                return ValidationError;
         | 
| 3424 3581 |  | 
| 3425 3582 | 
             
              })(Batman.Object);
         | 
| @@ -3474,6 +3631,19 @@ | |
| 3474 3631 |  | 
| 3475 3632 | 
             
                })(StorageAdapter.StorageError);
         | 
| 3476 3633 |  | 
| 3634 | 
            +
                StorageAdapter.UnauthorizedError = (function(_super1) {
         | 
| 3635 | 
            +
                  __extends(UnauthorizedError, _super1);
         | 
| 3636 | 
            +
             | 
| 3637 | 
            +
                  UnauthorizedError.prototype.name = 'UnauthorizedError';
         | 
| 3638 | 
            +
             | 
| 3639 | 
            +
                  function UnauthorizedError(message) {
         | 
| 3640 | 
            +
                    UnauthorizedError.__super__.constructor.call(this, message || "Storage operation denied due to invalid credentials!");
         | 
| 3641 | 
            +
                  }
         | 
| 3642 | 
            +
             | 
| 3643 | 
            +
                  return UnauthorizedError;
         | 
| 3644 | 
            +
             | 
| 3645 | 
            +
                })(StorageAdapter.StorageError);
         | 
| 3646 | 
            +
             | 
| 3477 3647 | 
             
                StorageAdapter.NotAllowedError = (function(_super1) {
         | 
| 3478 3648 | 
             
                  __extends(NotAllowedError, _super1);
         | 
| 3479 3649 |  | 
| @@ -3500,6 +3670,19 @@ | |
| 3500 3670 |  | 
| 3501 3671 | 
             
                })(StorageAdapter.StorageError);
         | 
| 3502 3672 |  | 
| 3673 | 
            +
                StorageAdapter.EntityTooLargeError = (function(_super1) {
         | 
| 3674 | 
            +
                  __extends(EntityTooLargeError, _super1);
         | 
| 3675 | 
            +
             | 
| 3676 | 
            +
                  EntityTooLargeError.prototype.name = "EntityTooLargeError";
         | 
| 3677 | 
            +
             | 
| 3678 | 
            +
                  function EntityTooLargeError(message) {
         | 
| 3679 | 
            +
                    EntityTooLargeError.__super__.constructor.call(this, message || "Storage operation denied due to size constraints!");
         | 
| 3680 | 
            +
                  }
         | 
| 3681 | 
            +
             | 
| 3682 | 
            +
                  return EntityTooLargeError;
         | 
| 3683 | 
            +
             | 
| 3684 | 
            +
                })(StorageAdapter.StorageError);
         | 
| 3685 | 
            +
             | 
| 3503 3686 | 
             
                StorageAdapter.UnprocessableRecordError = (function(_super1) {
         | 
| 3504 3687 | 
             
                  __extends(UnprocessableRecordError, _super1);
         | 
| 3505 3688 |  | 
| @@ -3539,6 +3722,19 @@ | |
| 3539 3722 |  | 
| 3540 3723 | 
             
                })(StorageAdapter.StorageError);
         | 
| 3541 3724 |  | 
| 3725 | 
            +
                StorageAdapter.BadGatewayError = (function(_super1) {
         | 
| 3726 | 
            +
                  __extends(BadGatewayError, _super1);
         | 
| 3727 | 
            +
             | 
| 3728 | 
            +
                  BadGatewayError.prototype.name = "BadGatewayError";
         | 
| 3729 | 
            +
             | 
| 3730 | 
            +
                  function BadGatewayError(message) {
         | 
| 3731 | 
            +
                    BadGatewayError.__super__.constructor.call(this, message || "Storage operation failed due to unavailability of the backend!");
         | 
| 3732 | 
            +
                  }
         | 
| 3733 | 
            +
             | 
| 3734 | 
            +
                  return BadGatewayError;
         | 
| 3735 | 
            +
             | 
| 3736 | 
            +
                })(StorageAdapter.StorageError);
         | 
| 3737 | 
            +
             | 
| 3542 3738 | 
             
                function StorageAdapter(model) {
         | 
| 3543 3739 | 
             
                  var constructor;
         | 
| 3544 3740 | 
             
                  StorageAdapter.__super__.constructor.call(this, {
         | 
| @@ -3555,6 +3751,25 @@ | |
| 3555 3751 |  | 
| 3556 3752 | 
             
                StorageAdapter.prototype.isStorageAdapter = true;
         | 
| 3557 3753 |  | 
| 3754 | 
            +
                StorageAdapter.prototype.onlyCertainAttributes = function(json, only) {
         | 
| 3755 | 
            +
                  var key;
         | 
| 3756 | 
            +
                  for (key in json) {
         | 
| 3757 | 
            +
                    if (only.indexOf(key) < 0) {
         | 
| 3758 | 
            +
                      delete json[key];
         | 
| 3759 | 
            +
                    }
         | 
| 3760 | 
            +
                  }
         | 
| 3761 | 
            +
                  return json;
         | 
| 3762 | 
            +
                };
         | 
| 3763 | 
            +
             | 
| 3764 | 
            +
                StorageAdapter.prototype.exceptCertainAttributes = function(json, except) {
         | 
| 3765 | 
            +
                  var key, _i, _len;
         | 
| 3766 | 
            +
                  for (_i = 0, _len = except.length; _i < _len; _i++) {
         | 
| 3767 | 
            +
                    key = except[_i];
         | 
| 3768 | 
            +
                    delete json[key];
         | 
| 3769 | 
            +
                  }
         | 
| 3770 | 
            +
                  return json;
         | 
| 3771 | 
            +
                };
         | 
| 3772 | 
            +
             | 
| 3558 3773 | 
             
                StorageAdapter.prototype.storageKey = function(record) {
         | 
| 3559 3774 | 
             
                  var model;
         | 
| 3560 3775 | 
             
                  model = (record != null ? record.constructor : void 0) || this.model;
         | 
| @@ -3565,14 +3780,14 @@ | |
| 3565 3780 | 
             
                  if (constructor == null) {
         | 
| 3566 3781 | 
             
                    constructor = this.model;
         | 
| 3567 3782 | 
             
                  }
         | 
| 3568 | 
            -
                  return constructor. | 
| 3783 | 
            +
                  return constructor.createFromJSON(attributes);
         | 
| 3569 3784 | 
             
                };
         | 
| 3570 3785 |  | 
| 3571 3786 | 
             
                StorageAdapter.prototype.getRecordsFromData = function(attributeSet, constructor) {
         | 
| 3572 3787 | 
             
                  if (constructor == null) {
         | 
| 3573 3788 | 
             
                    constructor = this.model;
         | 
| 3574 3789 | 
             
                  }
         | 
| 3575 | 
            -
                  return constructor. | 
| 3790 | 
            +
                  return constructor.createMultipleFromJSON(attributeSet);
         | 
| 3576 3791 | 
             
                };
         | 
| 3577 3792 |  | 
| 3578 3793 | 
             
                StorageAdapter.skipIfError = function(f) {
         | 
| @@ -3744,7 +3959,7 @@ | |
| 3744 3959 | 
             
                    }
         | 
| 3745 3960 | 
             
                    this.url = function(options) {
         | 
| 3746 3961 | 
             
                      var childSegment, parentID, plural;
         | 
| 3747 | 
            -
                      childSegment = Batman.helpers.pluralize(this.get('resourceName').toLowerCase());
         | 
| 3962 | 
            +
                      childSegment = this.storageKey || Batman.helpers.pluralize(this.get('resourceName').toLowerCase());
         | 
| 3748 3963 | 
             
                      for (key in parents) {
         | 
| 3749 3964 | 
             
                        plural = parents[key];
         | 
| 3750 3965 | 
             
                        parentID = options.data[key];
         | 
| @@ -3757,7 +3972,7 @@ | |
| 3757 3972 | 
             
                    };
         | 
| 3758 3973 | 
             
                    return this.prototype.url = function() {
         | 
| 3759 3974 | 
             
                      var childSegment, id, parentID, plural, url;
         | 
| 3760 | 
            -
                      childSegment = Batman.helpers.pluralize(this.constructor.get('resourceName').toLowerCase());
         | 
| 3975 | 
            +
                      childSegment = this.constructor.storageKey || Batman.helpers.pluralize(this.constructor.get('resourceName').toLowerCase());
         | 
| 3761 3976 | 
             
                      for (key in parents) {
         | 
| 3762 3977 | 
             
                        plural = parents[key];
         | 
| 3763 3978 | 
             
                        parentID = this.get('dirtyKeys').get(key);
         | 
| @@ -3916,6 +4131,12 @@ | |
| 3916 4131 | 
             
                RestStorage.prototype.before('create', 'update', RestStorage.skipIfError(function(env, next) {
         | 
| 3917 4132 | 
             
                  var data, json, namespace;
         | 
| 3918 4133 | 
             
                  json = env.subject.toJSON();
         | 
| 4134 | 
            +
                  if (env.options.only) {
         | 
| 4135 | 
            +
                    json = this.onlyCertainAttributes(json, env.options.only);
         | 
| 4136 | 
            +
                  }
         | 
| 4137 | 
            +
                  if (env.options.except) {
         | 
| 4138 | 
            +
                    json = this.exceptCertainAttributes(json, env.options.except);
         | 
| 4139 | 
            +
                  }
         | 
| 3919 4140 | 
             
                  if (namespace = this.recordJsonNamespace(env.subject)) {
         | 
| 3920 4141 | 
             
                    data = {};
         | 
| 3921 4142 | 
             
                    data[namespace] = json;
         | 
| @@ -4033,13 +4254,16 @@ | |
| 4033 4254 |  | 
| 4034 4255 | 
             
                RestStorage._statusCodeErrors = {
         | 
| 4035 4256 | 
             
                  '0': RestStorage.CommunicationError,
         | 
| 4257 | 
            +
                  '401': RestStorage.UnauthorizedError,
         | 
| 4036 4258 | 
             
                  '403': RestStorage.NotAllowedError,
         | 
| 4037 4259 | 
             
                  '404': RestStorage.NotFoundError,
         | 
| 4038 4260 | 
             
                  '406': RestStorage.NotAcceptableError,
         | 
| 4039 4261 | 
             
                  '409': RestStorage.RecordExistsError,
         | 
| 4262 | 
            +
                  '413': RestStorage.EntityTooLargeError,
         | 
| 4040 4263 | 
             
                  '422': RestStorage.UnprocessableRecordError,
         | 
| 4041 4264 | 
             
                  '500': RestStorage.InternalStorageError,
         | 
| 4042 | 
            -
                  '501': RestStorage.NotImplementedError
         | 
| 4265 | 
            +
                  '501': RestStorage.NotImplementedError,
         | 
| 4266 | 
            +
                  '502': RestStorage.BadGatewayError
         | 
| 4043 4267 | 
             
                };
         | 
| 4044 4268 |  | 
| 4045 4269 | 
             
                RestStorage.prototype._errorFor = function(error, env) {
         | 
| @@ -4151,7 +4375,15 @@ | |
| 4151 4375 | 
             
                }));
         | 
| 4152 4376 |  | 
| 4153 4377 | 
             
                LocalStorage.prototype.before('create', 'update', LocalStorage.skipIfError(function(env, next) {
         | 
| 4154 | 
            -
                   | 
| 4378 | 
            +
                  var json;
         | 
| 4379 | 
            +
                  json = env.subject.toJSON();
         | 
| 4380 | 
            +
                  if (env.options.only) {
         | 
| 4381 | 
            +
                    json = this.onlyCertainAttributes(json, env.options.only);
         | 
| 4382 | 
            +
                  }
         | 
| 4383 | 
            +
                  if (env.options.except) {
         | 
| 4384 | 
            +
                    json = this.exceptCertainAttributes(json, env.options.except);
         | 
| 4385 | 
            +
                  }
         | 
| 4386 | 
            +
                  env.recordAttributes = JSON.stringify(json);
         | 
| 4155 4387 | 
             
                  return next();
         | 
| 4156 4388 | 
             
                }));
         | 
| 4157 4389 |  | 
| @@ -4516,7 +4748,7 @@ | |
| 4516 4748 | 
             
                      return {
         | 
| 4517 4749 | 
             
                        controller: resourceNameFromModel(argument.constructor),
         | 
| 4518 4750 | 
             
                        action: 'show',
         | 
| 4519 | 
            -
                        id: argument.get('id')
         | 
| 4751 | 
            +
                        id: (typeof argument.toParam === "function" ? argument.toParam() : void 0) || argument.get('id')
         | 
| 4520 4752 | 
             
                      };
         | 
| 4521 4753 | 
             
                    } else {
         | 
| 4522 4754 | 
             
                      return {};
         | 
| @@ -4542,7 +4774,7 @@ | |
| 4542 4774 | 
             
                  ControllerDirectory.accessor('__app', Batman.Property.defaultAccessor);
         | 
| 4543 4775 |  | 
| 4544 4776 | 
             
                  ControllerDirectory.accessor(function(key) {
         | 
| 4545 | 
            -
                    return this.get("__app." + (Batman.helpers. | 
| 4777 | 
            +
                    return this.get("__app." + (Batman.helpers.titleize(key)) + "Controller.sharedController");
         | 
| 4546 4778 | 
             
                  });
         | 
| 4547 4779 |  | 
| 4548 4780 | 
             
                  return ControllerDirectory;
         | 
| @@ -4689,7 +4921,9 @@ | |
| 4689 4921 | 
             
                  for (index = _i = 0, _len = matches.length; _i < _len; index = ++_i) {
         | 
| 4690 4922 | 
             
                    match = matches[index];
         | 
| 4691 4923 | 
             
                    name = namedArguments[index];
         | 
| 4692 | 
            -
                     | 
| 4924 | 
            +
                    if (match != null) {
         | 
| 4925 | 
            +
                      params[name] = decodeURIComponent(match);
         | 
| 4926 | 
            +
                    }
         | 
| 4693 4927 | 
             
                  }
         | 
| 4694 4928 | 
             
                  return Batman.extend(params, uri.queryParams);
         | 
| 4695 4929 | 
             
                };
         | 
| @@ -4791,9 +5025,13 @@ | |
| 4791 5025 |  | 
| 4792 5026 | 
             
                function ControllerActionRoute(templatePath, options) {
         | 
| 4793 5027 | 
             
                  this.callback = __bind(this.callback, this);
         | 
| 4794 | 
            -
                  var action, controller, _ref;
         | 
| 5028 | 
            +
                  var action, controller, _ref, _ref1;
         | 
| 4795 5029 | 
             
                  if (options.signature) {
         | 
| 4796 | 
            -
                     | 
| 5030 | 
            +
                    if (Batman.typeOf(options.signature) === 'String') {
         | 
| 5031 | 
            +
                      _ref = options.signature.split('#'), controller = _ref[0], action = _ref[1];
         | 
| 5032 | 
            +
                    } else {
         | 
| 5033 | 
            +
                      _ref1 = options.signature, controller = _ref1.controller, action = _ref1.action;
         | 
| 5034 | 
            +
                    }
         | 
| 4797 5035 | 
             
                    action || (action = 'index');
         | 
| 4798 5036 | 
             
                    options.controller = controller;
         | 
| 4799 5037 | 
             
                    options.action = action;
         | 
| @@ -5279,6 +5517,9 @@ | |
| 5279 5517 | 
             
                          _results = [];
         | 
| 5280 5518 | 
             
                          for (_i = 0, _len = value.length; _i < _len; _i++) {
         | 
| 5281 5519 | 
             
                            handler = value[_i];
         | 
| 5520 | 
            +
                            if (typeof handler === 'string') {
         | 
| 5521 | 
            +
                              handler = _this[handler];
         | 
| 5522 | 
            +
                            }
         | 
| 5282 5523 | 
             
                            _results.push(handler.call(_this, error));
         | 
| 5283 5524 | 
             
                          }
         | 
| 5284 5525 | 
             
                          return _results;
         | 
| @@ -5379,16 +5620,14 @@ | |
| 5379 5620 | 
             
                    }
         | 
| 5380 5621 | 
             
                  } else {
         | 
| 5381 5622 | 
             
                    if (Batman.typeOf(url) === 'Object') {
         | 
| 5382 | 
            -
                       | 
| 5383 | 
            -
                        url.controller = this;
         | 
| 5384 | 
            -
                      }
         | 
| 5623 | 
            +
                      url.controller || (url.controller = this.get('routingKey'));
         | 
| 5385 5624 | 
             
                    }
         | 
| 5386 5625 | 
             
                    return Batman.redirect(url);
         | 
| 5387 5626 | 
             
                  }
         | 
| 5388 5627 | 
             
                };
         | 
| 5389 5628 |  | 
| 5390 5629 | 
             
                Controller.prototype.render = function(options) {
         | 
| 5391 | 
            -
                  var action, frame, view, yieldContentView, yieldName, _ref, _ref1, _ref2, _ref3;
         | 
| 5630 | 
            +
                  var action, frame, view, yieldContentView, yieldName, _ref, _ref1, _ref2, _ref3, _ref4;
         | 
| 5392 5631 | 
             
                  if (options == null) {
         | 
| 5393 5632 | 
             
                    options = {};
         | 
| 5394 5633 | 
             
                  }
         | 
| @@ -5404,7 +5643,7 @@ | |
| 5404 5643 | 
             
                    options.view = null;
         | 
| 5405 5644 | 
             
                  } else {
         | 
| 5406 5645 | 
             
                    options.viewClass || (options.viewClass = this._viewClassForAction(action));
         | 
| 5407 | 
            -
                    options.source || (options.source = Batman.helpers.underscore(this.get('routingKey') + '/' + action));
         | 
| 5646 | 
            +
                    options.source || (options.source = ((_ref1 = options.viewClass) != null ? _ref1.prototype.source : void 0) || Batman.helpers.underscore(this.get('routingKey') + '/' + action));
         | 
| 5408 5647 | 
             
                    view = this.renderCache.viewForOptions(options);
         | 
| 5409 5648 | 
             
                  }
         | 
| 5410 5649 | 
             
                  if (view) {
         | 
| @@ -5421,10 +5660,10 @@ | |
| 5421 5660 | 
             
                      view.set('contentFor', yieldName);
         | 
| 5422 5661 | 
             
                    }
         | 
| 5423 5662 | 
             
                    view.set('controller', this);
         | 
| 5424 | 
            -
                    if (( | 
| 5425 | 
            -
                      if (( | 
| 5426 | 
            -
                        if (( | 
| 5427 | 
            -
                           | 
| 5663 | 
            +
                    if ((_ref2 = Batman.currentApp) != null) {
         | 
| 5664 | 
            +
                      if ((_ref3 = _ref2.layout) != null) {
         | 
| 5665 | 
            +
                        if ((_ref4 = _ref3.subviews) != null) {
         | 
| 5666 | 
            +
                          _ref4.add(view);
         | 
| 5428 5667 | 
             
                        }
         | 
| 5429 5668 | 
             
                      }
         | 
| 5430 5669 | 
             
                    }
         | 
| @@ -5526,7 +5765,7 @@ | |
| 5526 5765 |  | 
| 5527 5766 | 
             
                Set._applySetAccessors(Set);
         | 
| 5528 5767 |  | 
| 5529 | 
            -
                _ref = ['indexedBy', 'indexedByUnique', 'sortedBy', 'equality', '_indexOfItem'];
         | 
| 5768 | 
            +
                _ref = ['indexedBy', 'indexedByUnique', 'sortedBy', 'equality', '_indexOfItem', 'mappedTo'];
         | 
| 5530 5769 | 
             
                for (_i = 0, _len = _ref.length; _i < _len; _i++) {
         | 
| 5531 5770 | 
             
                  k = _ref[_i];
         | 
| 5532 5771 | 
             
                  Set.prototype[k] = Batman.SimpleSet.prototype[k];
         | 
| @@ -5544,7 +5783,11 @@ | |
| 5544 5783 | 
             
                  _fn(k);
         | 
| 5545 5784 | 
             
                }
         | 
| 5546 5785 |  | 
| 5547 | 
            -
                Set.prototype.toJSON =  | 
| 5786 | 
            +
                Set.prototype.toJSON = function() {
         | 
| 5787 | 
            +
                  return this.map(function(value) {
         | 
| 5788 | 
            +
                    return (typeof value.toJSON === "function" ? value.toJSON() : void 0) || value;
         | 
| 5789 | 
            +
                  });
         | 
| 5790 | 
            +
                };
         | 
| 5548 5791 |  | 
| 5549 5792 | 
             
                Set.prototype.add = Set.mutation(function() {
         | 
| 5550 5793 | 
             
                  var addedItems;
         | 
| @@ -6005,7 +6248,7 @@ | |
| 6005 6248 | 
             
                  predicateKeys = [];
         | 
| 6006 6249 | 
             
                  definePredicate = function(state) {
         | 
| 6007 6250 | 
             
                    var key;
         | 
| 6008 | 
            -
                    key = "is" + (Batman.helpers. | 
| 6251 | 
            +
                    key = "is" + (Batman.helpers.titleize(state));
         | 
| 6009 6252 | 
             
                    if (_this.prototype[key] != null) {
         | 
| 6010 6253 | 
             
                      return;
         | 
| 6011 6254 | 
             
                    }
         | 
| @@ -6259,7 +6502,9 @@ | |
| 6259 6502 | 
             
                      if ((matches = validatorClass.matches(optionsOrFunction))) {
         | 
| 6260 6503 | 
             
                        validators.push({
         | 
| 6261 6504 | 
             
                          keys: keys,
         | 
| 6262 | 
            -
                          validator: new validatorClass(matches)
         | 
| 6505 | 
            +
                          validator: new validatorClass(matches),
         | 
| 6506 | 
            +
                          "if": optionsOrFunction["if"],
         | 
| 6507 | 
            +
                          unless: optionsOrFunction.unless
         | 
| 6263 6508 | 
             
                        });
         | 
| 6264 6509 | 
             
                      }
         | 
| 6265 6510 | 
             
                    }
         | 
| @@ -6333,16 +6578,25 @@ | |
| 6333 6578 | 
             
                };
         | 
| 6334 6579 |  | 
| 6335 6580 | 
             
                Model.findWithOptions = function(id, options, callback) {
         | 
| 6336 | 
            -
                  var record | 
| 6581 | 
            +
                  var record,
         | 
| 6582 | 
            +
                    _this = this;
         | 
| 6337 6583 | 
             
                  if (options == null) {
         | 
| 6338 6584 | 
             
                    options = {};
         | 
| 6339 6585 | 
             
                  }
         | 
| 6340 6586 | 
             
                  Batman.developer.assert(callback, "Must call find with a callback!");
         | 
| 6341 | 
            -
                   | 
| 6342 | 
            -
                  record. | 
| 6343 | 
            -
             | 
| 6587 | 
            +
                  this._pending || (this._pending = {});
         | 
| 6588 | 
            +
                  record = this._loadIdentity(id) || this._pending[id];
         | 
| 6589 | 
            +
                  if (record == null) {
         | 
| 6590 | 
            +
                    record = new this;
         | 
| 6591 | 
            +
                    record._withoutDirtyTracking(function() {
         | 
| 6592 | 
            +
                      return this.set('id', id);
         | 
| 6593 | 
            +
                    });
         | 
| 6594 | 
            +
                    this._pending[id] = record;
         | 
| 6595 | 
            +
                  }
         | 
| 6596 | 
            +
                  record.loadWithOptions(options, function() {
         | 
| 6597 | 
            +
                    delete _this._pending[id];
         | 
| 6598 | 
            +
                    return callback.apply(_this, arguments);
         | 
| 6344 6599 | 
             
                  });
         | 
| 6345 | 
            -
                  record.loadWithOptions(options, callback);
         | 
| 6346 6600 | 
             
                  return record;
         | 
| 6347 6601 | 
             
                };
         | 
| 6348 6602 |  | 
| @@ -6400,6 +6654,10 @@ | |
| 6400 6654 | 
             
                  return this._makeOrFindRecordFromData(json);
         | 
| 6401 6655 | 
             
                };
         | 
| 6402 6656 |  | 
| 6657 | 
            +
                Model.createMultipleFromJSON = function(array) {
         | 
| 6658 | 
            +
                  return this._makeOrFindRecordsFromData(array);
         | 
| 6659 | 
            +
                };
         | 
| 6660 | 
            +
             | 
| 6403 6661 | 
             
                Model._loadIdentity = function(id) {
         | 
| 6404 6662 | 
             
                  return this.get('loaded.indexedByUnique.id').get(id);
         | 
| 6405 6663 | 
             
                };
         | 
| @@ -6625,10 +6883,7 @@ | |
| 6625 6883 | 
             
                      }
         | 
| 6626 6884 | 
             
                    },
         | 
| 6627 6885 | 
             
                    set: function(key, value) {
         | 
| 6628 | 
            -
                      var  | 
| 6629 | 
            -
                      if ((typeof value === "string") && (value.match(/[^0-9]/) === null) && (("" + (parsedValue = parseInt(value, 10))) === value)) {
         | 
| 6630 | 
            -
                        value = parsedValue;
         | 
| 6631 | 
            -
                      }
         | 
| 6886 | 
            +
                      var primaryKey;
         | 
| 6632 6887 | 
             
                      primaryKey = this.constructor.primaryKey;
         | 
| 6633 6888 | 
             
                      if (primaryKey === 'id') {
         | 
| 6634 6889 | 
             
                        this._willSet(key);
         | 
| @@ -6664,22 +6919,20 @@ | |
| 6664 6919 | 
             
                Model.prototype.toJSON = function() {
         | 
| 6665 6920 | 
             
                  var encoders, obj,
         | 
| 6666 6921 | 
             
                    _this = this;
         | 
| 6667 | 
            -
                  obj = {};
         | 
| 6668 6922 | 
             
                  encoders = this._batman.get('encoders');
         | 
| 6669 | 
            -
                  if (! | 
| 6670 | 
            -
                     | 
| 6671 | 
            -
                      var encodedVal, val;
         | 
| 6672 | 
            -
                      if (encoder.encode) {
         | 
| 6673 | 
            -
                        val = _this.get(key);
         | 
| 6674 | 
            -
                        if (typeof val !== 'undefined') {
         | 
| 6675 | 
            -
                          encodedVal = encoder.encode(val, key, obj, _this);
         | 
| 6676 | 
            -
                          if (typeof encodedVal !== 'undefined') {
         | 
| 6677 | 
            -
                            return obj[encoder.as] = encodedVal;
         | 
| 6678 | 
            -
                          }
         | 
| 6679 | 
            -
                        }
         | 
| 6680 | 
            -
                      }
         | 
| 6681 | 
            -
                    });
         | 
| 6923 | 
            +
                  if (!encoders || encoders.isEmpty()) {
         | 
| 6924 | 
            +
                    return {};
         | 
| 6682 6925 | 
             
                  }
         | 
| 6926 | 
            +
                  obj = {};
         | 
| 6927 | 
            +
                  encoders.forEach(function(key, encoder) {
         | 
| 6928 | 
            +
                    var encodedVal, val, _ref2;
         | 
| 6929 | 
            +
                    if (!encoder.encode || (val = _this.get(key)) === void 0) {
         | 
| 6930 | 
            +
                      return;
         | 
| 6931 | 
            +
                    }
         | 
| 6932 | 
            +
                    if ((encodedVal = encoder.encode(val, key, obj, _this)) !== void 0) {
         | 
| 6933 | 
            +
                      return obj[(_ref2 = typeof encoder.as === "function" ? encoder.as(key, val, obj, _this) : void 0) != null ? _ref2 : encoder.as] = encodedVal;
         | 
| 6934 | 
            +
                    }
         | 
| 6935 | 
            +
                  });
         | 
| 6683 6936 | 
             
                  return obj;
         | 
| 6684 6937 | 
             
                };
         | 
| 6685 6938 |  | 
| @@ -6697,9 +6950,16 @@ | |
| 6697 6950 | 
             
                    }
         | 
| 6698 6951 | 
             
                  } else {
         | 
| 6699 6952 | 
             
                    encoders.forEach(function(key, encoder) {
         | 
| 6700 | 
            -
                       | 
| 6701 | 
            -
             | 
| 6953 | 
            +
                      var as, _ref2;
         | 
| 6954 | 
            +
                      if (!encoder.decode) {
         | 
| 6955 | 
            +
                        return;
         | 
| 6956 | 
            +
                      }
         | 
| 6957 | 
            +
                      as = (_ref2 = typeof encoder.as === "function" ? encoder.as(key, data[key], obj, _this) : void 0) != null ? _ref2 : encoder.as;
         | 
| 6958 | 
            +
                      value = data[as];
         | 
| 6959 | 
            +
                      if (value === void 0 || (value === null && (_this._associationForAttribute(as) != null))) {
         | 
| 6960 | 
            +
                        return;
         | 
| 6702 6961 | 
             
                      }
         | 
| 6962 | 
            +
                      return obj[key] = encoder.decode(value, as, data, obj, _this);
         | 
| 6703 6963 | 
             
                    });
         | 
| 6704 6964 | 
             
                  }
         | 
| 6705 6965 | 
             
                  if (this.constructor.primaryKey !== 'id') {
         | 
| @@ -6785,11 +7045,12 @@ | |
| 6785 7045 | 
             
                  _ref3 = isNew ? ['create', 'create', 'created'] : ['save', 'update', 'saved'], startState = _ref3[0], storageOperation = _ref3[1], endState = _ref3[2];
         | 
| 6786 7046 | 
             
                  if (this.get('lifecycle').startTransition(startState)) {
         | 
| 6787 7047 | 
             
                    return this.validate(function(error, errors) {
         | 
| 6788 | 
            -
                      var associations;
         | 
| 7048 | 
            +
                      var associations, payload;
         | 
| 6789 7049 | 
             
                      if (error || errors.length) {
         | 
| 6790 7050 | 
             
                        _this.get('lifecycle').failedValidation();
         | 
| 6791 7051 | 
             
                        return typeof callback === "function" ? callback(error || errors, _this) : void 0;
         | 
| 6792 7052 | 
             
                      }
         | 
| 7053 | 
            +
                      _this.fire('validated');
         | 
| 6793 7054 | 
             
                      associations = _this.constructor._batman.get('associations');
         | 
| 6794 7055 | 
             
                      _this._withoutDirtyTracking(function() {
         | 
| 6795 7056 | 
             
                        var _ref4,
         | 
| @@ -6798,9 +7059,10 @@ | |
| 6798 7059 | 
             
                          return association.apply(_this);
         | 
| 6799 7060 | 
             
                        }) : void 0 : void 0;
         | 
| 6800 7061 | 
             
                      });
         | 
| 6801 | 
            -
                       | 
| 7062 | 
            +
                      payload = Batman.extend({}, options, {
         | 
| 6802 7063 | 
             
                        data: options
         | 
| 6803 | 
            -
                      } | 
| 7064 | 
            +
                      });
         | 
| 7065 | 
            +
                      return _this._doStorageOperation(storageOperation, payload, function(err, record, env) {
         | 
| 6804 7066 | 
             
                        if (!err) {
         | 
| 6805 7067 | 
             
                          _this.get('dirtyKeys').clear();
         | 
| 6806 7068 | 
             
                          _this.get('_dirtiedKeys').clear();
         | 
| @@ -6858,7 +7120,7 @@ | |
| 6858 7120 | 
             
                };
         | 
| 6859 7121 |  | 
| 6860 7122 | 
             
                Model.prototype.validate = function(callback) {
         | 
| 6861 | 
            -
                  var args, count, e, errors, finishedValidation, key, validator, validators, _j, _k, _len1, _len2, _ref2;
         | 
| 7123 | 
            +
                  var args, condition, count, e, errors, finishedValidation, key, validator, validators, _j, _k, _len1, _len2, _ref2;
         | 
| 6862 7124 | 
             
                  errors = this.get('errors');
         | 
| 6863 7125 | 
             
                  errors.clear();
         | 
| 6864 7126 | 
             
                  validators = this._batman.get('validators') || [];
         | 
| @@ -6878,6 +7140,20 @@ | |
| 6878 7140 | 
             
                  };
         | 
| 6879 7141 | 
             
                  for (_j = 0, _len1 = validators.length; _j < _len1; _j++) {
         | 
| 6880 7142 | 
             
                    validator = validators[_j];
         | 
| 7143 | 
            +
                    if (validator["if"]) {
         | 
| 7144 | 
            +
                      condition = typeof validator["if"] === 'string' ? this.get(validator["if"]) : validator["if"].call(this, errors, this, key);
         | 
| 7145 | 
            +
                      if (!condition) {
         | 
| 7146 | 
            +
                        finishedValidation();
         | 
| 7147 | 
            +
                        continue;
         | 
| 7148 | 
            +
                      }
         | 
| 7149 | 
            +
                    }
         | 
| 7150 | 
            +
                    if (validator.unless) {
         | 
| 7151 | 
            +
                      condition = typeof validator.unless === 'string' ? this.get(validator.unless) : validator.unless.call(this, errors, this, key);
         | 
| 7152 | 
            +
                      if (condition) {
         | 
| 7153 | 
            +
                        finishedValidation();
         | 
| 7154 | 
            +
                        continue;
         | 
| 7155 | 
            +
                      }
         | 
| 7156 | 
            +
                    }
         | 
| 6881 7157 | 
             
                    _ref2 = validator.keys;
         | 
| 6882 7158 | 
             
                    for (_k = 0, _len2 = _ref2.length; _k < _len2; _k++) {
         | 
| 6883 7159 | 
             
                      key = _ref2[_k];
         | 
| @@ -6921,6 +7197,11 @@ | |
| 6921 7197 | 
             
                  }
         | 
| 6922 7198 | 
             
                };
         | 
| 6923 7199 |  | 
| 7200 | 
            +
                Model.prototype._associationForAttribute = function(attribute) {
         | 
| 7201 | 
            +
                  var _ref2;
         | 
| 7202 | 
            +
                  return (_ref2 = this.constructor._batman.get('associations')) != null ? _ref2.get(attribute) : void 0;
         | 
| 7203 | 
            +
                };
         | 
| 7204 | 
            +
             | 
| 6924 7205 | 
             
                Model.prototype._doStorageOperation = function(operation, options, callback) {
         | 
| 6925 7206 | 
             
                  var adapter,
         | 
| 6926 7207 | 
             
                    _this = this;
         | 
| @@ -6948,6 +7229,74 @@ | |
| 6948 7229 | 
             
                  Model.prototype[functionName] = Batman.Property.wrapTrackingPrevention(Model.prototype[functionName]);
         | 
| 6949 7230 | 
             
                }
         | 
| 6950 7231 |  | 
| 7232 | 
            +
                Model.prototype.reflectOnAllAssociations = function(associationType) {
         | 
| 7233 | 
            +
                  var associations;
         | 
| 7234 | 
            +
                  associations = this.constructor._batman.get('associations');
         | 
| 7235 | 
            +
                  if (associationType != null) {
         | 
| 7236 | 
            +
                    return associations != null ? associations.getByType(associationType) : void 0;
         | 
| 7237 | 
            +
                  } else {
         | 
| 7238 | 
            +
                    return associations != null ? associations.getAll() : void 0;
         | 
| 7239 | 
            +
                  }
         | 
| 7240 | 
            +
                };
         | 
| 7241 | 
            +
             | 
| 7242 | 
            +
                Model.prototype.reflectOnAssociation = function(associationLabel) {
         | 
| 7243 | 
            +
                  var _ref3;
         | 
| 7244 | 
            +
                  return (_ref3 = this.constructor._batman.get('associations')) != null ? _ref3.getByLabel(associationLabel) : void 0;
         | 
| 7245 | 
            +
                };
         | 
| 7246 | 
            +
             | 
| 7247 | 
            +
                Model.prototype.transaction = function() {
         | 
| 7248 | 
            +
                  return this._transaction([], []);
         | 
| 7249 | 
            +
                };
         | 
| 7250 | 
            +
             | 
| 7251 | 
            +
                Model.prototype._transaction = function(visited, stack) {
         | 
| 7252 | 
            +
                  var attributes, hasManys, index, key, label, newValues, transaction, value, _k, _len2, _ref3, _ref4;
         | 
| 7253 | 
            +
                  index = visited.indexOf(this);
         | 
| 7254 | 
            +
                  if (index !== -1) {
         | 
| 7255 | 
            +
                    return stack[index];
         | 
| 7256 | 
            +
                  }
         | 
| 7257 | 
            +
                  visited.push(this);
         | 
| 7258 | 
            +
                  stack.push(transaction = new this.constructor);
         | 
| 7259 | 
            +
                  if (hasManys = this.reflectOnAllAssociations('hasMany')) {
         | 
| 7260 | 
            +
                    hasManys = hasManys.filter(function(association) {
         | 
| 7261 | 
            +
                      return association.options.includeInTransaction;
         | 
| 7262 | 
            +
                    });
         | 
| 7263 | 
            +
                    _ref3 = hasManys.mapToProperty('label');
         | 
| 7264 | 
            +
                    for (_k = 0, _len2 = _ref3.length; _k < _len2; _k++) {
         | 
| 7265 | 
            +
                      label = _ref3[_k];
         | 
| 7266 | 
            +
                      this.get(label);
         | 
| 7267 | 
            +
                    }
         | 
| 7268 | 
            +
                  }
         | 
| 7269 | 
            +
                  attributes = this.get('attributes').toObject();
         | 
| 7270 | 
            +
                  for (key in attributes) {
         | 
| 7271 | 
            +
                    if (!__hasProp.call(attributes, key)) continue;
         | 
| 7272 | 
            +
                    value = attributes[key];
         | 
| 7273 | 
            +
                    if (value instanceof Batman.Model && !value.isTransaction) {
         | 
| 7274 | 
            +
                      attributes[key] = value._transaction(visited, stack);
         | 
| 7275 | 
            +
                    } else if (value instanceof Batman.AssociationSet && !value.isTransaction) {
         | 
| 7276 | 
            +
                      newValues = new Batman.TransactionAssociationSet(value, visited, stack);
         | 
| 7277 | 
            +
                      attributes[key] = newValues;
         | 
| 7278 | 
            +
                    } else if (Batman.typeOf(value) === 'Object') {
         | 
| 7279 | 
            +
                      Batman.developer.warn("You're passing a mutable object (" + key + ", " + value.constructor.name + ") in a " + this.constructor.name + " transaction:", value);
         | 
| 7280 | 
            +
                    }
         | 
| 7281 | 
            +
                  }
         | 
| 7282 | 
            +
                  transaction._withoutDirtyTracking(function() {
         | 
| 7283 | 
            +
                    return transaction.updateAttributes(attributes);
         | 
| 7284 | 
            +
                  });
         | 
| 7285 | 
            +
                  transaction._batman.base = this;
         | 
| 7286 | 
            +
                  _ref4 = Batman.Transaction;
         | 
| 7287 | 
            +
                  for (key in _ref4) {
         | 
| 7288 | 
            +
                    value = _ref4[key];
         | 
| 7289 | 
            +
                    transaction[key] = value;
         | 
| 7290 | 
            +
                  }
         | 
| 7291 | 
            +
                  transaction.accessor('isTransaction', function() {
         | 
| 7292 | 
            +
                    return this.isTransaction;
         | 
| 7293 | 
            +
                  });
         | 
| 7294 | 
            +
                  transaction.accessor('base', function() {
         | 
| 7295 | 
            +
                    return this.base();
         | 
| 7296 | 
            +
                  });
         | 
| 7297 | 
            +
                  return transaction;
         | 
| 7298 | 
            +
                };
         | 
| 7299 | 
            +
             | 
| 6951 7300 | 
             
                return Model;
         | 
| 6952 7301 |  | 
| 6953 7302 | 
             
              }).call(this, Batman.Object);
         | 
| @@ -6964,7 +7313,7 @@ | |
| 6964 7313 | 
             
                  var collection, _base;
         | 
| 6965 7314 | 
             
                  Batman.initializeObject(this);
         | 
| 6966 7315 | 
             
                  collection = (_base = this._batman).associations || (_base.associations = new Batman.AssociationCurator(this));
         | 
| 6967 | 
            -
                  return collection.add(new Batman["" + (Batman.helpers. | 
| 7316 | 
            +
                  return collection.add(new Batman["" + (Batman.helpers.titleize(k)) + "Association"](this, label, scope));
         | 
| 6968 7317 | 
             
                };
         | 
| 6969 7318 | 
             
              };
         | 
| 6970 7319 | 
             
              for (_i = 0, _len = _ref.length; _i < _len; _i++) {
         | 
| @@ -7131,11 +7480,8 @@ | |
| 7131 7480 | 
             
                    loadOptions.urlContext = this.model;
         | 
| 7132 7481 | 
             
                  }
         | 
| 7133 7482 | 
             
                  return this.association.getRelatedModel().loadWithOptions(loadOptions, function(error, loadedRecords) {
         | 
| 7134 | 
            -
                    if (error) {
         | 
| 7135 | 
            -
                      throw error;
         | 
| 7136 | 
            -
                    }
         | 
| 7137 7483 | 
             
                    if (!loadedRecords || loadedRecords.length <= 0) {
         | 
| 7138 | 
            -
                      return callback(new Error("Couldn't find related record!"), void 0);
         | 
| 7484 | 
            +
                      return callback(error || new Error("Couldn't find related record!"), void 0);
         | 
| 7139 7485 | 
             
                    } else {
         | 
| 7140 7486 | 
             
                      return callback(void 0, loadedRecords[0]);
         | 
| 7141 7487 | 
             
                    }
         | 
| @@ -7170,18 +7516,12 @@ | |
| 7170 7516 | 
             
                };
         | 
| 7171 7517 |  | 
| 7172 7518 | 
             
                BelongsToProxy.prototype.fetchFromRemote = function(callback) {
         | 
| 7173 | 
            -
                  var loadOptions | 
| 7174 | 
            -
                    _this = this;
         | 
| 7519 | 
            +
                  var loadOptions;
         | 
| 7175 7520 | 
             
                  loadOptions = {};
         | 
| 7176 7521 | 
             
                  if (this.association.options.url) {
         | 
| 7177 7522 | 
             
                    loadOptions.recordUrl = this.association.options.url;
         | 
| 7178 7523 | 
             
                  }
         | 
| 7179 | 
            -
                  return this.association.getRelatedModel().findWithOptions(this.get('foreignValue'), loadOptions,  | 
| 7180 | 
            -
                    if (error) {
         | 
| 7181 | 
            -
                      throw error;
         | 
| 7182 | 
            -
                    }
         | 
| 7183 | 
            -
                    return callback(void 0, loadedRecord);
         | 
| 7184 | 
            -
                  });
         | 
| 7524 | 
            +
                  return this.association.getRelatedModel().findWithOptions(this.get('foreignValue'), loadOptions, callback);
         | 
| 7185 7525 | 
             
                };
         | 
| 7186 7526 |  | 
| 7187 7527 | 
             
                return BelongsToProxy;
         | 
| @@ -7212,18 +7552,12 @@ | |
| 7212 7552 | 
             
                };
         | 
| 7213 7553 |  | 
| 7214 7554 | 
             
                PolymorphicBelongsToProxy.prototype.fetchFromRemote = function(callback) {
         | 
| 7215 | 
            -
                  var loadOptions | 
| 7216 | 
            -
                    _this = this;
         | 
| 7555 | 
            +
                  var loadOptions;
         | 
| 7217 7556 | 
             
                  loadOptions = {};
         | 
| 7218 7557 | 
             
                  if (this.association.options.url) {
         | 
| 7219 7558 | 
             
                    loadOptions.recordUrl = this.association.options.url;
         | 
| 7220 7559 | 
             
                  }
         | 
| 7221 | 
            -
                  return this.association.getRelatedModelForType(this.get('foreignTypeValue')).findWithOptions(this.get('foreignValue'), loadOptions,  | 
| 7222 | 
            -
                    if (error) {
         | 
| 7223 | 
            -
                      throw error;
         | 
| 7224 | 
            -
                    }
         | 
| 7225 | 
            -
                    return callback(void 0, loadedRecord);
         | 
| 7226 | 
            -
                  });
         | 
| 7560 | 
            +
                  return this.association.getRelatedModelForType(this.get('foreignTypeValue')).findWithOptions(this.get('foreignValue'), loadOptions, callback);
         | 
| 7227 7561 | 
             
                };
         | 
| 7228 7562 |  | 
| 7229 7563 | 
             
                return PolymorphicBelongsToProxy;
         | 
| @@ -7599,10 +7933,24 @@ | |
| 7599 7933 | 
             
                  }
         | 
| 7600 7934 | 
             
                }
         | 
| 7601 7935 |  | 
| 7602 | 
            -
                Request.prototype.send = function() {
         | 
| 7603 | 
            -
                  return Batman.developer.error(" | 
| 7936 | 
            +
                Request.prototype.send = function(data) {
         | 
| 7937 | 
            +
                  return Batman.developer.error("You must add a platform library to implement Batman.Request (for example, batman.jquery)");
         | 
| 7604 7938 | 
             
                };
         | 
| 7605 7939 |  | 
| 7940 | 
            +
                Request.set('pendingRequestCount', 0);
         | 
| 7941 | 
            +
             | 
| 7942 | 
            +
                Request.classAccessor('requestIsPending', function() {
         | 
| 7943 | 
            +
                  return this.get('pendingRequestCount') > 0;
         | 
| 7944 | 
            +
                });
         | 
| 7945 | 
            +
             | 
| 7946 | 
            +
                Request.prototype.on('loading', function() {
         | 
| 7947 | 
            +
                  return Batman.Request.set('pendingRequestCount', Batman.Request.get('pendingRequestCount') + 1);
         | 
| 7948 | 
            +
                });
         | 
| 7949 | 
            +
             | 
| 7950 | 
            +
                Request.prototype.on('loaded', function() {
         | 
| 7951 | 
            +
                  return Batman.Request.set('pendingRequestCount', Batman.Request.get('pendingRequestCount') - 1);
         | 
| 7952 | 
            +
                });
         | 
| 7953 | 
            +
             | 
| 7606 7954 | 
             
                return Request;
         | 
| 7607 7955 |  | 
| 7608 7956 | 
             
              })(Batman.Object);
         | 
| @@ -7675,7 +8023,7 @@ | |
| 7675 8023 |  | 
| 7676 8024 | 
             
                SetObserver.prototype._manageObserversForItem = function(item, method) {
         | 
| 7677 8025 | 
             
                  var key, _i, _len, _ref;
         | 
| 7678 | 
            -
                  if (item.isObservable) {
         | 
| 8026 | 
            +
                  if (item != null ? item.isObservable : void 0) {
         | 
| 7679 8027 | 
             
                    _ref = this.observedItemKeys;
         | 
| 7680 8028 | 
             
                    for (_i = 0, _len = _ref.length; _i < _len; _i++) {
         | 
| 7681 8029 | 
             
                      key = _ref[_i];
         | 
| @@ -8003,16 +8351,23 @@ | |
| 8003 8351 |  | 
| 8004 8352 | 
             
                AssociationSet.accessor('loaded', Batman.Property.defaultAccessor);
         | 
| 8005 8353 |  | 
| 8006 | 
            -
                AssociationSet.prototype.load = function(callback) {
         | 
| 8007 | 
            -
                  var  | 
| 8354 | 
            +
                AssociationSet.prototype.load = function(options, callback) {
         | 
| 8355 | 
            +
                  var loadOptions,
         | 
| 8356 | 
            +
                    _this = this;
         | 
| 8357 | 
            +
                  loadOptions = this._getLoadOptions();
         | 
| 8358 | 
            +
                  if (!callback) {
         | 
| 8359 | 
            +
                    callback = options;
         | 
| 8360 | 
            +
                  } else {
         | 
| 8361 | 
            +
                    loadOptions.data = Batman.extend(loadOptions.data, options);
         | 
| 8362 | 
            +
                  }
         | 
| 8008 8363 | 
             
                  if (this.foreignKeyValue == null) {
         | 
| 8009 8364 | 
             
                    return callback(void 0, this);
         | 
| 8010 8365 | 
             
                  }
         | 
| 8011 | 
            -
                  return this.association.getRelatedModel().loadWithOptions( | 
| 8366 | 
            +
                  return this.association.getRelatedModel().loadWithOptions(loadOptions, function(err, records, env) {
         | 
| 8012 8367 | 
             
                    if (!err) {
         | 
| 8013 8368 | 
             
                      _this.markAsLoaded();
         | 
| 8014 8369 | 
             
                    }
         | 
| 8015 | 
            -
                    return callback(err, _this);
         | 
| 8370 | 
            +
                    return callback(err, _this, env);
         | 
| 8016 8371 | 
             
                  });
         | 
| 8017 8372 | 
             
                };
         | 
| 8018 8373 |  | 
| @@ -8034,6 +8389,35 @@ | |
| 8034 8389 | 
             
                  return this.fire('loaded');
         | 
| 8035 8390 | 
             
                };
         | 
| 8036 8391 |  | 
| 8392 | 
            +
                AssociationSet.accessor('parentRecord', function() {
         | 
| 8393 | 
            +
                  var parentClass, parentPrimaryKey, parentPrimaryKeyValue, query;
         | 
| 8394 | 
            +
                  parentClass = this.get('association.model');
         | 
| 8395 | 
            +
                  parentPrimaryKey = parentClass.get('primaryKey');
         | 
| 8396 | 
            +
                  parentPrimaryKeyValue = this.get('foreignKeyValue');
         | 
| 8397 | 
            +
                  query = {};
         | 
| 8398 | 
            +
                  query[parentPrimaryKey] = parentPrimaryKeyValue;
         | 
| 8399 | 
            +
                  return parentClass.createFromJSON(query);
         | 
| 8400 | 
            +
                });
         | 
| 8401 | 
            +
             | 
| 8402 | 
            +
                AssociationSet.prototype.build = function(attrs) {
         | 
| 8403 | 
            +
                  var associatedClass, initParams, mixedAttrs, newObj, options, scope;
         | 
| 8404 | 
            +
                  if (attrs == null) {
         | 
| 8405 | 
            +
                    attrs = {};
         | 
| 8406 | 
            +
                  }
         | 
| 8407 | 
            +
                  initParams = {};
         | 
| 8408 | 
            +
                  initParams[this.get('association.foreignKey')] = this.get('foreignKeyValue');
         | 
| 8409 | 
            +
                  options = this.get('association.options');
         | 
| 8410 | 
            +
                  if (options.inverseOf != null) {
         | 
| 8411 | 
            +
                    initParams[options.inverseOf] = this.get('parentRecord');
         | 
| 8412 | 
            +
                  }
         | 
| 8413 | 
            +
                  scope = options.namespace || Batman.currentApp;
         | 
| 8414 | 
            +
                  associatedClass = scope[options.name];
         | 
| 8415 | 
            +
                  mixedAttrs = Batman.extend(attrs, initParams);
         | 
| 8416 | 
            +
                  newObj = new associatedClass(mixedAttrs);
         | 
| 8417 | 
            +
                  this.add(newObj);
         | 
| 8418 | 
            +
                  return newObj;
         | 
| 8419 | 
            +
                };
         | 
| 8420 | 
            +
             | 
| 8037 8421 | 
             
                return AssociationSet;
         | 
| 8038 8422 |  | 
| 8039 8423 | 
             
              })(Batman.SetSort);
         | 
| @@ -8074,6 +8458,107 @@ | |
| 8074 8458 |  | 
| 8075 8459 | 
             
            }).call(this);
         | 
| 8076 8460 |  | 
| 8461 | 
            +
            (function() {
         | 
| 8462 | 
            +
              var __hasProp = {}.hasOwnProperty,
         | 
| 8463 | 
            +
                __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
         | 
| 8464 | 
            +
             | 
| 8465 | 
            +
              Batman.SetMapping = (function(_super) {
         | 
| 8466 | 
            +
                __extends(SetMapping, _super);
         | 
| 8467 | 
            +
             | 
| 8468 | 
            +
                function SetMapping(base, key) {
         | 
| 8469 | 
            +
                  var initialValues,
         | 
| 8470 | 
            +
                    _this = this;
         | 
| 8471 | 
            +
                  this.base = base;
         | 
| 8472 | 
            +
                  this.key = key;
         | 
| 8473 | 
            +
                  initialValues = this.base.mapToProperty(this.key);
         | 
| 8474 | 
            +
                  this._counter = new this.constructor.PresenceCounter(initialValues);
         | 
| 8475 | 
            +
                  SetMapping.__super__.constructor.apply(this, initialValues);
         | 
| 8476 | 
            +
                  this._setObserver = new Batman.SetObserver(this.base);
         | 
| 8477 | 
            +
                  this._setObserver.observedItemKeys = [this.key];
         | 
| 8478 | 
            +
                  this._setObserver.observerForItemAndKey = function(item) {
         | 
| 8479 | 
            +
                    return function(newValue, oldValue) {
         | 
| 8480 | 
            +
                      return _this._handleItemModified(item, newValue, oldValue);
         | 
| 8481 | 
            +
                    };
         | 
| 8482 | 
            +
                  };
         | 
| 8483 | 
            +
                  this._setObserver.on('itemsWereAdded', this._handleItemsAdded.bind(this));
         | 
| 8484 | 
            +
                  this._setObserver.on('itemsWereRemoved', this._handleItemsRemoved.bind(this));
         | 
| 8485 | 
            +
                  this._setObserver.startObserving();
         | 
| 8486 | 
            +
                }
         | 
| 8487 | 
            +
             | 
| 8488 | 
            +
                SetMapping.prototype._handleItemsAdded = function(items, indexes) {
         | 
| 8489 | 
            +
                  var item, _i, _len, _results;
         | 
| 8490 | 
            +
                  _results = [];
         | 
| 8491 | 
            +
                  for (_i = 0, _len = items.length; _i < _len; _i++) {
         | 
| 8492 | 
            +
                    item = items[_i];
         | 
| 8493 | 
            +
                    _results.push(this._addValueInstance(item.get(this.key)));
         | 
| 8494 | 
            +
                  }
         | 
| 8495 | 
            +
                  return _results;
         | 
| 8496 | 
            +
                };
         | 
| 8497 | 
            +
             | 
| 8498 | 
            +
                SetMapping.prototype._handleItemsRemoved = function(items, indexes) {
         | 
| 8499 | 
            +
                  var item, _i, _len, _results;
         | 
| 8500 | 
            +
                  _results = [];
         | 
| 8501 | 
            +
                  for (_i = 0, _len = items.length; _i < _len; _i++) {
         | 
| 8502 | 
            +
                    item = items[_i];
         | 
| 8503 | 
            +
                    _results.push(this._removeValueInstance(item.get(this.key)));
         | 
| 8504 | 
            +
                  }
         | 
| 8505 | 
            +
                  return _results;
         | 
| 8506 | 
            +
                };
         | 
| 8507 | 
            +
             | 
| 8508 | 
            +
                SetMapping.prototype._handleItemModified = function(item, newValue, oldValue) {
         | 
| 8509 | 
            +
                  this._removeValueInstance(oldValue);
         | 
| 8510 | 
            +
                  return this._addValueInstance(newValue);
         | 
| 8511 | 
            +
                };
         | 
| 8512 | 
            +
             | 
| 8513 | 
            +
                SetMapping.prototype._addValueInstance = function(mappedValue) {
         | 
| 8514 | 
            +
                  this._counter.increment(mappedValue);
         | 
| 8515 | 
            +
                  return this.add(mappedValue);
         | 
| 8516 | 
            +
                };
         | 
| 8517 | 
            +
             | 
| 8518 | 
            +
                SetMapping.prototype._removeValueInstance = function(mappedValue) {
         | 
| 8519 | 
            +
                  var remaining;
         | 
| 8520 | 
            +
                  remaining = this._counter.decrement(mappedValue);
         | 
| 8521 | 
            +
                  if (remaining === 0) {
         | 
| 8522 | 
            +
                    return this.remove(mappedValue);
         | 
| 8523 | 
            +
                  }
         | 
| 8524 | 
            +
                };
         | 
| 8525 | 
            +
             | 
| 8526 | 
            +
                return SetMapping;
         | 
| 8527 | 
            +
             | 
| 8528 | 
            +
              })(Batman.Set);
         | 
| 8529 | 
            +
             | 
| 8530 | 
            +
              Batman.SetMapping.PresenceCounter = (function() {
         | 
| 8531 | 
            +
                function PresenceCounter(initialValues) {
         | 
| 8532 | 
            +
                  var value, _i, _len;
         | 
| 8533 | 
            +
                  this._storage = new Batman.SimpleHash;
         | 
| 8534 | 
            +
                  for (_i = 0, _len = initialValues.length; _i < _len; _i++) {
         | 
| 8535 | 
            +
                    value = initialValues[_i];
         | 
| 8536 | 
            +
                    this.increment(value);
         | 
| 8537 | 
            +
                  }
         | 
| 8538 | 
            +
                }
         | 
| 8539 | 
            +
             | 
| 8540 | 
            +
                PresenceCounter.prototype.increment = function(value) {
         | 
| 8541 | 
            +
                  var count;
         | 
| 8542 | 
            +
                  count = this._storage.get(value);
         | 
| 8543 | 
            +
                  if (!count) {
         | 
| 8544 | 
            +
                    return this._storage.set(value, 1);
         | 
| 8545 | 
            +
                  } else {
         | 
| 8546 | 
            +
                    return this._storage.set(value, count + 1);
         | 
| 8547 | 
            +
                  }
         | 
| 8548 | 
            +
                };
         | 
| 8549 | 
            +
             | 
| 8550 | 
            +
                PresenceCounter.prototype.decrement = function(value) {
         | 
| 8551 | 
            +
                  var count;
         | 
| 8552 | 
            +
                  count = this._storage.get(value);
         | 
| 8553 | 
            +
                  return this._storage.set(value, count - 1);
         | 
| 8554 | 
            +
                };
         | 
| 8555 | 
            +
             | 
| 8556 | 
            +
                return PresenceCounter;
         | 
| 8557 | 
            +
             | 
| 8558 | 
            +
              })();
         | 
| 8559 | 
            +
             | 
| 8560 | 
            +
            }).call(this);
         | 
| 8561 | 
            +
             | 
| 8077 8562 | 
             
            (function() {
         | 
| 8078 8563 | 
             
              var __hasProp = {}.hasOwnProperty,
         | 
| 8079 8564 | 
             
                __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
         | 
| @@ -8944,6 +9429,9 @@ | |
| 8944 9429 | 
             
                };
         | 
| 8945 9430 |  | 
| 8946 9431 | 
             
                RouteMapBuilder.prototype.root = function(signature, options) {
         | 
| 9432 | 
            +
                  if (options == null) {
         | 
| 9433 | 
            +
                    options = {};
         | 
| 9434 | 
            +
                  }
         | 
| 8947 9435 | 
             
                  return this.route('/', signature, options);
         | 
| 8948 9436 | 
             
                };
         | 
| 8949 9437 |  | 
| @@ -9018,7 +9506,10 @@ | |
| 9018 9506 | 
             
                  klass = options.callback ? Batman.CallbackActionRoute : Batman.ControllerActionRoute;
         | 
| 9019 9507 | 
             
                  options.app = this.app;
         | 
| 9020 9508 | 
             
                  route = new klass(path, options);
         | 
| 9021 | 
            -
                   | 
| 9509 | 
            +
                  this.routeMap.addRoute(name, route);
         | 
| 9510 | 
            +
                  if (name === '') {
         | 
| 9511 | 
            +
                    return this.routeMap.addRoute('root', route);
         | 
| 9512 | 
            +
                  }
         | 
| 9022 9513 | 
             
                };
         | 
| 9023 9514 |  | 
| 9024 9515 | 
             
                RouteMapBuilder.prototype._nameFromPath = function(path) {
         | 
| @@ -9248,9 +9739,10 @@ | |
| 9248 9739 | 
             
                Association.prototype.isPolymorphic = false;
         | 
| 9249 9740 |  | 
| 9250 9741 | 
             
                Association.prototype.defaultOptions = {
         | 
| 9251 | 
            -
                  saveInline:  | 
| 9742 | 
            +
                  saveInline: false,
         | 
| 9252 9743 | 
             
                  autoload: true,
         | 
| 9253 | 
            -
                  nestUrl: false
         | 
| 9744 | 
            +
                  nestUrl: false,
         | 
| 9745 | 
            +
                  includeInTransaction: true
         | 
| 9254 9746 | 
             
                };
         | 
| 9255 9747 |  | 
| 9256 9748 | 
             
                function Association(model, label, options) {
         | 
| @@ -9626,7 +10118,7 @@ | |
| 9626 10118 | 
             
                  }
         | 
| 9627 10119 | 
             
                  Batman.developer["do"](function() {
         | 
| 9628 10120 | 
             
                    if ((Batman.currentApp != null) && !relatedModel) {
         | 
| 9629 | 
            -
                      return Batman.developer.warn("Related model " + type + " for polymorphic association not found.");
         | 
| 10121 | 
            +
                      return Batman.developer.warn("Related model " + type + " for hasMany polymorphic association " + this.label + " not found.");
         | 
| 9630 10122 | 
             
                    }
         | 
| 9631 10123 | 
             
                  });
         | 
| 9632 10124 | 
             
                  return relatedModel;
         | 
| @@ -9729,21 +10221,13 @@ | |
| 9729 10221 | 
             
                SingularAssociation.prototype.isSingular = true;
         | 
| 9730 10222 |  | 
| 9731 10223 | 
             
                SingularAssociation.prototype.getAccessor = function(association, model, label) {
         | 
| 9732 | 
            -
                  var proxy, record, recordInAttributes | 
| 9733 | 
            -
                    _this = this;
         | 
| 10224 | 
            +
                  var proxy, record, recordInAttributes;
         | 
| 9734 10225 | 
             
                  if (recordInAttributes = association.getFromAttributes(this)) {
         | 
| 9735 10226 | 
             
                    return recordInAttributes;
         | 
| 9736 10227 | 
             
                  }
         | 
| 9737 10228 | 
             
                  if (association.getRelatedModel()) {
         | 
| 9738 10229 | 
             
                    proxy = this.associationProxy(association);
         | 
| 9739 10230 | 
             
                    record = false;
         | 
| 9740 | 
            -
                    if (proxy._loadSetter == null) {
         | 
| 9741 | 
            -
                      proxy._loadSetter = proxy.once('loaded', function(child) {
         | 
| 9742 | 
            -
                        return _this._withoutDirtyTracking(function() {
         | 
| 9743 | 
            -
                          return this.set(association.label, child);
         | 
| 9744 | 
            -
                        });
         | 
| 9745 | 
            -
                      });
         | 
| 9746 | 
            -
                    }
         | 
| 9747 10231 | 
             
                    if (!Batman.Property.withoutTracking(function() {
         | 
| 9748 10232 | 
             
                      return proxy.get('loaded');
         | 
| 9749 10233 | 
             
                    })) {
         | 
| @@ -9935,7 +10419,7 @@ | |
| 9935 10419 | 
             
                  if (this.options.encodeForeignTypeKey) {
         | 
| 9936 10420 | 
             
                    this.model.encode(this.foreignTypeKey);
         | 
| 9937 10421 | 
             
                  }
         | 
| 9938 | 
            -
                  this. | 
| 10422 | 
            +
                  this.typeIndices = {};
         | 
| 9939 10423 | 
             
                }
         | 
| 9940 10424 |  | 
| 9941 10425 | 
             
                PolymorphicBelongsToAssociation.prototype.getRelatedModel = false;
         | 
| @@ -9990,7 +10474,7 @@ | |
| 9990 10474 | 
             
                  }
         | 
| 9991 10475 | 
             
                  Batman.developer["do"](function() {
         | 
| 9992 10476 | 
             
                    if ((Batman.currentApp != null) && !relatedModel) {
         | 
| 9993 | 
            -
                      return Batman.developer.warn("Related model " + type + " for polymorphic association not found.");
         | 
| 10477 | 
            +
                      return Batman.developer.warn("Related model " + type + " for belongsTo polymorphic association " + this.label + " not found.");
         | 
| 9994 10478 | 
             
                    }
         | 
| 9995 10479 | 
             
                  });
         | 
| 9996 10480 | 
             
                  return relatedModel;
         | 
| @@ -9998,8 +10482,8 @@ | |
| 9998 10482 |  | 
| 9999 10483 | 
             
                PolymorphicBelongsToAssociation.prototype.setIndexForType = function(type) {
         | 
| 10000 10484 | 
             
                  var _base;
         | 
| 10001 | 
            -
                  (_base = this. | 
| 10002 | 
            -
                  return this. | 
| 10485 | 
            +
                  (_base = this.typeIndices)[type] || (_base[type] = new Batman.PolymorphicUniqueAssociationSetIndex(this, type, this.primaryKey));
         | 
| 10486 | 
            +
                  return this.typeIndices[type];
         | 
| 10003 10487 | 
             
                };
         | 
| 10004 10488 |  | 
| 10005 10489 | 
             
                PolymorphicBelongsToAssociation.prototype.inverseForType = function(type) {
         | 
| @@ -10049,9 +10533,193 @@ | |
| 10049 10533 | 
             
            }).call(this);
         | 
| 10050 10534 |  | 
| 10051 10535 | 
             
            (function() {
         | 
| 10052 | 
            -
              var __hasProp = {}.hasOwnProperty | 
| 10053 | 
            -
             | 
| 10054 | 
            -
             | 
| 10536 | 
            +
              var __hasProp = {}.hasOwnProperty;
         | 
| 10537 | 
            +
             | 
| 10538 | 
            +
              Batman.Transaction = {
         | 
| 10539 | 
            +
                isTransaction: true,
         | 
| 10540 | 
            +
                base: function() {
         | 
| 10541 | 
            +
                  return this._batman.base;
         | 
| 10542 | 
            +
                },
         | 
| 10543 | 
            +
                applyChanges: function(visited) {
         | 
| 10544 | 
            +
                  var attributes, base, key, updatedAssociationSet, value, _ref;
         | 
| 10545 | 
            +
                  if (visited == null) {
         | 
| 10546 | 
            +
                    visited = [];
         | 
| 10547 | 
            +
                  }
         | 
| 10548 | 
            +
                  if (visited.indexOf(this) !== -1) {
         | 
| 10549 | 
            +
                    return this.base();
         | 
| 10550 | 
            +
                  }
         | 
| 10551 | 
            +
                  visited.push(this);
         | 
| 10552 | 
            +
                  attributes = this.get('attributes').toObject();
         | 
| 10553 | 
            +
                  for (key in attributes) {
         | 
| 10554 | 
            +
                    if (!__hasProp.call(attributes, key)) continue;
         | 
| 10555 | 
            +
                    value = attributes[key];
         | 
| 10556 | 
            +
                    if (value instanceof Batman.Model && value.isTransaction) {
         | 
| 10557 | 
            +
                      value.applyChanges(visited);
         | 
| 10558 | 
            +
                      delete attributes[key];
         | 
| 10559 | 
            +
                    } else if (value instanceof Batman.TransactionAssociationSet) {
         | 
| 10560 | 
            +
                      updatedAssociationSet = value.applyChanges(visited);
         | 
| 10561 | 
            +
                      attributes[key] = updatedAssociationSet;
         | 
| 10562 | 
            +
                    }
         | 
| 10563 | 
            +
                  }
         | 
| 10564 | 
            +
                  base = this.base();
         | 
| 10565 | 
            +
                  base.mixin(attributes);
         | 
| 10566 | 
            +
                  return (_ref = typeof base.applyChanges === "function" ? base.applyChanges() : void 0) != null ? _ref : base;
         | 
| 10567 | 
            +
                },
         | 
| 10568 | 
            +
                save: function(options, callback) {
         | 
| 10569 | 
            +
                  var finish, validated, _ref,
         | 
| 10570 | 
            +
                    _this = this;
         | 
| 10571 | 
            +
                  if (!callback) {
         | 
| 10572 | 
            +
                    _ref = [{}, options], options = _ref[0], callback = _ref[1];
         | 
| 10573 | 
            +
                  }
         | 
| 10574 | 
            +
                  this.once('validated', validated = function() {
         | 
| 10575 | 
            +
                    return _this.applyChanges();
         | 
| 10576 | 
            +
                  });
         | 
| 10577 | 
            +
                  finish = function() {
         | 
| 10578 | 
            +
                    _this.off('validated', validated);
         | 
| 10579 | 
            +
                    return typeof callback === "function" ? callback.apply(null, arguments) : void 0;
         | 
| 10580 | 
            +
                  };
         | 
| 10581 | 
            +
                  return this.constructor.prototype.save.call(this, options, function(err, result) {
         | 
| 10582 | 
            +
                    if (!err) {
         | 
| 10583 | 
            +
                      result = _this.base();
         | 
| 10584 | 
            +
                      result.get('dirtyKeys').clear();
         | 
| 10585 | 
            +
                      result.get('_dirtiedKeys').clear();
         | 
| 10586 | 
            +
                      result.get('lifecycle').startTransition('save');
         | 
| 10587 | 
            +
                      result.get('lifecycle').startTransition('saved');
         | 
| 10588 | 
            +
                    }
         | 
| 10589 | 
            +
                    return finish(err, result);
         | 
| 10590 | 
            +
                  });
         | 
| 10591 | 
            +
                }
         | 
| 10592 | 
            +
              };
         | 
| 10593 | 
            +
             | 
| 10594 | 
            +
            }).call(this);
         | 
| 10595 | 
            +
             | 
| 10596 | 
            +
            (function() {
         | 
| 10597 | 
            +
              var __hasProp = {}.hasOwnProperty,
         | 
| 10598 | 
            +
                __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
         | 
| 10599 | 
            +
                __slice = [].slice;
         | 
| 10600 | 
            +
             | 
| 10601 | 
            +
              Batman.TransactionAssociationSet = (function(_super) {
         | 
| 10602 | 
            +
                __extends(TransactionAssociationSet, _super);
         | 
| 10603 | 
            +
             | 
| 10604 | 
            +
                TransactionAssociationSet.prototype.isTransaction = true;
         | 
| 10605 | 
            +
             | 
| 10606 | 
            +
                function TransactionAssociationSet(associationSet, visited, stack) {
         | 
| 10607 | 
            +
                  this.set('associationSet', associationSet);
         | 
| 10608 | 
            +
                  this._loader = this._addFromAssociationSet.bind(this);
         | 
| 10609 | 
            +
                  associationSet.on('itemsWereAdded', this._loader);
         | 
| 10610 | 
            +
                  this._visited = visited;
         | 
| 10611 | 
            +
                  this._stack = stack;
         | 
| 10612 | 
            +
                  this._storage = [];
         | 
| 10613 | 
            +
                  this._originalStorage = [];
         | 
| 10614 | 
            +
                  this._removedStorage = [];
         | 
| 10615 | 
            +
                  this.add.apply(this, associationSet.toArray());
         | 
| 10616 | 
            +
                }
         | 
| 10617 | 
            +
             | 
| 10618 | 
            +
                TransactionAssociationSet.delegate('association', 'foreignKeyValue', {
         | 
| 10619 | 
            +
                  to: 'associationSet'
         | 
| 10620 | 
            +
                });
         | 
| 10621 | 
            +
             | 
| 10622 | 
            +
                TransactionAssociationSet.prototype._addFromAssociationSet = function(items, indexes) {
         | 
| 10623 | 
            +
                  return this.add.apply(this, items);
         | 
| 10624 | 
            +
                };
         | 
| 10625 | 
            +
             | 
| 10626 | 
            +
                TransactionAssociationSet.prototype.add = TransactionAssociationSet.mutation(function() {
         | 
| 10627 | 
            +
                  var addedTransactions, item, items, originalIndex, removedIndex, transactionItem, _i, _len;
         | 
| 10628 | 
            +
                  items = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
         | 
| 10629 | 
            +
                  addedTransactions = [];
         | 
| 10630 | 
            +
                  for (_i = 0, _len = items.length; _i < _len; _i++) {
         | 
| 10631 | 
            +
                    item = items[_i];
         | 
| 10632 | 
            +
                    if (!(item instanceof Batman.Model && !item.isTransaction)) {
         | 
| 10633 | 
            +
                      Batman.developer.warn("You tried to add a " + item.constructor.name + " to a TransactionAssociationSet (" + (this.get('association.label')) + ")", item);
         | 
| 10634 | 
            +
                      continue;
         | 
| 10635 | 
            +
                    }
         | 
| 10636 | 
            +
                    transactionItem = item._transaction(this._visited, this._stack);
         | 
| 10637 | 
            +
                    this._storage.push(transactionItem);
         | 
| 10638 | 
            +
                    addedTransactions.push(transactionItem);
         | 
| 10639 | 
            +
                    originalIndex = this._originalStorage.indexOf(item);
         | 
| 10640 | 
            +
                    if (originalIndex === -1) {
         | 
| 10641 | 
            +
                      this._originalStorage.push(item);
         | 
| 10642 | 
            +
                    }
         | 
| 10643 | 
            +
                    removedIndex = this._removedStorage.indexOf(item);
         | 
| 10644 | 
            +
                    if (removedIndex > -1) {
         | 
| 10645 | 
            +
                      this._removedStorage.splice(removedIndex, 1);
         | 
| 10646 | 
            +
                    }
         | 
| 10647 | 
            +
                  }
         | 
| 10648 | 
            +
                  this.length = this._storage.length;
         | 
| 10649 | 
            +
                  if (addedTransactions.length) {
         | 
| 10650 | 
            +
                    this.fire('itemsWereAdded', addedTransactions);
         | 
| 10651 | 
            +
                  }
         | 
| 10652 | 
            +
                  return addedTransactions;
         | 
| 10653 | 
            +
                });
         | 
| 10654 | 
            +
             | 
| 10655 | 
            +
                TransactionAssociationSet.prototype.remove = TransactionAssociationSet.mutation(function() {
         | 
| 10656 | 
            +
                  var item, originalIndex, removedTransactions, transactionIndex, transactionItem, transactions, _i, _len;
         | 
| 10657 | 
            +
                  transactions = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
         | 
| 10658 | 
            +
                  removedTransactions = [];
         | 
| 10659 | 
            +
                  for (_i = 0, _len = transactions.length; _i < _len; _i++) {
         | 
| 10660 | 
            +
                    transactionItem = transactions[_i];
         | 
| 10661 | 
            +
                    if (!transactionItem.isTransaction) {
         | 
| 10662 | 
            +
                      throw "Tried to remove real item from transaction set: " + (t.toJSON());
         | 
| 10663 | 
            +
                    }
         | 
| 10664 | 
            +
                    transactionIndex = this._storage.indexOf(transactionItem);
         | 
| 10665 | 
            +
                    if (transactionIndex > -1) {
         | 
| 10666 | 
            +
                      this._storage.splice(transactionIndex, 1);
         | 
| 10667 | 
            +
                      removedTransactions.push(transactionItem);
         | 
| 10668 | 
            +
                    }
         | 
| 10669 | 
            +
                    item = transactionItem.base();
         | 
| 10670 | 
            +
                    originalIndex = this._originalStorage.indexOf(item);
         | 
| 10671 | 
            +
                    if (originalIndex > -1) {
         | 
| 10672 | 
            +
                      this._removedStorage.push(item);
         | 
| 10673 | 
            +
                      this._originalStorage.splice(originalIndex, 1);
         | 
| 10674 | 
            +
                    }
         | 
| 10675 | 
            +
                  }
         | 
| 10676 | 
            +
                  this.length = this._storage.length;
         | 
| 10677 | 
            +
                  if (removedTransactions.length) {
         | 
| 10678 | 
            +
                    this.fire('itemsWereRemoved', removedTransactions);
         | 
| 10679 | 
            +
                  }
         | 
| 10680 | 
            +
                  return removedTransactions;
         | 
| 10681 | 
            +
                });
         | 
| 10682 | 
            +
             | 
| 10683 | 
            +
                TransactionAssociationSet.prototype.applyChanges = function(visited) {
         | 
| 10684 | 
            +
                  var originals, target, transactionItem, _i, _len, _ref;
         | 
| 10685 | 
            +
                  _ref = this._storage;
         | 
| 10686 | 
            +
                  for (_i = 0, _len = _ref.length; _i < _len; _i++) {
         | 
| 10687 | 
            +
                    transactionItem = _ref[_i];
         | 
| 10688 | 
            +
                    transactionItem.applyChanges(visited);
         | 
| 10689 | 
            +
                  }
         | 
| 10690 | 
            +
                  originals = (function(func, args, ctor) {
         | 
| 10691 | 
            +
                    ctor.prototype = func.prototype;
         | 
| 10692 | 
            +
                    var child = new ctor, result = func.apply(child, args);
         | 
| 10693 | 
            +
                    return Object(result) === result ? result : child;
         | 
| 10694 | 
            +
                  })(Batman.Set, this._originalStorage, function(){});
         | 
| 10695 | 
            +
                  target = this.get('associationSet');
         | 
| 10696 | 
            +
                  target.off('itemsWereAdded', this._loader);
         | 
| 10697 | 
            +
                  target.replace(originals);
         | 
| 10698 | 
            +
                  target.set('removedItems', (function(func, args, ctor) {
         | 
| 10699 | 
            +
                    ctor.prototype = func.prototype;
         | 
| 10700 | 
            +
                    var child = new ctor, result = func.apply(child, args);
         | 
| 10701 | 
            +
                    return Object(result) === result ? result : child;
         | 
| 10702 | 
            +
                  })(Batman.Set, this._removedStorage, function(){}));
         | 
| 10703 | 
            +
                  return target;
         | 
| 10704 | 
            +
                };
         | 
| 10705 | 
            +
             | 
| 10706 | 
            +
                TransactionAssociationSet.accessor('length', function() {
         | 
| 10707 | 
            +
                  this.registerAsMutableSource();
         | 
| 10708 | 
            +
                  return this.length;
         | 
| 10709 | 
            +
                });
         | 
| 10710 | 
            +
             | 
| 10711 | 
            +
                TransactionAssociationSet.prototype.build = Batman.AssociationSet.prototype.build;
         | 
| 10712 | 
            +
             | 
| 10713 | 
            +
                return TransactionAssociationSet;
         | 
| 10714 | 
            +
             | 
| 10715 | 
            +
              })(Batman.Set);
         | 
| 10716 | 
            +
             | 
| 10717 | 
            +
            }).call(this);
         | 
| 10718 | 
            +
             | 
| 10719 | 
            +
            (function() {
         | 
| 10720 | 
            +
              var __hasProp = {}.hasOwnProperty,
         | 
| 10721 | 
            +
                __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
         | 
| 10722 | 
            +
                __slice = [].slice;
         | 
| 10055 10723 |  | 
| 10056 10724 | 
             
              Batman.Validator = (function(_super) {
         | 
| 10057 10725 | 
             
                __extends(Validator, _super);
         | 
| @@ -10102,12 +10770,20 @@ | |
| 10102 10770 | 
             
                  Validator.__super__.constructor.apply(this, mixins);
         | 
| 10103 10771 | 
             
                }
         | 
| 10104 10772 |  | 
| 10105 | 
            -
                Validator.prototype. | 
| 10106 | 
            -
                  return Batman.developer.error("You must override  | 
| 10773 | 
            +
                Validator.prototype.validateEach = function(record) {
         | 
| 10774 | 
            +
                  return Batman.developer.error("You must override validateEach in Batman.Validator subclasses.");
         | 
| 10107 10775 | 
             
                };
         | 
| 10108 10776 |  | 
| 10109 | 
            -
                Validator.prototype.format = function( | 
| 10110 | 
            -
                   | 
| 10777 | 
            +
                Validator.prototype.format = function(attr, messageKey, interpolations, record) {
         | 
| 10778 | 
            +
                  if (this.options.message) {
         | 
| 10779 | 
            +
                    if (typeof this.options.message === 'function') {
         | 
| 10780 | 
            +
                      return this.options.message.call(record, attr, messageKey);
         | 
| 10781 | 
            +
                    } else {
         | 
| 10782 | 
            +
                      return this.options.message;
         | 
| 10783 | 
            +
                    }
         | 
| 10784 | 
            +
                  } else {
         | 
| 10785 | 
            +
                    return Batman.t("errors.messages." + messageKey, interpolations);
         | 
| 10786 | 
            +
                  }
         | 
| 10111 10787 | 
             
                };
         | 
| 10112 10788 |  | 
| 10113 10789 | 
             
                Validator.prototype.handleBlank = function(value) {
         | 
| @@ -10142,10 +10818,13 @@ | |
| 10142 10818 | 
             
                    equal_to: "must be equal to %{count}",
         | 
| 10143 10819 | 
             
                    less_than: "must be less than %{count}",
         | 
| 10144 10820 | 
             
                    less_than_or_equal_to: "must be less than or equal to %{count}",
         | 
| 10821 | 
            +
                    not_an_integer: "must be an integer",
         | 
| 10145 10822 | 
             
                    not_matching: "is not valid",
         | 
| 10146 10823 | 
             
                    invalid_association: "is not valid",
         | 
| 10147 10824 | 
             
                    not_included_in_list: "is not included in the list",
         | 
| 10148 | 
            -
                    included_in_list: "is included in the list"
         | 
| 10825 | 
            +
                    included_in_list: "is included in the list",
         | 
| 10826 | 
            +
                    not_an_email: "is not a valid email address",
         | 
| 10827 | 
            +
                    confirmation_does_not_match: 'and confirmation do not match'
         | 
| 10149 10828 | 
             
                  }
         | 
| 10150 10829 | 
             
                }
         | 
| 10151 10830 | 
             
              });
         | 
| @@ -10176,7 +10855,7 @@ | |
| 10176 10855 | 
             
                    return callback();
         | 
| 10177 10856 | 
             
                  }
         | 
| 10178 10857 | 
             
                  if ((value == null) || value === '' || !this.regexp.test(value)) {
         | 
| 10179 | 
            -
                    errors.add(key, this.format(key, 'not_matching'));
         | 
| 10858 | 
            +
                    errors.add(key, this.format(key, 'not_matching', {}, record));
         | 
| 10180 10859 | 
             
                  }
         | 
| 10181 10860 | 
             
                  return callback();
         | 
| 10182 10861 | 
             
                };
         | 
| @@ -10208,7 +10887,7 @@ | |
| 10208 10887 | 
             
                  var value;
         | 
| 10209 10888 | 
             
                  value = record.get(key);
         | 
| 10210 10889 | 
             
                  if (!this.isPresent(value)) {
         | 
| 10211 | 
            -
                    errors.add(key, this.format(key, 'blank'));
         | 
| 10890 | 
            +
                    errors.add(key, this.format(key, 'blank', {}, record));
         | 
| 10212 10891 | 
             
                  }
         | 
| 10213 10892 | 
             
                  return callback();
         | 
| 10214 10893 | 
             
                };
         | 
| @@ -10238,7 +10917,7 @@ | |
| 10238 10917 | 
             
                  return _ref;
         | 
| 10239 10918 | 
             
                }
         | 
| 10240 10919 |  | 
| 10241 | 
            -
                NumericValidator.triggers('numeric', 'greaterThan', 'greaterThanOrEqualTo', 'equalTo', 'lessThan', 'lessThanOrEqualTo');
         | 
| 10920 | 
            +
                NumericValidator.triggers('numeric', 'greaterThan', 'greaterThanOrEqualTo', 'equalTo', 'lessThan', 'lessThanOrEqualTo', 'onlyInteger');
         | 
| 10242 10921 |  | 
| 10243 10922 | 
             
                NumericValidator.options('allowBlank');
         | 
| 10244 10923 |  | 
| @@ -10250,32 +10929,34 @@ | |
| 10250 10929 | 
             
                    return callback();
         | 
| 10251 10930 | 
             
                  }
         | 
| 10252 10931 | 
             
                  if ((value == null) || !(this.isNumeric(value) || this.canCoerceToNumeric(value))) {
         | 
| 10253 | 
            -
                    errors.add(key, this.format(key, 'not_numeric'));
         | 
| 10932 | 
            +
                    errors.add(key, this.format(key, 'not_numeric', {}, record));
         | 
| 10933 | 
            +
                  } else if (options.onlyInteger && !this.isInteger(value)) {
         | 
| 10934 | 
            +
                    errors.add(key, this.format(key, 'not_an_integer', {}, record));
         | 
| 10254 10935 | 
             
                  } else {
         | 
| 10255 10936 | 
             
                    if ((options.greaterThan != null) && value <= options.greaterThan) {
         | 
| 10256 10937 | 
             
                      errors.add(key, this.format(key, 'greater_than', {
         | 
| 10257 10938 | 
             
                        count: options.greaterThan
         | 
| 10258 | 
            -
                      }));
         | 
| 10939 | 
            +
                      }, record));
         | 
| 10259 10940 | 
             
                    }
         | 
| 10260 10941 | 
             
                    if ((options.greaterThanOrEqualTo != null) && value < options.greaterThanOrEqualTo) {
         | 
| 10261 10942 | 
             
                      errors.add(key, this.format(key, 'greater_than_or_equal_to', {
         | 
| 10262 10943 | 
             
                        count: options.greaterThanOrEqualTo
         | 
| 10263 | 
            -
                      }));
         | 
| 10944 | 
            +
                      }, record));
         | 
| 10264 10945 | 
             
                    }
         | 
| 10265 10946 | 
             
                    if ((options.equalTo != null) && value !== options.equalTo) {
         | 
| 10266 10947 | 
             
                      errors.add(key, this.format(key, 'equal_to', {
         | 
| 10267 10948 | 
             
                        count: options.equalTo
         | 
| 10268 | 
            -
                      }));
         | 
| 10949 | 
            +
                      }, record));
         | 
| 10269 10950 | 
             
                    }
         | 
| 10270 10951 | 
             
                    if ((options.lessThan != null) && value >= options.lessThan) {
         | 
| 10271 10952 | 
             
                      errors.add(key, this.format(key, 'less_than', {
         | 
| 10272 10953 | 
             
                        count: options.lessThan
         | 
| 10273 | 
            -
                      }));
         | 
| 10954 | 
            +
                      }, record));
         | 
| 10274 10955 | 
             
                    }
         | 
| 10275 10956 | 
             
                    if ((options.lessThanOrEqualTo != null) && value > options.lessThanOrEqualTo) {
         | 
| 10276 10957 | 
             
                      errors.add(key, this.format(key, 'less_than_or_equal_to', {
         | 
| 10277 10958 | 
             
                        count: options.lessThanOrEqualTo
         | 
| 10278 | 
            -
                      }));
         | 
| 10959 | 
            +
                      }, record));
         | 
| 10279 10960 | 
             
                    }
         | 
| 10280 10961 | 
             
                  }
         | 
| 10281 10962 | 
             
                  return callback();
         | 
| @@ -10285,6 +10966,10 @@ | |
| 10285 10966 | 
             
                  return !isNaN(parseFloat(value)) && isFinite(value);
         | 
| 10286 10967 | 
             
                };
         | 
| 10287 10968 |  | 
| 10969 | 
            +
                NumericValidator.prototype.isInteger = function(value) {
         | 
| 10970 | 
            +
                  return parseFloat(value) === (value | 0);
         | 
| 10971 | 
            +
                };
         | 
| 10972 | 
            +
             | 
| 10288 10973 | 
             
                NumericValidator.prototype.canCoerceToNumeric = function(value) {
         | 
| 10289 10974 | 
             
                  return (value - 0) == value && value.length > 0;
         | 
| 10290 10975 | 
             
                };
         | 
| @@ -10323,7 +11008,7 @@ | |
| 10323 11008 | 
             
                  var options, value;
         | 
| 10324 11009 | 
             
                  options = this.options;
         | 
| 10325 11010 | 
             
                  value = record.get(key);
         | 
| 10326 | 
            -
                  if ( | 
| 11011 | 
            +
                  if (this.handleBlank(value)) {
         | 
| 10327 11012 | 
             
                    return callback();
         | 
| 10328 11013 | 
             
                  }
         | 
| 10329 11014 | 
             
                  if (value == null) {
         | 
| @@ -10332,17 +11017,17 @@ | |
| 10332 11017 | 
             
                  if (options.minLength && value.length < options.minLength) {
         | 
| 10333 11018 | 
             
                    errors.add(key, this.format(key, 'too_short', {
         | 
| 10334 11019 | 
             
                      count: options.minLength
         | 
| 10335 | 
            -
                    }));
         | 
| 11020 | 
            +
                    }, record));
         | 
| 10336 11021 | 
             
                  }
         | 
| 10337 11022 | 
             
                  if (options.maxLength && value.length > options.maxLength) {
         | 
| 10338 11023 | 
             
                    errors.add(key, this.format(key, 'too_long', {
         | 
| 10339 11024 | 
             
                      count: options.maxLength
         | 
| 10340 | 
            -
                    }));
         | 
| 11025 | 
            +
                    }, record));
         | 
| 10341 11026 | 
             
                  }
         | 
| 10342 11027 | 
             
                  if (options.length && value.length !== options.length) {
         | 
| 10343 11028 | 
             
                    errors.add(key, this.format(key, 'wrong_length', {
         | 
| 10344 11029 | 
             
                      count: options.length
         | 
| 10345 | 
            -
                    }));
         | 
| 11030 | 
            +
                    }, record));
         | 
| 10346 11031 | 
             
                  }
         | 
| 10347 11032 | 
             
                  return callback();
         | 
| 10348 11033 | 
             
                };
         | 
| @@ -10364,14 +11049,18 @@ | |
| 10364 11049 |  | 
| 10365 11050 | 
             
                InclusionValidator.triggers('inclusion');
         | 
| 10366 11051 |  | 
| 11052 | 
            +
                InclusionValidator.options('allowBlank');
         | 
| 11053 | 
            +
             | 
| 10367 11054 | 
             
                function InclusionValidator(options) {
         | 
| 10368 11055 | 
             
                  this.acceptableValues = options.inclusion["in"];
         | 
| 10369 11056 | 
             
                  InclusionValidator.__super__.constructor.apply(this, arguments);
         | 
| 10370 11057 | 
             
                }
         | 
| 10371 11058 |  | 
| 10372 11059 | 
             
                InclusionValidator.prototype.validateEach = function(errors, record, key, callback) {
         | 
| 10373 | 
            -
                   | 
| 10374 | 
            -
             | 
| 11060 | 
            +
                  var value;
         | 
| 11061 | 
            +
                  value = record.get(key);
         | 
| 11062 | 
            +
                  if (!this.handleBlank(value) && this.acceptableValues.indexOf(value) === -1) {
         | 
| 11063 | 
            +
                    errors.add(key, this.format(key, 'not_included_in_list', {}, record));
         | 
| 10375 11064 | 
             
                  }
         | 
| 10376 11065 | 
             
                  return callback();
         | 
| 10377 11066 | 
             
                };
         | 
| @@ -10400,7 +11089,7 @@ | |
| 10400 11089 |  | 
| 10401 11090 | 
             
                ExclusionValidator.prototype.validateEach = function(errors, record, key, callback) {
         | 
| 10402 11091 | 
             
                  if (this.unacceptableValues.indexOf(record.get(key)) >= 0) {
         | 
| 10403 | 
            -
                    errors.add(key, this.format(key, 'included_in_list'));
         | 
| 11092 | 
            +
                    errors.add(key, this.format(key, 'included_in_list', {}, record));
         | 
| 10404 11093 | 
             
                  }
         | 
| 10405 11094 | 
             
                  return callback();
         | 
| 10406 11095 | 
             
                };
         | 
| @@ -10413,6 +11102,82 @@ | |
| 10413 11102 |  | 
| 10414 11103 | 
             
            }).call(this);
         | 
| 10415 11104 |  | 
| 11105 | 
            +
            (function() {
         | 
| 11106 | 
            +
              var _ref,
         | 
| 11107 | 
            +
                __hasProp = {}.hasOwnProperty,
         | 
| 11108 | 
            +
                __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
         | 
| 11109 | 
            +
             | 
| 11110 | 
            +
              Batman.EmailValidator = (function(_super) {
         | 
| 11111 | 
            +
                __extends(EmailValidator, _super);
         | 
| 11112 | 
            +
             | 
| 11113 | 
            +
                function EmailValidator() {
         | 
| 11114 | 
            +
                  _ref = EmailValidator.__super__.constructor.apply(this, arguments);
         | 
| 11115 | 
            +
                  return _ref;
         | 
| 11116 | 
            +
                }
         | 
| 11117 | 
            +
             | 
| 11118 | 
            +
                EmailValidator.triggers('email');
         | 
| 11119 | 
            +
             | 
| 11120 | 
            +
                EmailValidator.prototype.emailRegexp = /[a-z0-9!#$%&'*+\/=?^_`{|}~.-]+@[a-z0-9-]+(\.[a-z0-9-]+)*/;
         | 
| 11121 | 
            +
             | 
| 11122 | 
            +
                EmailValidator.prototype.validateEach = function(errors, record, key, callback) {
         | 
| 11123 | 
            +
                  var value;
         | 
| 11124 | 
            +
                  value = record.get(key);
         | 
| 11125 | 
            +
                  if ((value == null) || value === '' || !this.emailRegexp.test(value)) {
         | 
| 11126 | 
            +
                    errors.add(key, this.format(key, 'not_an_email', {}, record));
         | 
| 11127 | 
            +
                  }
         | 
| 11128 | 
            +
                  return callback();
         | 
| 11129 | 
            +
                };
         | 
| 11130 | 
            +
             | 
| 11131 | 
            +
                return EmailValidator;
         | 
| 11132 | 
            +
             | 
| 11133 | 
            +
              })(Batman.Validator);
         | 
| 11134 | 
            +
             | 
| 11135 | 
            +
              Batman.Validators.push(Batman.EmailValidator);
         | 
| 11136 | 
            +
             | 
| 11137 | 
            +
            }).call(this);
         | 
| 11138 | 
            +
             | 
| 11139 | 
            +
            (function() {
         | 
| 11140 | 
            +
              var _ref,
         | 
| 11141 | 
            +
                __hasProp = {}.hasOwnProperty,
         | 
| 11142 | 
            +
                __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
         | 
| 11143 | 
            +
             | 
| 11144 | 
            +
              Batman.ConfirmationValidator = (function(_super) {
         | 
| 11145 | 
            +
                __extends(ConfirmationValidator, _super);
         | 
| 11146 | 
            +
             | 
| 11147 | 
            +
                function ConfirmationValidator() {
         | 
| 11148 | 
            +
                  _ref = ConfirmationValidator.__super__.constructor.apply(this, arguments);
         | 
| 11149 | 
            +
                  return _ref;
         | 
| 11150 | 
            +
                }
         | 
| 11151 | 
            +
             | 
| 11152 | 
            +
                ConfirmationValidator.triggers('confirmation');
         | 
| 11153 | 
            +
             | 
| 11154 | 
            +
                ConfirmationValidator.prototype.validateEach = function(errors, record, key, callback) {
         | 
| 11155 | 
            +
                  var confirmation_key, confirmation_value, options, value;
         | 
| 11156 | 
            +
                  options = this.options;
         | 
| 11157 | 
            +
                  if (!options.confirmation) {
         | 
| 11158 | 
            +
                    return;
         | 
| 11159 | 
            +
                  }
         | 
| 11160 | 
            +
                  if (Batman.typeOf(this.options.confirmation) === "String") {
         | 
| 11161 | 
            +
                    confirmation_key = this.options.confirmation;
         | 
| 11162 | 
            +
                  } else {
         | 
| 11163 | 
            +
                    confirmation_key = key + "_confirmation";
         | 
| 11164 | 
            +
                  }
         | 
| 11165 | 
            +
                  value = record.get(key);
         | 
| 11166 | 
            +
                  confirmation_value = record.get(confirmation_key);
         | 
| 11167 | 
            +
                  if (value !== confirmation_value) {
         | 
| 11168 | 
            +
                    errors.add(key, this.format(key, 'confirmation_does_not_match', {}, record));
         | 
| 11169 | 
            +
                  }
         | 
| 11170 | 
            +
                  return callback();
         | 
| 11171 | 
            +
                };
         | 
| 11172 | 
            +
             | 
| 11173 | 
            +
                return ConfirmationValidator;
         | 
| 11174 | 
            +
             | 
| 11175 | 
            +
              })(Batman.Validator);
         | 
| 11176 | 
            +
             | 
| 11177 | 
            +
              Batman.Validators.push(Batman.ConfirmationValidator);
         | 
| 11178 | 
            +
             | 
| 11179 | 
            +
            }).call(this);
         | 
| 11180 | 
            +
             | 
| 10416 11181 | 
             
            (function() {
         | 
| 10417 11182 | 
             
              var _ref,
         | 
| 10418 11183 | 
             
                __hasProp = {}.hasOwnProperty,
         | 
| @@ -10439,7 +11204,7 @@ | |
| 10439 11204 | 
             
                    count = 1;
         | 
| 10440 11205 | 
             
                    childFinished = function(err, childErrors) {
         | 
| 10441 11206 | 
             
                      if (childErrors.length > 0) {
         | 
| 10442 | 
            -
                        errors.add(key, _this.format(key, 'invalid_association'));
         | 
| 11207 | 
            +
                        errors.add(key, _this.format(key, 'invalid_association', {}, record));
         | 
| 10443 11208 | 
             
                      }
         | 
| 10444 11209 | 
             
                      if (--count === 0) {
         | 
| 10445 11210 | 
             
                        return callback();
         | 
| @@ -10468,6 +11233,63 @@ | |
| 10468 11233 |  | 
| 10469 11234 | 
             
            }).call(this);
         | 
| 10470 11235 |  | 
| 11236 | 
            +
            (function() {
         | 
| 11237 | 
            +
              var _ref,
         | 
| 11238 | 
            +
                __hasProp = {}.hasOwnProperty,
         | 
| 11239 | 
            +
                __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
         | 
| 11240 | 
            +
             | 
| 11241 | 
            +
              Batman.AssociatedFieldValidator = (function(_super) {
         | 
| 11242 | 
            +
                __extends(AssociatedFieldValidator, _super);
         | 
| 11243 | 
            +
             | 
| 11244 | 
            +
                function AssociatedFieldValidator() {
         | 
| 11245 | 
            +
                  _ref = AssociatedFieldValidator.__super__.constructor.apply(this, arguments);
         | 
| 11246 | 
            +
                  return _ref;
         | 
| 11247 | 
            +
                }
         | 
| 11248 | 
            +
             | 
| 11249 | 
            +
                AssociatedFieldValidator.triggers('associatedFields');
         | 
| 11250 | 
            +
             | 
| 11251 | 
            +
                AssociatedFieldValidator.prototype.validateEach = function(errors, record, key, callback) {
         | 
| 11252 | 
            +
                  var childFinished, count, value,
         | 
| 11253 | 
            +
                    _this = this;
         | 
| 11254 | 
            +
                  value = record.get(key);
         | 
| 11255 | 
            +
                  if (value != null) {
         | 
| 11256 | 
            +
                    if (value instanceof Batman.AssociationProxy) {
         | 
| 11257 | 
            +
                      value = typeof value.get === "function" ? value.get('target') : void 0;
         | 
| 11258 | 
            +
                    }
         | 
| 11259 | 
            +
                    count = 1;
         | 
| 11260 | 
            +
                    childFinished = function(err, childErrors) {
         | 
| 11261 | 
            +
                      if (childErrors != null) {
         | 
| 11262 | 
            +
                        childErrors.forEach(function(validationError) {
         | 
| 11263 | 
            +
                          return errors.add(validationError.get('attribute'), validationError.get('message'));
         | 
| 11264 | 
            +
                        });
         | 
| 11265 | 
            +
                      }
         | 
| 11266 | 
            +
                      if (--count === 0) {
         | 
| 11267 | 
            +
                        return callback();
         | 
| 11268 | 
            +
                      }
         | 
| 11269 | 
            +
                    };
         | 
| 11270 | 
            +
                    if ((value != null ? value.forEach : void 0) != null) {
         | 
| 11271 | 
            +
                      value.forEach(function(record) {
         | 
| 11272 | 
            +
                        count += 1;
         | 
| 11273 | 
            +
                        return record.validate(childFinished);
         | 
| 11274 | 
            +
                      });
         | 
| 11275 | 
            +
                    } else if ((value != null ? value.validate : void 0) != null) {
         | 
| 11276 | 
            +
                      count += 1;
         | 
| 11277 | 
            +
                      value.validate(childFinished);
         | 
| 11278 | 
            +
                    }
         | 
| 11279 | 
            +
                    return childFinished(null, []);
         | 
| 11280 | 
            +
                  } else {
         | 
| 11281 | 
            +
                    return callback();
         | 
| 11282 | 
            +
                  }
         | 
| 11283 | 
            +
                };
         | 
| 11284 | 
            +
             | 
| 11285 | 
            +
                return AssociatedFieldValidator;
         | 
| 11286 | 
            +
             | 
| 11287 | 
            +
              })(Batman.Validator);
         | 
| 11288 | 
            +
             | 
| 11289 | 
            +
              Batman.Validators.push(Batman.AssociatedFieldValidator);
         | 
| 11290 | 
            +
             | 
| 11291 | 
            +
            }).call(this);
         | 
| 11292 | 
            +
             | 
| 10471 11293 | 
             
            (function() {
         | 
| 10472 11294 | 
             
              var __hasProp = {}.hasOwnProperty,
         | 
| 10473 11295 | 
             
                __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
         | 
| @@ -10629,6 +11451,14 @@ | |
| 10629 11451 | 
             
                  return this._batman.set('options', keys);
         | 
| 10630 11452 | 
             
                };
         | 
| 10631 11453 |  | 
| 11454 | 
            +
                View.filter = function(key, filter) {
         | 
| 11455 | 
            +
                  var filters;
         | 
| 11456 | 
            +
                  Batman.initializeObject(this.prototype);
         | 
| 11457 | 
            +
                  filters = this.prototype._batman.filters || {};
         | 
| 11458 | 
            +
                  filters[key] = filter;
         | 
| 11459 | 
            +
                  return this.prototype._batman.set('filters', filters);
         | 
| 11460 | 
            +
                };
         | 
| 11461 | 
            +
             | 
| 10632 11462 | 
             
                View.viewForNode = function(node, climbTree) {
         | 
| 10633 11463 | 
             
                  var view;
         | 
| 10634 11464 | 
             
                  if (climbTree == null) {
         | 
| @@ -10702,16 +11532,19 @@ | |
| 10702 11532 | 
             
                };
         | 
| 10703 11533 |  | 
| 10704 11534 | 
             
                View.prototype._addSubview = function(subview) {
         | 
| 10705 | 
            -
                  var subviewController, yieldName, yieldObject;
         | 
| 11535 | 
            +
                  var filters, subviewController, yieldName, yieldObject;
         | 
| 10706 11536 | 
             
                  subviewController = subview.controller;
         | 
| 10707 11537 | 
             
                  subview.removeFromSuperview();
         | 
| 10708 11538 | 
             
                  subview.set('controller', subviewController || this.controller);
         | 
| 10709 11539 | 
             
                  subview.set('superview', this);
         | 
| 10710 | 
            -
                  subview. | 
| 11540 | 
            +
                  subview.fireAndCall('viewDidMoveToSuperview');
         | 
| 10711 11541 | 
             
                  if ((yieldName = subview.contentFor) && !subview.parentNode) {
         | 
| 10712 11542 | 
             
                    yieldObject = Batman.DOM.Yield.withName(yieldName);
         | 
| 10713 11543 | 
             
                    yieldObject.set('contentView', subview);
         | 
| 10714 11544 | 
             
                  }
         | 
| 11545 | 
            +
                  if (filters = this._batman.get('filters')) {
         | 
| 11546 | 
            +
                    subview._batman.set('filters', Batman.mixin({}, filters, subview._batman.get('filters')));
         | 
| 11547 | 
            +
                  }
         | 
| 10715 11548 | 
             
                  this.get('node');
         | 
| 10716 11549 | 
             
                  subview.get('node');
         | 
| 10717 11550 | 
             
                  this.observe('node', subview._nodesChanged);
         | 
| @@ -10725,7 +11558,7 @@ | |
| 10725 11558 | 
             
                  if (!this.superview) {
         | 
| 10726 11559 | 
             
                    return;
         | 
| 10727 11560 | 
             
                  }
         | 
| 10728 | 
            -
                  this. | 
| 11561 | 
            +
                  this.fireAndCall('viewWillRemoveFromSuperview');
         | 
| 10729 11562 | 
             
                  this.forget('node', this._nodesChanged);
         | 
| 10730 11563 | 
             
                  this.forget('parentNode', this._nodesChanged);
         | 
| 10731 11564 | 
             
                  this.superview.forget('node', this._nodesChanged);
         | 
| @@ -10806,10 +11639,7 @@ | |
| 10806 11639 | 
             
                  if (value != null) {
         | 
| 10807 11640 | 
             
                    this.set(eventName, value);
         | 
| 10808 11641 | 
             
                  } else {
         | 
| 10809 | 
            -
                    this. | 
| 10810 | 
            -
                    if (typeof this[eventName] === "function") {
         | 
| 10811 | 
            -
                      this[eventName]();
         | 
| 10812 | 
            -
                    }
         | 
| 11642 | 
            +
                    this.fireAndCall(eventName);
         | 
| 10813 11643 | 
             
                  }
         | 
| 10814 11644 | 
             
                  _ref = this.subviews._storage;
         | 
| 10815 11645 | 
             
                  _results = [];
         | 
| @@ -10874,7 +11704,7 @@ | |
| 10874 11704 | 
             
                      if (node) {
         | 
| 10875 11705 | 
             
                        this.set('node', node);
         | 
| 10876 11706 | 
             
                      }
         | 
| 10877 | 
            -
                      this. | 
| 11707 | 
            +
                      this.fireAndCall('viewDidLoad');
         | 
| 10878 11708 | 
             
                    }
         | 
| 10879 11709 | 
             
                    return this.node;
         | 
| 10880 11710 | 
             
                  },
         | 
| @@ -10910,8 +11740,7 @@ | |
| 10910 11740 | 
             
                  }
         | 
| 10911 11741 | 
             
                  new Batman.BindingParser(this);
         | 
| 10912 11742 | 
             
                  this.set('isBound', true);
         | 
| 10913 | 
            -
                  this. | 
| 10914 | 
            -
                  return typeof this.ready === "function" ? this.ready() : void 0;
         | 
| 11743 | 
            +
                  return this.fireAndCall('ready');
         | 
| 10915 11744 | 
             
                };
         | 
| 10916 11745 |  | 
| 10917 11746 | 
             
                View.prototype.destroyBindings = function() {
         | 
| @@ -10945,11 +11774,14 @@ | |
| 10945 11774 | 
             
                    Batman.developer.warn("Tried to die() a view more than once.");
         | 
| 10946 11775 | 
             
                    return;
         | 
| 10947 11776 | 
             
                  }
         | 
| 10948 | 
            -
                  this. | 
| 11777 | 
            +
                  this.fireAndCall('destroy');
         | 
| 11778 | 
            +
                  this.destroyBindings();
         | 
| 11779 | 
            +
                  this.destroySubviews();
         | 
| 10949 11780 | 
             
                  if (this.node) {
         | 
| 10950 11781 | 
             
                    this.wasInDOM = Batman.DOM.containsNode(this.node);
         | 
| 10951 11782 | 
             
                    Batman.DOM.destroyNode(this.node);
         | 
| 10952 11783 | 
             
                  }
         | 
| 11784 | 
            +
                  this.removeFromSuperview();
         | 
| 10953 11785 | 
             
                  this.forget();
         | 
| 10954 11786 | 
             
                  if ((_ref = this._batman.properties) != null) {
         | 
| 10955 11787 | 
             
                    _ref.forEach(function(key, property) {
         | 
| @@ -10963,9 +11795,6 @@ | |
| 10963 11795 | 
             
                      event.clearHandlers();
         | 
| 10964 11796 | 
             
                    }
         | 
| 10965 11797 | 
             
                  }
         | 
| 10966 | 
            -
                  this.destroyBindings();
         | 
| 10967 | 
            -
                  this.destroySubviews();
         | 
| 10968 | 
            -
                  this.removeFromSuperview();
         | 
| 10969 11798 | 
             
                  this.node = null;
         | 
| 10970 11799 | 
             
                  this.parentNode = null;
         | 
| 10971 11800 | 
             
                  this.subviews = null;
         | 
| @@ -10987,22 +11816,19 @@ | |
| 10987 11816 | 
             
                };
         | 
| 10988 11817 |  | 
| 10989 11818 | 
             
                View.prototype.targetForKeypath = function(keypath, forceTarget) {
         | 
| 10990 | 
            -
                  var controller, lookupNode, nearestNonBackingView,  | 
| 10991 | 
            -
                   | 
| 10992 | 
            -
                  lookupNode = proxiedObject || this;
         | 
| 11819 | 
            +
                  var controller, lookupNode, nearestNonBackingView, target;
         | 
| 11820 | 
            +
                  lookupNode = this;
         | 
| 10993 11821 | 
             
                  while (lookupNode) {
         | 
| 10994 | 
            -
                    if ( | 
| 10995 | 
            -
                      return  | 
| 11822 | 
            +
                    if (target = this._testTargetForKeypath(lookupNode, keypath)) {
         | 
| 11823 | 
            +
                      return target;
         | 
| 10996 11824 | 
             
                    }
         | 
| 10997 11825 | 
             
                    if (forceTarget && !nearestNonBackingView && !lookupNode.isBackingView) {
         | 
| 10998 | 
            -
                      nearestNonBackingView = lookupNode;
         | 
| 11826 | 
            +
                      nearestNonBackingView = Batman.get(lookupNode, 'proxiedObject') || lookupNode;
         | 
| 10999 11827 | 
             
                    }
         | 
| 11000 11828 | 
             
                    if (!controller && lookupNode.isView && lookupNode.controller) {
         | 
| 11001 11829 | 
             
                      controller = lookupNode.controller;
         | 
| 11002 11830 | 
             
                    }
         | 
| 11003 | 
            -
                    if ( | 
| 11004 | 
            -
                      lookupNode = this;
         | 
| 11005 | 
            -
                    } else if (lookupNode.isView && lookupNode.superview) {
         | 
| 11831 | 
            +
                    if (lookupNode.isView && lookupNode.superview) {
         | 
| 11006 11832 | 
             
                      lookupNode = lookupNode.superview;
         | 
| 11007 11833 | 
             
                    } else if (controller) {
         | 
| 11008 11834 | 
             
                      lookupNode = controller;
         | 
| @@ -11022,6 +11848,18 @@ | |
| 11022 11848 | 
             
                  return nearestNonBackingView;
         | 
| 11023 11849 | 
             
                };
         | 
| 11024 11850 |  | 
| 11851 | 
            +
                View.prototype._testTargetForKeypath = function(object, keypath) {
         | 
| 11852 | 
            +
                  var proxiedObject;
         | 
| 11853 | 
            +
                  if (proxiedObject = Batman.get(object, 'proxiedObject')) {
         | 
| 11854 | 
            +
                    if (typeof Batman.get(proxiedObject, keypath) !== 'undefined') {
         | 
| 11855 | 
            +
                      return proxiedObject;
         | 
| 11856 | 
            +
                    }
         | 
| 11857 | 
            +
                  }
         | 
| 11858 | 
            +
                  if (typeof Batman.get(object, keypath) !== 'undefined') {
         | 
| 11859 | 
            +
                    return object;
         | 
| 11860 | 
            +
                  }
         | 
| 11861 | 
            +
                };
         | 
| 11862 | 
            +
             | 
| 11025 11863 | 
             
                View.prototype.lookupKeypath = function(keypath) {
         | 
| 11026 11864 | 
             
                  var base, target;
         | 
| 11027 11865 | 
             
                  base = this.baseForKeypath(keypath);
         | 
| @@ -11041,6 +11879,11 @@ | |
| 11041 11879 | 
             
                  return (_ref = Batman.Property.forBaseAndKey(target, keypath)) != null ? _ref.setValue(value) : void 0;
         | 
| 11042 11880 | 
             
                };
         | 
| 11043 11881 |  | 
| 11882 | 
            +
                View.prototype.fireAndCall = function(key) {
         | 
| 11883 | 
            +
                  this.fire(key);
         | 
| 11884 | 
            +
                  return typeof this[key] === "function" ? this[key]() : void 0;
         | 
| 11885 | 
            +
                };
         | 
| 11886 | 
            +
             | 
| 11044 11887 | 
             
                return View;
         | 
| 11045 11888 |  | 
| 11046 11889 | 
             
              })(Batman.Object);
         | 
| @@ -11247,7 +12090,7 @@ | |
| 11247 12090 | 
             
                };
         | 
| 11248 12091 |  | 
| 11249 12092 | 
             
                AbstractBinding.prototype.parseFilter = function() {
         | 
| 11250 | 
            -
                  var args, e, filter, filterName, filterString, filters, key, keyPath, orig, split;
         | 
| 12093 | 
            +
                  var args, e, filter, filterName, filterString, filters, key, keyPath, orig, split, _ref, _ref1;
         | 
| 11251 12094 | 
             
                  this.filterFunctions = [];
         | 
| 11252 12095 | 
             
                  this.filterArguments = [];
         | 
| 11253 12096 | 
             
                  keyPath = this.keyPath;
         | 
| @@ -11275,7 +12118,7 @@ | |
| 11275 12118 | 
             
                      }
         | 
| 11276 12119 | 
             
                      filterName = filterString.substr(0, split);
         | 
| 11277 12120 | 
             
                      args = filterString.substr(split);
         | 
| 11278 | 
            -
                      if (!(filter = Batman.Filters[filterName])) {
         | 
| 12121 | 
            +
                      if (!(filter = ((_ref = this.view) != null ? (_ref1 = _ref._batman.get('filters')) != null ? _ref1[filterName] : void 0 : void 0) || Batman.Filters[filterName])) {
         | 
| 11279 12122 | 
             
                        return Batman.developer.error("Unrecognized filter '" + filterName + "' in key \"" + this.keyPath + "\"!");
         | 
| 11280 12123 | 
             
                      }
         | 
| 11281 12124 | 
             
                      this.filterFunctions.push(filter);
         | 
| @@ -11433,7 +12276,7 @@ | |
| 11433 12276 | 
             
                    if (_this.isDataChanging) {
         | 
| 11434 12277 | 
             
                      return;
         | 
| 11435 12278 | 
             
                    }
         | 
| 11436 | 
            -
                    return _this.view. | 
| 12279 | 
            +
                    return _this.view.setKeypath(_this.keyPath, value);
         | 
| 11437 12280 | 
             
                  });
         | 
| 11438 12281 | 
             
                }
         | 
| 11439 12282 |  | 
| @@ -11509,16 +12352,16 @@ | |
| 11509 12352 | 
             
                  view = Batman.View.viewForNode(this.node, false);
         | 
| 11510 12353 | 
             
                  if (!!value === !this.invert) {
         | 
| 11511 12354 | 
             
                    if (view != null) {
         | 
| 11512 | 
            -
                      view. | 
| 12355 | 
            +
                      view.fireAndCall('viewWillShow');
         | 
| 11513 12356 | 
             
                    }
         | 
| 11514 12357 | 
             
                    this.node.style.display = this.originalDisplay;
         | 
| 11515 | 
            -
                    return view != null ? view. | 
| 12358 | 
            +
                    return view != null ? view.fireAndCall('viewDidShow') : void 0;
         | 
| 11516 12359 | 
             
                  } else {
         | 
| 11517 12360 | 
             
                    if (view != null) {
         | 
| 11518 | 
            -
                      view. | 
| 12361 | 
            +
                      view.fireAndCall('viewWillHide');
         | 
| 11519 12362 | 
             
                    }
         | 
| 11520 12363 | 
             
                    Batman.DOM.setStyleProperty(this.node, 'display', 'none', 'important');
         | 
| 11521 | 
            -
                    return view != null ? view. | 
| 12364 | 
            +
                    return view != null ? view.fireAndCall('viewDidHide') : void 0;
         | 
| 11522 12365 | 
             
                  }
         | 
| 11523 12366 | 
             
                };
         | 
| 11524 12367 |  | 
| @@ -11692,20 +12535,13 @@ | |
| 11692 12535 | 
             
            }).call(this);
         | 
| 11693 12536 |  | 
| 11694 12537 | 
             
            (function() {
         | 
| 11695 | 
            -
              var  | 
| 11696 | 
            -
                __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
         | 
| 12538 | 
            +
              var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
         | 
| 11697 12539 | 
             
                __hasProp = {}.hasOwnProperty,
         | 
| 11698 12540 | 
             
                __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
         | 
| 11699 12541 |  | 
| 11700 12542 | 
             
              Batman.DOM.RouteBinding = (function(_super) {
         | 
| 11701 12543 | 
             
                __extends(RouteBinding, _super);
         | 
| 11702 12544 |  | 
| 11703 | 
            -
                function RouteBinding() {
         | 
| 11704 | 
            -
                  this.routeClick = __bind(this.routeClick, this);
         | 
| 11705 | 
            -
                  _ref = RouteBinding.__super__.constructor.apply(this, arguments);
         | 
| 11706 | 
            -
                  return _ref;
         | 
| 11707 | 
            -
                }
         | 
| 11708 | 
            -
             | 
| 11709 12545 | 
             
                RouteBinding.prototype.onAnchorTag = false;
         | 
| 11710 12546 |  | 
| 11711 12547 | 
             
                RouteBinding.prototype.onlyObserve = Batman.BindingDefinitionOnlyObserve.Data;
         | 
| @@ -11714,34 +12550,44 @@ | |
| 11714 12550 | 
             
                  return this.view.lookupKeypath('dispatcher') || Batman.App.get('current.dispatcher');
         | 
| 11715 12551 | 
             
                });
         | 
| 11716 12552 |  | 
| 12553 | 
            +
                function RouteBinding() {
         | 
| 12554 | 
            +
                  this.routeClick = __bind(this.routeClick, this);
         | 
| 12555 | 
            +
                  var definition, paramKeypath;
         | 
| 12556 | 
            +
                  RouteBinding.__super__.constructor.apply(this, arguments);
         | 
| 12557 | 
            +
                  if (paramKeypath = this.node.getAttribute('data-route-params')) {
         | 
| 12558 | 
            +
                    definition = new Batman.DOM.ReaderBindingDefinition(this.node, paramKeypath, this.view);
         | 
| 12559 | 
            +
                    this.set('queryParams', new Batman.DOM.RouteParamsBinding(definition, this));
         | 
| 12560 | 
            +
                  }
         | 
| 12561 | 
            +
                }
         | 
| 12562 | 
            +
             | 
| 11717 12563 | 
             
                RouteBinding.prototype.bind = function() {
         | 
| 11718 | 
            -
                  var  | 
| 11719 | 
            -
                  if (( | 
| 12564 | 
            +
                  var _ref;
         | 
| 12565 | 
            +
                  if ((_ref = this.node.nodeName) === 'a' || _ref === 'A') {
         | 
| 11720 12566 | 
             
                    this.onAnchorTag = true;
         | 
| 11721 12567 | 
             
                  }
         | 
| 11722 12568 | 
             
                  RouteBinding.__super__.bind.apply(this, arguments);
         | 
| 11723 12569 | 
             
                  if (this.onAnchorTag && this.node.getAttribute('target')) {
         | 
| 11724 12570 | 
             
                    return;
         | 
| 11725 12571 | 
             
                  }
         | 
| 11726 | 
            -
                  return Batman.DOM.events. | 
| 12572 | 
            +
                  return Batman.DOM.events.primaryInteractionEvent(this.node, this.routeClick);
         | 
| 11727 12573 | 
             
                };
         | 
| 11728 12574 |  | 
| 11729 12575 | 
             
                RouteBinding.prototype.routeClick = function(node, event) {
         | 
| 11730 | 
            -
                  var  | 
| 12576 | 
            +
                  var path;
         | 
| 11731 12577 | 
             
                  if (event.__batmanActionTaken) {
         | 
| 11732 12578 | 
             
                    return;
         | 
| 11733 12579 | 
             
                  }
         | 
| 11734 12580 | 
             
                  event.__batmanActionTaken = true;
         | 
| 11735 | 
            -
                   | 
| 11736 | 
            -
                  if ( | 
| 11737 | 
            -
                    return Batman.redirect( | 
| 12581 | 
            +
                  path = this.generatePath(this.get('filteredValue'), this.get('queryParams.filteredValue'));
         | 
| 12582 | 
            +
                  if (path != null) {
         | 
| 12583 | 
            +
                    return Batman.redirect(path);
         | 
| 11738 12584 | 
             
                  }
         | 
| 11739 12585 | 
             
                };
         | 
| 11740 12586 |  | 
| 11741 | 
            -
                RouteBinding.prototype.dataChange = function(value) {
         | 
| 12587 | 
            +
                RouteBinding.prototype.dataChange = function(value, node, queryParams) {
         | 
| 11742 12588 | 
             
                  var path;
         | 
| 11743 12589 | 
             
                  if (value) {
         | 
| 11744 | 
            -
                    path = this. | 
| 12590 | 
            +
                    path = this.generatePath(value, queryParams || this.get('queryParams.filteredValue'));
         | 
| 11745 12591 | 
             
                  }
         | 
| 11746 12592 | 
             
                  if (this.onAnchorTag) {
         | 
| 11747 12593 | 
             
                    if (path && Batman.navigator) {
         | 
| @@ -11753,21 +12599,46 @@ | |
| 11753 12599 | 
             
                  }
         | 
| 11754 12600 | 
             
                };
         | 
| 11755 12601 |  | 
| 11756 | 
            -
                RouteBinding.prototype. | 
| 11757 | 
            -
                  var  | 
| 11758 | 
            -
                   | 
| 11759 | 
            -
             | 
| 11760 | 
            -
             | 
| 11761 | 
            -
             | 
| 11762 | 
            -
             | 
| 12602 | 
            +
                RouteBinding.prototype.generatePath = function(value, params) {
         | 
| 12603 | 
            +
                  var path, uri, _ref;
         | 
| 12604 | 
            +
                  path = (value != null ? value.isNamedRouteQuery : void 0) ? value.get('path') : (_ref = this.get('dispatcher')) != null ? _ref.pathFromParams(value) : void 0;
         | 
| 12605 | 
            +
                  if (!params || !path) {
         | 
| 12606 | 
            +
                    return path;
         | 
| 12607 | 
            +
                  }
         | 
| 12608 | 
            +
                  if (Batman.typeOf(params) === 'Object') {
         | 
| 12609 | 
            +
                    if (params.toObject != null) {
         | 
| 12610 | 
            +
                      params = params.toObject();
         | 
| 11763 12611 | 
             
                    }
         | 
| 12612 | 
            +
                  } else {
         | 
| 12613 | 
            +
                    params = Batman.URI.paramsFromQuery(params);
         | 
| 11764 12614 | 
             
                  }
         | 
| 12615 | 
            +
                  uri = new Batman.URI(path);
         | 
| 12616 | 
            +
                  uri.queryParams = params;
         | 
| 12617 | 
            +
                  return uri.toString();
         | 
| 11765 12618 | 
             
                };
         | 
| 11766 12619 |  | 
| 11767 12620 | 
             
                return RouteBinding;
         | 
| 11768 12621 |  | 
| 11769 12622 | 
             
              })(Batman.DOM.AbstractBinding);
         | 
| 11770 12623 |  | 
| 12624 | 
            +
              Batman.DOM.RouteParamsBinding = (function(_super) {
         | 
| 12625 | 
            +
                __extends(RouteParamsBinding, _super);
         | 
| 12626 | 
            +
             | 
| 12627 | 
            +
                RouteParamsBinding.prototype.onlyObserve = Batman.BindingDefinitionOnlyObserve.Data;
         | 
| 12628 | 
            +
             | 
| 12629 | 
            +
                function RouteParamsBinding(definition, routeBinding) {
         | 
| 12630 | 
            +
                  this.routeBinding = routeBinding;
         | 
| 12631 | 
            +
                  RouteParamsBinding.__super__.constructor.call(this, definition);
         | 
| 12632 | 
            +
                }
         | 
| 12633 | 
            +
             | 
| 12634 | 
            +
                RouteParamsBinding.prototype.dataChange = function(value) {
         | 
| 12635 | 
            +
                  return this.routeBinding.dataChange(this.routeBinding.get('filteredValue'), this.node, value);
         | 
| 12636 | 
            +
                };
         | 
| 12637 | 
            +
             | 
| 12638 | 
            +
                return RouteParamsBinding;
         | 
| 12639 | 
            +
             | 
| 12640 | 
            +
              })(Batman.DOM.AbstractBinding);
         | 
| 12641 | 
            +
             | 
| 11771 12642 | 
             
            }).call(this);
         | 
| 11772 12643 |  | 
| 11773 12644 | 
             
            (function() {
         | 
| @@ -11846,7 +12717,7 @@ | |
| 11846 12717 | 
             
            }).call(this);
         | 
| 11847 12718 |  | 
| 11848 12719 | 
             
            (function() {
         | 
| 11849 | 
            -
              var _ref, | 
| 12720 | 
            +
              var _ref,
         | 
| 11850 12721 | 
             
                __hasProp = {}.hasOwnProperty,
         | 
| 11851 12722 | 
             
                __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
         | 
| 11852 12723 |  | 
| @@ -11867,20 +12738,21 @@ | |
| 11867 12738 | 
             
              Batman.DOM.DeferredRenderBinding = (function(_super) {
         | 
| 11868 12739 | 
             
                __extends(DeferredRenderBinding, _super);
         | 
| 11869 12740 |  | 
| 11870 | 
            -
                function DeferredRenderBinding() {
         | 
| 11871 | 
            -
                  _ref1 = DeferredRenderBinding.__super__.constructor.apply(this, arguments);
         | 
| 11872 | 
            -
                  return _ref1;
         | 
| 11873 | 
            -
                }
         | 
| 11874 | 
            -
             | 
| 11875 12741 | 
             
                DeferredRenderBinding.prototype.onlyObserve = Batman.BindingDefinitionOnlyObserve.Data;
         | 
| 11876 12742 |  | 
| 11877 12743 | 
             
                DeferredRenderBinding.prototype.backWithView = Batman.DeferredRenderView;
         | 
| 11878 12744 |  | 
| 11879 12745 | 
             
                DeferredRenderBinding.prototype.skipChildren = true;
         | 
| 11880 12746 |  | 
| 12747 | 
            +
                function DeferredRenderBinding(definition) {
         | 
| 12748 | 
            +
                  this.invert = definition.invert;
         | 
| 12749 | 
            +
                  this.attributeName = this.invert ? 'data-deferif' : 'data-renderif';
         | 
| 12750 | 
            +
                  DeferredRenderBinding.__super__.constructor.apply(this, arguments);
         | 
| 12751 | 
            +
                }
         | 
| 12752 | 
            +
             | 
| 11881 12753 | 
             
                DeferredRenderBinding.prototype.dataChange = function(value) {
         | 
| 11882 | 
            -
                  if (value && !this.backingView.isBound) {
         | 
| 11883 | 
            -
                    this.node.removeAttribute( | 
| 12754 | 
            +
                  if (!!value === !this.invert && !this.backingView.isBound) {
         | 
| 12755 | 
            +
                    this.node.removeAttribute(this.attributeName);
         | 
| 11884 12756 | 
             
                    return this.backingView.initializeBindings();
         | 
| 11885 12757 | 
             
                  }
         | 
| 11886 12758 | 
             
                };
         | 
| @@ -11937,22 +12809,79 @@ | |
| 11937 12809 | 
             
              var __hasProp = {}.hasOwnProperty,
         | 
| 11938 12810 | 
             
                __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
         | 
| 11939 12811 |  | 
| 11940 | 
            -
              Batman. | 
| 11941 | 
            -
                 | 
| 12812 | 
            +
              Batman.Tracking = {
         | 
| 12813 | 
            +
                loadTracker: function() {
         | 
| 12814 | 
            +
                  if (Batman.Tracking.tracker) {
         | 
| 12815 | 
            +
                    return Batman.Tracking.tracker;
         | 
| 12816 | 
            +
                  }
         | 
| 12817 | 
            +
                  Batman.Tracking.tracker = Batman.currentApp.EventTracker ? new Batman.currentApp.EventTracker : (Batman.developer.warn("Define " + Batman.currentApp.name + ".EventTracker to use data-track"), {
         | 
| 12818 | 
            +
                    track: function() {}
         | 
| 12819 | 
            +
                  });
         | 
| 12820 | 
            +
                  return Batman.Tracking.tracker;
         | 
| 12821 | 
            +
                },
         | 
| 12822 | 
            +
                trackEvent: function(type, data, node) {
         | 
| 12823 | 
            +
                  return Batman.Tracking.loadTracker().track(type, data, node);
         | 
| 12824 | 
            +
                }
         | 
| 12825 | 
            +
              };
         | 
| 11942 12826 |  | 
| 11943 | 
            -
             | 
| 12827 | 
            +
              Batman.DOM.ClickTrackingBinding = (function(_super) {
         | 
| 12828 | 
            +
                __extends(ClickTrackingBinding, _super);
         | 
| 11944 12829 |  | 
| 11945 | 
            -
                 | 
| 12830 | 
            +
                ClickTrackingBinding.prototype.onlyObserve = Batman.BindingDefinitionOnlyObserve.None;
         | 
| 11946 12831 |  | 
| 11947 | 
            -
                 | 
| 11948 | 
            -
             | 
| 12832 | 
            +
                ClickTrackingBinding.prototype.bindImmediately = false;
         | 
| 12833 | 
            +
             | 
| 12834 | 
            +
                function ClickTrackingBinding() {
         | 
| 12835 | 
            +
                  var callback,
         | 
| 11949 12836 | 
             
                    _this = this;
         | 
| 11950 | 
            -
                   | 
| 12837 | 
            +
                  ClickTrackingBinding.__super__.constructor.apply(this, arguments);
         | 
| 11951 12838 | 
             
                  callback = function() {
         | 
| 11952 | 
            -
                     | 
| 11953 | 
            -
             | 
| 11954 | 
            -
             | 
| 11955 | 
            -
             | 
| 12839 | 
            +
                    return Batman.Tracking.trackEvent('click', _this.get('filteredValue'), _this.node);
         | 
| 12840 | 
            +
                  };
         | 
| 12841 | 
            +
                  Batman.DOM.events.click(this.node, callback, this.view, 'click', false);
         | 
| 12842 | 
            +
                  this.bind();
         | 
| 12843 | 
            +
                }
         | 
| 12844 | 
            +
             | 
| 12845 | 
            +
                return ClickTrackingBinding;
         | 
| 12846 | 
            +
             | 
| 12847 | 
            +
              })(Batman.DOM.AbstractAttributeBinding);
         | 
| 12848 | 
            +
             | 
| 12849 | 
            +
              Batman.DOM.ViewTrackingBinding = (function(_super) {
         | 
| 12850 | 
            +
                __extends(ViewTrackingBinding, _super);
         | 
| 12851 | 
            +
             | 
| 12852 | 
            +
                ViewTrackingBinding.prototype.onlyObserve = Batman.BindingDefinitionOnlyObserve.None;
         | 
| 12853 | 
            +
             | 
| 12854 | 
            +
                function ViewTrackingBinding() {
         | 
| 12855 | 
            +
                  ViewTrackingBinding.__super__.constructor.apply(this, arguments);
         | 
| 12856 | 
            +
                  Batman.Tracking.trackEvent('view', this.get('filteredValue'), this.node);
         | 
| 12857 | 
            +
                }
         | 
| 12858 | 
            +
             | 
| 12859 | 
            +
                return ViewTrackingBinding;
         | 
| 12860 | 
            +
             | 
| 12861 | 
            +
              })(Batman.DOM.AbstractAttributeBinding);
         | 
| 12862 | 
            +
             | 
| 12863 | 
            +
            }).call(this);
         | 
| 12864 | 
            +
             | 
| 12865 | 
            +
            (function() {
         | 
| 12866 | 
            +
              var __hasProp = {}.hasOwnProperty,
         | 
| 12867 | 
            +
                __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
         | 
| 12868 | 
            +
             | 
| 12869 | 
            +
              Batman.DOM.EventBinding = (function(_super) {
         | 
| 12870 | 
            +
                __extends(EventBinding, _super);
         | 
| 12871 | 
            +
             | 
| 12872 | 
            +
                EventBinding.prototype.onlyObserve = Batman.BindingDefinitionOnlyObserve.None;
         | 
| 12873 | 
            +
             | 
| 12874 | 
            +
                EventBinding.prototype.bindImmediately = false;
         | 
| 12875 | 
            +
             | 
| 12876 | 
            +
                function EventBinding() {
         | 
| 12877 | 
            +
                  var attacher, callback,
         | 
| 12878 | 
            +
                    _this = this;
         | 
| 12879 | 
            +
                  EventBinding.__super__.constructor.apply(this, arguments);
         | 
| 12880 | 
            +
                  callback = function() {
         | 
| 12881 | 
            +
                    var func, target;
         | 
| 12882 | 
            +
                    func = _this.get('filteredValue');
         | 
| 12883 | 
            +
                    target = _this.view.targetForKeypath(_this.functionPath || _this.unfilteredKey);
         | 
| 12884 | 
            +
                    if (target && _this.functionPath) {
         | 
| 11956 12885 | 
             
                      target = Batman.get(target, _this.functionPath);
         | 
| 11957 12886 | 
             
                    }
         | 
| 11958 12887 | 
             
                    return func != null ? func.apply(target, arguments) : void 0;
         | 
| @@ -11962,7 +12891,7 @@ | |
| 11962 12891 | 
             
                  } else {
         | 
| 11963 12892 | 
             
                    Batman.DOM.events.other(this.node, this.attributeName, callback, this.view);
         | 
| 11964 12893 | 
             
                  }
         | 
| 11965 | 
            -
                  this. | 
| 12894 | 
            +
                  this.bind();
         | 
| 11966 12895 | 
             
                }
         | 
| 11967 12896 |  | 
| 11968 12897 | 
             
                EventBinding.prototype._unfilteredValue = function(key) {
         | 
| @@ -11999,20 +12928,31 @@ | |
| 11999 12928 |  | 
| 12000 12929 | 
             
                ContextBinding.prototype.bindingName = 'context';
         | 
| 12001 12930 |  | 
| 12002 | 
            -
                function ContextBinding() {
         | 
| 12003 | 
            -
                  var contextAttribute | 
| 12931 | 
            +
                function ContextBinding(definition) {
         | 
| 12932 | 
            +
                  var contextAttribute,
         | 
| 12933 | 
            +
                    _this = this;
         | 
| 12934 | 
            +
                  this.contextKeypath = definition.attr || 'proxiedObject';
         | 
| 12004 12935 | 
             
                  ContextBinding.__super__.constructor.apply(this, arguments);
         | 
| 12005 12936 | 
             
                  contextAttribute = this.attributeName ? "data-" + this.bindingName + "-" + this.attributeName : "data-" + this.bindingName;
         | 
| 12006 12937 | 
             
                  this.node.removeAttribute(contextAttribute);
         | 
| 12007 12938 | 
             
                  this.node.insertBefore(document.createComment("batman-" + contextAttribute + "=\"" + this.keyPath + "\""), this.node.firstChild);
         | 
| 12939 | 
            +
                  this.backingView.observe(this.contextKeypath, this._updateValue = function(value) {
         | 
| 12940 | 
            +
                    if (_this.isDataChanging) {
         | 
| 12941 | 
            +
                      return;
         | 
| 12942 | 
            +
                    }
         | 
| 12943 | 
            +
                    return _this.view.setKeypath(_this.keyPath, value);
         | 
| 12944 | 
            +
                  });
         | 
| 12008 12945 | 
             
                }
         | 
| 12009 12946 |  | 
| 12010 12947 | 
             
                ContextBinding.prototype.dataChange = function(proxiedObject) {
         | 
| 12011 | 
            -
                   | 
| 12948 | 
            +
                  this.isDataChanging = true;
         | 
| 12949 | 
            +
                  this.backingView.set(this.contextKeypath, proxiedObject);
         | 
| 12950 | 
            +
                  return this.isDataChanging = false;
         | 
| 12012 12951 | 
             
                };
         | 
| 12013 12952 |  | 
| 12014 12953 | 
             
                ContextBinding.prototype.die = function() {
         | 
| 12015 | 
            -
                  this.backingView. | 
| 12954 | 
            +
                  this.backingView.forget(this.contextKeypath, this._updateValue);
         | 
| 12955 | 
            +
                  this.backingView.unset(this.contextKeypath);
         | 
| 12016 12956 | 
             
                  return ContextBinding.__super__.die.apply(this, arguments);
         | 
| 12017 12957 | 
             
                };
         | 
| 12018 12958 |  | 
| @@ -12250,6 +13190,22 @@ | |
| 12250 13190 | 
             
                  return _ref;
         | 
| 12251 13191 | 
             
                }
         | 
| 12252 13192 |  | 
| 13193 | 
            +
                AbstractCollectionBinding.prototype.dataChange = function(collection) {
         | 
| 13194 | 
            +
                  var items, _items;
         | 
| 13195 | 
            +
                  if (collection != null) {
         | 
| 13196 | 
            +
                    if (!this.bindCollection(collection)) {
         | 
| 13197 | 
            +
                      items = (collection != null ? collection.forEach : void 0) ? (_items = [], collection.forEach(function(item) {
         | 
| 13198 | 
            +
                        return _items.push(item);
         | 
| 13199 | 
            +
                      }), _items) : Object.keys(collection);
         | 
| 13200 | 
            +
                      this.handleArrayChanged(items);
         | 
| 13201 | 
            +
                    }
         | 
| 13202 | 
            +
                  } else {
         | 
| 13203 | 
            +
                    this.unbindCollection();
         | 
| 13204 | 
            +
                    this.collection = [];
         | 
| 13205 | 
            +
                    this.handleArrayChanged([]);
         | 
| 13206 | 
            +
                  }
         | 
| 13207 | 
            +
                };
         | 
| 13208 | 
            +
             | 
| 12253 13209 | 
             
                AbstractCollectionBinding.prototype.bindCollection = function(newCollection) {
         | 
| 12254 13210 | 
             
                  var _ref1;
         | 
| 12255 13211 | 
             
                  if (newCollection instanceof Batman.Hash) {
         | 
| @@ -12368,6 +13324,9 @@ | |
| 12368 13324 |  | 
| 12369 13325 | 
             
                StyleBinding.prototype.setStyle = function(key, value) {
         | 
| 12370 13326 | 
             
                  key = Batman.helpers.camelize(key.trim(), true);
         | 
| 13327 | 
            +
                  if (key === "") {
         | 
| 13328 | 
            +
                    return false;
         | 
| 13329 | 
            +
                  }
         | 
| 12371 13330 | 
             
                  if (this.oldStyles[key] == null) {
         | 
| 12372 13331 | 
             
                    this.oldStyles[key] = this.node.style[key] || "";
         | 
| 12373 13332 | 
             
                  }
         | 
| @@ -12435,27 +13394,28 @@ | |
| 12435 13394 | 
             
            }).call(this);
         | 
| 12436 13395 |  | 
| 12437 13396 | 
             
            (function() {
         | 
| 12438 | 
            -
              var  | 
| 12439 | 
            -
                __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
         | 
| 13397 | 
            +
              var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
         | 
| 12440 13398 | 
             
                __hasProp = {}.hasOwnProperty,
         | 
| 12441 13399 | 
             
                __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
         | 
| 12442 13400 |  | 
| 12443 13401 | 
             
              Batman.DOM.ClassBinding = (function(_super) {
         | 
| 12444 13402 | 
             
                __extends(ClassBinding, _super);
         | 
| 12445 13403 |  | 
| 13404 | 
            +
                ClassBinding.prototype.onlyObserve = Batman.BindingDefinitionOnlyObserve.Data;
         | 
| 13405 | 
            +
             | 
| 12446 13406 | 
             
                function ClassBinding() {
         | 
| 12447 13407 | 
             
                  this.handleArrayChanged = __bind(this.handleArrayChanged, this);
         | 
| 12448 | 
            -
                   | 
| 12449 | 
            -
                   | 
| 13408 | 
            +
                  this.existingClasses = arguments[0].node.className.split(' ');
         | 
| 13409 | 
            +
                  ClassBinding.__super__.constructor.apply(this, arguments);
         | 
| 12450 13410 | 
             
                }
         | 
| 12451 13411 |  | 
| 12452 | 
            -
                ClassBinding.prototype.onlyObserve = Batman.BindingDefinitionOnlyObserve.Data;
         | 
| 12453 | 
            -
             | 
| 12454 13412 | 
             
                ClassBinding.prototype.dataChange = function(value) {
         | 
| 13413 | 
            +
                  var newClasses;
         | 
| 12455 13414 | 
             
                  if (value != null) {
         | 
| 12456 13415 | 
             
                    this.unbindCollection();
         | 
| 12457 13416 | 
             
                    if (typeof value === 'string') {
         | 
| 12458 | 
            -
                       | 
| 13417 | 
            +
                      newClasses = [value].concat(this.existingClasses);
         | 
| 13418 | 
            +
                      return this.node.className = newClasses.join(' ').trim();
         | 
| 12459 13419 | 
             
                    } else {
         | 
| 12460 13420 | 
             
                      this.bindCollection(value);
         | 
| 12461 13421 | 
             
                      return this.updateFromCollection();
         | 
| @@ -12464,17 +13424,17 @@ | |
| 12464 13424 | 
             
                };
         | 
| 12465 13425 |  | 
| 12466 13426 | 
             
                ClassBinding.prototype.updateFromCollection = function() {
         | 
| 12467 | 
            -
                  var array, k, v;
         | 
| 13427 | 
            +
                  var array, existingClasses, k, newClasses, v;
         | 
| 12468 13428 | 
             
                  if (this.collection) {
         | 
| 12469 13429 | 
             
                    array = this.collection.map ? this.collection.map(function(x) {
         | 
| 12470 13430 | 
             
                      return x;
         | 
| 12471 13431 | 
             
                    }) : (function() {
         | 
| 12472 | 
            -
                      var  | 
| 12473 | 
            -
                       | 
| 13432 | 
            +
                      var _ref, _results;
         | 
| 13433 | 
            +
                      _ref = this.collection;
         | 
| 12474 13434 | 
             
                      _results = [];
         | 
| 12475 | 
            -
                      for (k in  | 
| 12476 | 
            -
                        if (!__hasProp.call( | 
| 12477 | 
            -
                        v =  | 
| 13435 | 
            +
                      for (k in _ref) {
         | 
| 13436 | 
            +
                        if (!__hasProp.call(_ref, k)) continue;
         | 
| 13437 | 
            +
                        v = _ref[k];
         | 
| 12478 13438 | 
             
                        _results.push(k);
         | 
| 12479 13439 | 
             
                      }
         | 
| 12480 13440 | 
             
                      return _results;
         | 
| @@ -12482,7 +13442,11 @@ | |
| 12482 13442 | 
             
                    if (array.toArray != null) {
         | 
| 12483 13443 | 
             
                      array = array.toArray();
         | 
| 12484 13444 | 
             
                    }
         | 
| 12485 | 
            -
                     | 
| 13445 | 
            +
                    existingClasses = this.existingClasses.slice(0);
         | 
| 13446 | 
            +
                    newClasses = array.filter(function(val) {
         | 
| 13447 | 
            +
                      return existingClasses.indexOf(val) === -1;
         | 
| 13448 | 
            +
                    });
         | 
| 13449 | 
            +
                    return this.node.className = existingClasses.concat(newClasses).join(' ').trim();
         | 
| 12486 13450 | 
             
                  }
         | 
| 12487 13451 | 
             
                };
         | 
| 12488 13452 |  | 
| @@ -12523,22 +13487,22 @@ | |
| 12523 13487 | 
             
                  parentNode = this.placeholderNode.parentNode || this.node.parentNode;
         | 
| 12524 13488 | 
             
                  if (!!value === !this.invert) {
         | 
| 12525 13489 | 
             
                    if (view != null) {
         | 
| 12526 | 
            -
                      view. | 
| 13490 | 
            +
                      view.fireAndCall('viewWillShow');
         | 
| 12527 13491 | 
             
                    }
         | 
| 12528 13492 | 
             
                    if (this.node.parentNode == null) {
         | 
| 12529 13493 | 
             
                      parentNode.insertBefore(this.node, this.placeholderNode);
         | 
| 12530 13494 | 
             
                      parentNode.removeChild(this.placeholderNode);
         | 
| 12531 13495 | 
             
                    }
         | 
| 12532 | 
            -
                    return view != null ? view. | 
| 13496 | 
            +
                    return view != null ? view.fireAndCall('viewDidShow') : void 0;
         | 
| 12533 13497 | 
             
                  } else {
         | 
| 12534 13498 | 
             
                    if (view != null) {
         | 
| 12535 | 
            -
                      view. | 
| 13499 | 
            +
                      view.fireAndCall('viewWillHide');
         | 
| 12536 13500 | 
             
                    }
         | 
| 12537 13501 | 
             
                    if (this.node.parentNode != null) {
         | 
| 12538 13502 | 
             
                      parentNode.insertBefore(this.placeholderNode, this.node);
         | 
| 12539 13503 | 
             
                      parentNode.removeChild(this.node);
         | 
| 12540 13504 | 
             
                    }
         | 
| 12541 | 
            -
                    return view != null ? view. | 
| 13505 | 
            +
                    return view != null ? view.fireAndCall('viewDidHide') : void 0;
         | 
| 12542 13506 | 
             
                  }
         | 
| 12543 13507 | 
             
                };
         | 
| 12544 13508 |  | 
| @@ -12747,8 +13711,12 @@ | |
| 12747 13711 | 
             
                  IteratorBinding.__super__.constructor.apply(this, arguments);
         | 
| 12748 13712 | 
             
                  this.backingView.set('attributeName', this.attributeName);
         | 
| 12749 13713 | 
             
                  this.view.prevent('ready');
         | 
| 12750 | 
            -
                  Batman.setImmediate(function() {
         | 
| 13714 | 
            +
                  this._handle = Batman.setImmediate(function() {
         | 
| 12751 13715 | 
             
                    var parentNode;
         | 
| 13716 | 
            +
                    if (_this.backingView.isDead) {
         | 
| 13717 | 
            +
                      Batman.developer.warn("IteratorBinding (data-foreach-" + _this.iteratorName + "='" + _this.keyPath + "') trying to insert dead backing view into DOM (" + _this.view.constructor.name + ")");
         | 
| 13718 | 
            +
                      return;
         | 
| 13719 | 
            +
                    }
         | 
| 12752 13720 | 
             
                    parentNode = _this.prototypeNode.parentNode;
         | 
| 12753 13721 | 
             
                    parentNode.insertBefore(_this.backingView.get('node'), _this.prototypeNode);
         | 
| 12754 13722 | 
             
                    parentNode.removeChild(_this.prototypeNode);
         | 
| @@ -12757,22 +13725,6 @@ | |
| 12757 13725 | 
             
                  });
         | 
| 12758 13726 | 
             
                }
         | 
| 12759 13727 |  | 
| 12760 | 
            -
                IteratorBinding.prototype.dataChange = function(collection) {
         | 
| 12761 | 
            -
                  var items, _items;
         | 
| 12762 | 
            -
                  if (collection != null) {
         | 
| 12763 | 
            -
                    if (!this.bindCollection(collection)) {
         | 
| 12764 | 
            -
                      items = (collection != null ? collection.forEach : void 0) ? (_items = [], collection.forEach(function(item) {
         | 
| 12765 | 
            -
                        return _items.push(item);
         | 
| 12766 | 
            -
                      }), _items) : Object.keys(collection);
         | 
| 12767 | 
            -
                      this.handleArrayChanged(items);
         | 
| 12768 | 
            -
                    }
         | 
| 12769 | 
            -
                  } else {
         | 
| 12770 | 
            -
                    this.unbindCollection();
         | 
| 12771 | 
            -
                    this.collection = [];
         | 
| 12772 | 
            -
                    this.handleArrayChanged([]);
         | 
| 12773 | 
            -
                  }
         | 
| 12774 | 
            -
                };
         | 
| 12775 | 
            -
             | 
| 12776 13728 | 
             
                IteratorBinding.prototype.handleArrayChanged = function(newItems) {
         | 
| 12777 13729 | 
             
                  if (!this.backingView.isDead) {
         | 
| 12778 13730 | 
             
                    this.backingView.destroySubviews();
         | 
| @@ -12806,6 +13758,9 @@ | |
| 12806 13758 | 
             
                };
         | 
| 12807 13759 |  | 
| 12808 13760 | 
             
                IteratorBinding.prototype.die = function() {
         | 
| 13761 | 
            +
                  if (this._handle) {
         | 
| 13762 | 
            +
                    Batman.clearImmediate(this._handle);
         | 
| 13763 | 
            +
                  }
         | 
| 12809 13764 | 
             
                  this.prototypeNode = null;
         | 
| 12810 13765 | 
             
                  return IteratorBinding.__super__.die.apply(this, arguments);
         | 
| 12811 13766 | 
             
                };
         | 
| @@ -13074,6 +14029,24 @@ | |
| 13074 14029 | 
             
                equals: buntUndefined(function(lhs, rhs, binding) {
         | 
| 13075 14030 | 
             
                  return lhs === rhs;
         | 
| 13076 14031 | 
             
                }),
         | 
| 14032 | 
            +
                eq: function(lhs, rhs) {
         | 
| 14033 | 
            +
                  return lhs === rhs;
         | 
| 14034 | 
            +
                },
         | 
| 14035 | 
            +
                neq: function(lhs, rhs) {
         | 
| 14036 | 
            +
                  return lhs !== rhs;
         | 
| 14037 | 
            +
                },
         | 
| 14038 | 
            +
                lt: buntUndefined(function(lhs, rhs) {
         | 
| 14039 | 
            +
                  return lhs < rhs;
         | 
| 14040 | 
            +
                }),
         | 
| 14041 | 
            +
                gt: buntUndefined(function(lhs, rhs) {
         | 
| 14042 | 
            +
                  return lhs > rhs;
         | 
| 14043 | 
            +
                }),
         | 
| 14044 | 
            +
                lteq: buntUndefined(function(lhs, rhs) {
         | 
| 14045 | 
            +
                  return lhs <= rhs;
         | 
| 14046 | 
            +
                }),
         | 
| 14047 | 
            +
                gteq: buntUndefined(function(lhs, rhs) {
         | 
| 14048 | 
            +
                  return lhs >= rhs;
         | 
| 14049 | 
            +
                }),
         | 
| 13077 14050 | 
             
                and: function(lhs, rhs) {
         | 
| 13078 14051 | 
             
                  return lhs && rhs;
         | 
| 13079 14052 | 
             
                },
         | 
| @@ -13083,6 +14056,27 @@ | |
| 13083 14056 | 
             
                not: function(value, binding) {
         | 
| 13084 14057 | 
             
                  return !value;
         | 
| 13085 14058 | 
             
                },
         | 
| 14059 | 
            +
                ceil: function(value) {
         | 
| 14060 | 
            +
                  return Math.ceil(value);
         | 
| 14061 | 
            +
                },
         | 
| 14062 | 
            +
                floor: function(value) {
         | 
| 14063 | 
            +
                  return Math.floor(value);
         | 
| 14064 | 
            +
                },
         | 
| 14065 | 
            +
                round: function(value) {
         | 
| 14066 | 
            +
                  return Math.round(value);
         | 
| 14067 | 
            +
                },
         | 
| 14068 | 
            +
                precision: function(value, p) {
         | 
| 14069 | 
            +
                  return parseFloat(value).toPrecision(p);
         | 
| 14070 | 
            +
                },
         | 
| 14071 | 
            +
                fixed: function(value, f) {
         | 
| 14072 | 
            +
                  return parseFloat(value).toFixed(f);
         | 
| 14073 | 
            +
                },
         | 
| 14074 | 
            +
                delimitNumber: function(value) {
         | 
| 14075 | 
            +
                  value = value.toString();
         | 
| 14076 | 
            +
                  return value.replace(/(^|[^\w.])(\d{4,})/g, function($0, $1, $2) {
         | 
| 14077 | 
            +
                    return $1 + $2.replace(/\d(?=(?:\d\d\d)+(?!\d))/g, "$&,");
         | 
| 14078 | 
            +
                  });
         | 
| 14079 | 
            +
                },
         | 
| 13086 14080 | 
             
                trim: buntUndefined(function(value, binding) {
         | 
| 13087 14081 | 
             
                  return value.trim();
         | 
| 13088 14082 | 
             
                }),
         | 
| @@ -13193,7 +14187,7 @@ | |
| 13193 14187 | 
             
                  values = {};
         | 
| 13194 14188 | 
             
                  for (k in interpolationKeypaths) {
         | 
| 13195 14189 | 
             
                    v = interpolationKeypaths[k];
         | 
| 13196 | 
            -
                    values[k] = this. | 
| 14190 | 
            +
                    values[k] = this.lookupKeypath(v);
         | 
| 13197 14191 | 
             
                    if (values[k] == null) {
         | 
| 13198 14192 | 
             
                      Batman.developer.warn("Warning! Undefined interpolation key " + k + " for interpolation", string);
         | 
| 13199 14193 | 
             
                      values[k] = '';
         | 
| @@ -13207,18 +14201,14 @@ | |
| 13207 14201 | 
             
                  if (!block) {
         | 
| 13208 14202 | 
             
                    return;
         | 
| 13209 14203 | 
             
                  }
         | 
| 13210 | 
            -
                   | 
| 13211 | 
            -
                     | 
| 13212 | 
            -
             | 
| 13213 | 
            -
                     | 
| 13214 | 
            -
                  } | 
| 14204 | 
            +
                  if (typeof block === "function") {
         | 
| 14205 | 
            +
                    return function() {
         | 
| 14206 | 
            +
                      return block.call.apply(block, [this].concat(__slice.call(curryArgs), __slice.call(arguments)));
         | 
| 14207 | 
            +
                    };
         | 
| 14208 | 
            +
                  } else if (typeof block.get === "function") {
         | 
| 14209 | 
            +
                    return block.get.apply(block, curryArgs);
         | 
| 14210 | 
            +
                  }
         | 
| 13215 14211 | 
             
                },
         | 
| 13216 | 
            -
                routeToAction: buntUndefined(function(model, action) {
         | 
| 13217 | 
            -
                  var params;
         | 
| 13218 | 
            -
                  params = Batman.Dispatcher.paramsFromArgument(model);
         | 
| 13219 | 
            -
                  params.action = action;
         | 
| 13220 | 
            -
                  return params;
         | 
| 13221 | 
            -
                }),
         | 
| 13222 14212 | 
             
                escape: buntUndefined(Batman.escapeHTML)
         | 
| 13223 14213 | 
             
              };
         | 
| 13224 14214 |  | 
| @@ -13240,4 +14230,1455 @@ | |
| 13240 14230 | 
             
            (function() {
         | 
| 13241 14231 |  | 
| 13242 14232 |  | 
| 14233 | 
            +
            }).call(this);
         | 
| 14234 | 
            +
             | 
| 14235 | 
            +
            /**
         | 
| 14236 | 
            +
             * Zest (https://github.com/chjj/zest)
         | 
| 14237 | 
            +
             * A css selector engine.
         | 
| 14238 | 
            +
             * Copyright (c) 2011-2012, Christopher Jeffrey. (MIT Licensed)
         | 
| 14239 | 
            +
             */
         | 
| 14240 | 
            +
             | 
| 14241 | 
            +
            // TODO
         | 
| 14242 | 
            +
            // - Recognize the TR subject selector when parsing.
         | 
| 14243 | 
            +
            // - Pass context to scope.
         | 
| 14244 | 
            +
            // - Add :column pseudo-classes.
         | 
| 14245 | 
            +
             | 
| 14246 | 
            +
            ;(function() {
         | 
| 14247 | 
            +
             | 
| 14248 | 
            +
            /**
         | 
| 14249 | 
            +
             * Shared
         | 
| 14250 | 
            +
             */
         | 
| 14251 | 
            +
             | 
| 14252 | 
            +
            var window = this
         | 
| 14253 | 
            +
              , document = this.document
         | 
| 14254 | 
            +
              , old = this.zest;
         | 
| 14255 | 
            +
             | 
| 14256 | 
            +
            /**
         | 
| 14257 | 
            +
             * Helpers
         | 
| 14258 | 
            +
             */
         | 
| 14259 | 
            +
             | 
| 14260 | 
            +
            var compareDocumentPosition = (function() {
         | 
| 14261 | 
            +
              if (document.compareDocumentPosition) {
         | 
| 14262 | 
            +
                return function(a, b) {
         | 
| 14263 | 
            +
                  return a.compareDocumentPosition(b);
         | 
| 14264 | 
            +
                };
         | 
| 14265 | 
            +
              }
         | 
| 14266 | 
            +
              return function(a, b) {
         | 
| 14267 | 
            +
                var el = a.ownerDocument.getElementsByTagName('*')
         | 
| 14268 | 
            +
                  , i = el.length;
         | 
| 14269 | 
            +
             | 
| 14270 | 
            +
                while (i--) {
         | 
| 14271 | 
            +
                  if (el[i] === a) return 2;
         | 
| 14272 | 
            +
                  if (el[i] === b) return 4;
         | 
| 14273 | 
            +
                }
         | 
| 14274 | 
            +
             | 
| 14275 | 
            +
                return 1;
         | 
| 14276 | 
            +
              };
         | 
| 14277 | 
            +
            })();
         | 
| 14278 | 
            +
             | 
| 14279 | 
            +
            var order = function(a, b) {
         | 
| 14280 | 
            +
              return compareDocumentPosition(a, b) & 2 ? 1 : -1;
         | 
| 14281 | 
            +
            };
         | 
| 14282 | 
            +
             | 
| 14283 | 
            +
            var next = function(el) {
         | 
| 14284 | 
            +
              while ((el = el.nextSibling)
         | 
| 14285 | 
            +
                     && el.nodeType !== 1);
         | 
| 14286 | 
            +
              return el;
         | 
| 14287 | 
            +
            };
         | 
| 14288 | 
            +
             | 
| 14289 | 
            +
            var prev = function(el) {
         | 
| 14290 | 
            +
              while ((el = el.previousSibling)
         | 
| 14291 | 
            +
                     && el.nodeType !== 1);
         | 
| 14292 | 
            +
              return el;
         | 
| 14293 | 
            +
            };
         | 
| 14294 | 
            +
             | 
| 14295 | 
            +
            var child = function(el) {
         | 
| 14296 | 
            +
              if (el = el.firstChild) {
         | 
| 14297 | 
            +
                while (el.nodeType !== 1
         | 
| 14298 | 
            +
                       && (el = el.nextSibling));
         | 
| 14299 | 
            +
              }
         | 
| 14300 | 
            +
              return el;
         | 
| 14301 | 
            +
            };
         | 
| 14302 | 
            +
             | 
| 14303 | 
            +
            var lastChild = function(el) {
         | 
| 14304 | 
            +
              if (el = el.lastChild) {
         | 
| 14305 | 
            +
                while (el.nodeType !== 1
         | 
| 14306 | 
            +
                       && (el = el.previousSibling));
         | 
| 14307 | 
            +
              }
         | 
| 14308 | 
            +
              return el;
         | 
| 14309 | 
            +
            };
         | 
| 14310 | 
            +
             | 
| 14311 | 
            +
            var unquote = function(str) {
         | 
| 14312 | 
            +
              if (!str) return str;
         | 
| 14313 | 
            +
              var ch = str[0];
         | 
| 14314 | 
            +
              return ch === '"' || ch === '\''
         | 
| 14315 | 
            +
                ? str.slice(1, -1)
         | 
| 14316 | 
            +
                : str;
         | 
| 14317 | 
            +
            };
         | 
| 14318 | 
            +
             | 
| 14319 | 
            +
            var indexOf = (function() {
         | 
| 14320 | 
            +
              if (Array.prototype.indexOf) {
         | 
| 14321 | 
            +
                return Array.prototype.indexOf;
         | 
| 14322 | 
            +
              }
         | 
| 14323 | 
            +
              return function(obj, item) {
         | 
| 14324 | 
            +
                var i = this.length;
         | 
| 14325 | 
            +
                while (i--) {
         | 
| 14326 | 
            +
                  if (this[i] === item) return i;
         | 
| 14327 | 
            +
                }
         | 
| 14328 | 
            +
                return -1;
         | 
| 14329 | 
            +
              };
         | 
| 14330 | 
            +
            })();
         | 
| 14331 | 
            +
             | 
| 14332 | 
            +
            var makeInside = function(start, end) {
         | 
| 14333 | 
            +
              var regex = rules.inside.source
         | 
| 14334 | 
            +
                .replace(/</g, start)
         | 
| 14335 | 
            +
                .replace(/>/g, end);
         | 
| 14336 | 
            +
             | 
| 14337 | 
            +
              return new RegExp(regex);
         | 
| 14338 | 
            +
            };
         | 
| 14339 | 
            +
             | 
| 14340 | 
            +
            var replace = function(regex, name, val) {
         | 
| 14341 | 
            +
              regex = regex.source;
         | 
| 14342 | 
            +
              regex = regex.replace(name, val.source || val);
         | 
| 14343 | 
            +
              return new RegExp(regex);
         | 
| 14344 | 
            +
            };
         | 
| 14345 | 
            +
             | 
| 14346 | 
            +
            var truncateUrl = function(url, num) {
         | 
| 14347 | 
            +
              return url
         | 
| 14348 | 
            +
                .replace(/^(?:\w+:\/\/|\/+)/, '')
         | 
| 14349 | 
            +
                .replace(/(?:\/+|\/*#.*?)$/, '')
         | 
| 14350 | 
            +
                .split('/', num)
         | 
| 14351 | 
            +
                .join('/');
         | 
| 14352 | 
            +
            };
         | 
| 14353 | 
            +
             | 
| 14354 | 
            +
            /**
         | 
| 14355 | 
            +
             * Handle `nth` Selectors
         | 
| 14356 | 
            +
             */
         | 
| 14357 | 
            +
             | 
| 14358 | 
            +
            var parseNth = function(param, test) {
         | 
| 14359 | 
            +
              var param = param.replace(/\s+/g, '')
         | 
| 14360 | 
            +
                , cap;
         | 
| 14361 | 
            +
             | 
| 14362 | 
            +
              if (param === 'even') {
         | 
| 14363 | 
            +
                param = '2n+0';
         | 
| 14364 | 
            +
              } else if (param === 'odd') {
         | 
| 14365 | 
            +
                param = '2n+1';
         | 
| 14366 | 
            +
              } else if (!~param.indexOf('n')) {
         | 
| 14367 | 
            +
                param = '0n' + param;
         | 
| 14368 | 
            +
              }
         | 
| 14369 | 
            +
             | 
| 14370 | 
            +
              cap = /^([+-])?(\d+)?n([+-])?(\d+)?$/.exec(param);
         | 
| 14371 | 
            +
             | 
| 14372 | 
            +
              return {
         | 
| 14373 | 
            +
                group: cap[1] === '-'
         | 
| 14374 | 
            +
                  ? -(cap[2] || 1)
         | 
| 14375 | 
            +
                  : +(cap[2] || 1),
         | 
| 14376 | 
            +
                offset: cap[4]
         | 
| 14377 | 
            +
                  ? (cap[3] === '-' ? -cap[4] : +cap[4])
         | 
| 14378 | 
            +
                  : 0
         | 
| 14379 | 
            +
              };
         | 
| 14380 | 
            +
            };
         | 
| 14381 | 
            +
             | 
| 14382 | 
            +
            var nth = function(param, test, last) {
         | 
| 14383 | 
            +
              var param = parseNth(param)
         | 
| 14384 | 
            +
                , group = param.group
         | 
| 14385 | 
            +
                , offset = param.offset
         | 
| 14386 | 
            +
                , find = !last ? child : lastChild
         | 
| 14387 | 
            +
                , advance = !last ? next : prev;
         | 
| 14388 | 
            +
             | 
| 14389 | 
            +
              return function(el) {
         | 
| 14390 | 
            +
                if (el.parentNode.nodeType !== 1) return;
         | 
| 14391 | 
            +
             | 
| 14392 | 
            +
                var rel = find(el.parentNode)
         | 
| 14393 | 
            +
                  , pos = 0;
         | 
| 14394 | 
            +
             | 
| 14395 | 
            +
                while (rel) {
         | 
| 14396 | 
            +
                  if (test(rel, el)) pos++;
         | 
| 14397 | 
            +
                  if (rel === el) {
         | 
| 14398 | 
            +
                    pos -= offset;
         | 
| 14399 | 
            +
                    return group && pos
         | 
| 14400 | 
            +
                      ? !(pos % group) && (pos < 0 === group < 0)
         | 
| 14401 | 
            +
                      : !pos;
         | 
| 14402 | 
            +
                  }
         | 
| 14403 | 
            +
                  rel = advance(rel);
         | 
| 14404 | 
            +
                }
         | 
| 14405 | 
            +
              };
         | 
| 14406 | 
            +
            };
         | 
| 14407 | 
            +
             | 
| 14408 | 
            +
            /**
         | 
| 14409 | 
            +
             * Simple Selectors
         | 
| 14410 | 
            +
             */
         | 
| 14411 | 
            +
             | 
| 14412 | 
            +
            var selectors = {
         | 
| 14413 | 
            +
              '*': (function() {
         | 
| 14414 | 
            +
                if (function() {
         | 
| 14415 | 
            +
                  var el = document.createElement('div');
         | 
| 14416 | 
            +
                  el.appendChild(document.createComment(''));
         | 
| 14417 | 
            +
                  return !!el.getElementsByTagName('*')[0];
         | 
| 14418 | 
            +
                }()) {
         | 
| 14419 | 
            +
                  return function(el) {
         | 
| 14420 | 
            +
                    if (el.nodeType === 1) return true;
         | 
| 14421 | 
            +
                  };
         | 
| 14422 | 
            +
                }
         | 
| 14423 | 
            +
                return function() {
         | 
| 14424 | 
            +
                  return true;
         | 
| 14425 | 
            +
                };
         | 
| 14426 | 
            +
              })(),
         | 
| 14427 | 
            +
              'type': function(type) {
         | 
| 14428 | 
            +
                type = type.toLowerCase();
         | 
| 14429 | 
            +
                return function(el) {
         | 
| 14430 | 
            +
                  return el.nodeName.toLowerCase() === type;
         | 
| 14431 | 
            +
                };
         | 
| 14432 | 
            +
              },
         | 
| 14433 | 
            +
              'attr': function(key, op, val, i) {
         | 
| 14434 | 
            +
                op = operators[op];
         | 
| 14435 | 
            +
                return function(el) {
         | 
| 14436 | 
            +
                  var attr;
         | 
| 14437 | 
            +
                  switch (key) {
         | 
| 14438 | 
            +
                    case 'for':
         | 
| 14439 | 
            +
                      attr = el.htmlFor;
         | 
| 14440 | 
            +
                      break;
         | 
| 14441 | 
            +
                    case 'class':
         | 
| 14442 | 
            +
                      // className is '' when non-existent
         | 
| 14443 | 
            +
                      // getAttribute('class') is null
         | 
| 14444 | 
            +
                      attr = el.className;
         | 
| 14445 | 
            +
                      if (attr === '' && el.getAttribute('class') == null) {
         | 
| 14446 | 
            +
                        attr = null;
         | 
| 14447 | 
            +
                      }
         | 
| 14448 | 
            +
                      break;
         | 
| 14449 | 
            +
                    case 'href':
         | 
| 14450 | 
            +
                      attr = el.getAttribute('href', 2);
         | 
| 14451 | 
            +
                      break;
         | 
| 14452 | 
            +
                    case 'title':
         | 
| 14453 | 
            +
                      // getAttribute('title') can be '' when non-existent sometimes?
         | 
| 14454 | 
            +
                      attr = el.getAttribute('title') || null;
         | 
| 14455 | 
            +
                      break;
         | 
| 14456 | 
            +
                    case 'id':
         | 
| 14457 | 
            +
                      if (el.getAttribute) {
         | 
| 14458 | 
            +
                        attr = el.getAttribute('id');
         | 
| 14459 | 
            +
                        break;
         | 
| 14460 | 
            +
                      }
         | 
| 14461 | 
            +
                    default:
         | 
| 14462 | 
            +
                      attr = el[key] != null
         | 
| 14463 | 
            +
                        ? el[key]
         | 
| 14464 | 
            +
                        : el.getAttribute && el.getAttribute(key);
         | 
| 14465 | 
            +
                      break;
         | 
| 14466 | 
            +
                  }
         | 
| 14467 | 
            +
                  if (attr == null) return;
         | 
| 14468 | 
            +
                  attr = attr + '';
         | 
| 14469 | 
            +
                  if (i) {
         | 
| 14470 | 
            +
                    attr = attr.toLowerCase();
         | 
| 14471 | 
            +
                    val = val.toLowerCase();
         | 
| 14472 | 
            +
                  }
         | 
| 14473 | 
            +
                  return op(attr, val);
         | 
| 14474 | 
            +
                };
         | 
| 14475 | 
            +
              },
         | 
| 14476 | 
            +
              ':first-child': function(el) {
         | 
| 14477 | 
            +
                return !prev(el) && el.parentNode.nodeType === 1;
         | 
| 14478 | 
            +
              },
         | 
| 14479 | 
            +
              ':last-child': function(el) {
         | 
| 14480 | 
            +
                return !next(el) && el.parentNode.nodeType === 1;
         | 
| 14481 | 
            +
              },
         | 
| 14482 | 
            +
              ':only-child': function(el) {
         | 
| 14483 | 
            +
                return !prev(el) && !next(el)
         | 
| 14484 | 
            +
                  && el.parentNode.nodeType === 1;
         | 
| 14485 | 
            +
              },
         | 
| 14486 | 
            +
              ':nth-child': function(param, last) {
         | 
| 14487 | 
            +
                return nth(param, function() {
         | 
| 14488 | 
            +
                  return true;
         | 
| 14489 | 
            +
                }, last);
         | 
| 14490 | 
            +
              },
         | 
| 14491 | 
            +
              ':nth-last-child': function(param) {
         | 
| 14492 | 
            +
                return selectors[':nth-child'](param, true);
         | 
| 14493 | 
            +
              },
         | 
| 14494 | 
            +
              ':root': function(el) {
         | 
| 14495 | 
            +
                return el.ownerDocument.documentElement === el;
         | 
| 14496 | 
            +
              },
         | 
| 14497 | 
            +
              ':empty': function(el) {
         | 
| 14498 | 
            +
                return !el.firstChild;
         | 
| 14499 | 
            +
              },
         | 
| 14500 | 
            +
              ':not': function(sel) {
         | 
| 14501 | 
            +
                var test = compileGroup(sel);
         | 
| 14502 | 
            +
                return function(el) {
         | 
| 14503 | 
            +
                  return !test(el);
         | 
| 14504 | 
            +
                };
         | 
| 14505 | 
            +
              },
         | 
| 14506 | 
            +
              ':first-of-type': function(el) {
         | 
| 14507 | 
            +
                if (el.parentNode.nodeType !== 1) return;
         | 
| 14508 | 
            +
                var type = el.nodeName;
         | 
| 14509 | 
            +
                while (el = prev(el)) {
         | 
| 14510 | 
            +
                  if (el.nodeName === type) return;
         | 
| 14511 | 
            +
                }
         | 
| 14512 | 
            +
                return true;
         | 
| 14513 | 
            +
              },
         | 
| 14514 | 
            +
              ':last-of-type': function(el) {
         | 
| 14515 | 
            +
                if (el.parentNode.nodeType !== 1) return;
         | 
| 14516 | 
            +
                var type = el.nodeName;
         | 
| 14517 | 
            +
                while (el = next(el)) {
         | 
| 14518 | 
            +
                  if (el.nodeName === type) return;
         | 
| 14519 | 
            +
                }
         | 
| 14520 | 
            +
                return true;
         | 
| 14521 | 
            +
              },
         | 
| 14522 | 
            +
              ':only-of-type': function(el) {
         | 
| 14523 | 
            +
                return selectors[':first-of-type'](el)
         | 
| 14524 | 
            +
                    && selectors[':last-of-type'](el);
         | 
| 14525 | 
            +
              },
         | 
| 14526 | 
            +
              ':nth-of-type': function(param, last) {
         | 
| 14527 | 
            +
                return nth(param, function(rel, el) {
         | 
| 14528 | 
            +
                  return rel.nodeName === el.nodeName;
         | 
| 14529 | 
            +
                }, last);
         | 
| 14530 | 
            +
              },
         | 
| 14531 | 
            +
              ':nth-last-of-type': function(param) {
         | 
| 14532 | 
            +
                return selectors[':nth-of-type'](param, true);
         | 
| 14533 | 
            +
              },
         | 
| 14534 | 
            +
              ':checked': function(el) {
         | 
| 14535 | 
            +
                return !!(el.checked || el.selected);
         | 
| 14536 | 
            +
              },
         | 
| 14537 | 
            +
              ':indeterminate': function(el) {
         | 
| 14538 | 
            +
                return !selectors[':checked'](el);
         | 
| 14539 | 
            +
              },
         | 
| 14540 | 
            +
              ':enabled': function(el) {
         | 
| 14541 | 
            +
                return !el.disabled && el.type !== 'hidden';
         | 
| 14542 | 
            +
              },
         | 
| 14543 | 
            +
              ':disabled': function(el) {
         | 
| 14544 | 
            +
                return !!el.disabled;
         | 
| 14545 | 
            +
              },
         | 
| 14546 | 
            +
              ':target': function(el) {
         | 
| 14547 | 
            +
                return el.id === window.location.hash.substring(1);
         | 
| 14548 | 
            +
              },
         | 
| 14549 | 
            +
              ':focus': function(el) {
         | 
| 14550 | 
            +
                return el === el.ownerDocument.activeElement;
         | 
| 14551 | 
            +
              },
         | 
| 14552 | 
            +
              ':matches': function(sel) {
         | 
| 14553 | 
            +
                return compileGroup(sel);
         | 
| 14554 | 
            +
              },
         | 
| 14555 | 
            +
              ':nth-match': function(param, last) {
         | 
| 14556 | 
            +
                var args = param.split(/\s*,\s*/)
         | 
| 14557 | 
            +
                  , arg = args.shift()
         | 
| 14558 | 
            +
                  , test = compileGroup(args.join(','));
         | 
| 14559 | 
            +
             | 
| 14560 | 
            +
                return nth(arg, test, last);
         | 
| 14561 | 
            +
              },
         | 
| 14562 | 
            +
              ':nth-last-match': function(param) {
         | 
| 14563 | 
            +
                return selectors[':nth-match'](param, true);
         | 
| 14564 | 
            +
              },
         | 
| 14565 | 
            +
              ':links-here': function(el) {
         | 
| 14566 | 
            +
                return el + '' === window.location + '';
         | 
| 14567 | 
            +
              },
         | 
| 14568 | 
            +
              ':lang': function(param) {
         | 
| 14569 | 
            +
                return function(el) {
         | 
| 14570 | 
            +
                  while (el) {
         | 
| 14571 | 
            +
                    if (el.lang) return el.lang.indexOf(param) === 0;
         | 
| 14572 | 
            +
                    el = el.parentNode;
         | 
| 14573 | 
            +
                  }
         | 
| 14574 | 
            +
                };
         | 
| 14575 | 
            +
              },
         | 
| 14576 | 
            +
              ':dir': function(param) {
         | 
| 14577 | 
            +
                return function(el) {
         | 
| 14578 | 
            +
                  while (el) {
         | 
| 14579 | 
            +
                    if (el.dir) return el.dir === param;
         | 
| 14580 | 
            +
                    el = el.parentNode;
         | 
| 14581 | 
            +
                  }
         | 
| 14582 | 
            +
                };
         | 
| 14583 | 
            +
              },
         | 
| 14584 | 
            +
              ':scope': function(el, con) {
         | 
| 14585 | 
            +
                var context = con || el.ownerDocument;
         | 
| 14586 | 
            +
                if (context.nodeType === 9) {
         | 
| 14587 | 
            +
                  return el === context.documentElement;
         | 
| 14588 | 
            +
                }
         | 
| 14589 | 
            +
                return el === context;
         | 
| 14590 | 
            +
              },
         | 
| 14591 | 
            +
              ':any-link': function(el) {
         | 
| 14592 | 
            +
                return typeof el.href === 'string';
         | 
| 14593 | 
            +
              },
         | 
| 14594 | 
            +
              ':local-link': function(el) {
         | 
| 14595 | 
            +
                if (el.nodeName) {
         | 
| 14596 | 
            +
                  return el.href && el.host === window.location.host;
         | 
| 14597 | 
            +
                }
         | 
| 14598 | 
            +
                var param = +el + 1;
         | 
| 14599 | 
            +
                return function(el) {
         | 
| 14600 | 
            +
                  if (!el.href) return;
         | 
| 14601 | 
            +
             | 
| 14602 | 
            +
                  var url = window.location + ''
         | 
| 14603 | 
            +
                    , href = el + '';
         | 
| 14604 | 
            +
             | 
| 14605 | 
            +
                  return truncateUrl(url, param) === truncateUrl(href, param);
         | 
| 14606 | 
            +
                };
         | 
| 14607 | 
            +
              },
         | 
| 14608 | 
            +
              ':default': function(el) {
         | 
| 14609 | 
            +
                return !!el.defaultSelected;
         | 
| 14610 | 
            +
              },
         | 
| 14611 | 
            +
              ':valid': function(el) {
         | 
| 14612 | 
            +
                return el.willValidate || (el.validity && el.validity.valid);
         | 
| 14613 | 
            +
              },
         | 
| 14614 | 
            +
              ':invalid': function(el) {
         | 
| 14615 | 
            +
                return !selectors[':valid'](el);
         | 
| 14616 | 
            +
              },
         | 
| 14617 | 
            +
              ':in-range': function(el) {
         | 
| 14618 | 
            +
                return el.value > el.min && el.value <= el.max;
         | 
| 14619 | 
            +
              },
         | 
| 14620 | 
            +
              ':out-of-range': function(el) {
         | 
| 14621 | 
            +
                return !selectors[':in-range'](el);
         | 
| 14622 | 
            +
              },
         | 
| 14623 | 
            +
              ':required': function(el) {
         | 
| 14624 | 
            +
                return !!el.required;
         | 
| 14625 | 
            +
              },
         | 
| 14626 | 
            +
              ':optional': function(el) {
         | 
| 14627 | 
            +
                return !el.required;
         | 
| 14628 | 
            +
              },
         | 
| 14629 | 
            +
              ':read-only': function(el) {
         | 
| 14630 | 
            +
                if (el.readOnly) return true;
         | 
| 14631 | 
            +
             | 
| 14632 | 
            +
                var attr = el.getAttribute('contenteditable')
         | 
| 14633 | 
            +
                  , prop = el.contentEditable
         | 
| 14634 | 
            +
                  , name = el.nodeName.toLowerCase();
         | 
| 14635 | 
            +
             | 
| 14636 | 
            +
                name = name !== 'input' && name !== 'textarea';
         | 
| 14637 | 
            +
             | 
| 14638 | 
            +
                return (name || el.disabled) && attr == null && prop !== 'true';
         | 
| 14639 | 
            +
              },
         | 
| 14640 | 
            +
              ':read-write': function(el) {
         | 
| 14641 | 
            +
                return !selectors[':read-only'](el);
         | 
| 14642 | 
            +
              },
         | 
| 14643 | 
            +
              ':hover': function() {
         | 
| 14644 | 
            +
                throw new Error(':hover is not supported.');
         | 
| 14645 | 
            +
              },
         | 
| 14646 | 
            +
              ':active': function() {
         | 
| 14647 | 
            +
                throw new Error(':active is not supported.');
         | 
| 14648 | 
            +
              },
         | 
| 14649 | 
            +
              ':link': function() {
         | 
| 14650 | 
            +
                throw new Error(':link is not supported.');
         | 
| 14651 | 
            +
              },
         | 
| 14652 | 
            +
              ':visited': function() {
         | 
| 14653 | 
            +
                throw new Error(':visited is not supported.');
         | 
| 14654 | 
            +
              },
         | 
| 14655 | 
            +
              ':column': function() {
         | 
| 14656 | 
            +
                throw new Error(':column is not supported.');
         | 
| 14657 | 
            +
              },
         | 
| 14658 | 
            +
              ':nth-column': function() {
         | 
| 14659 | 
            +
                throw new Error(':nth-column is not supported.');
         | 
| 14660 | 
            +
              },
         | 
| 14661 | 
            +
              ':nth-last-column': function() {
         | 
| 14662 | 
            +
                throw new Error(':nth-last-column is not supported.');
         | 
| 14663 | 
            +
              },
         | 
| 14664 | 
            +
              ':current': function() {
         | 
| 14665 | 
            +
                throw new Error(':current is not supported.');
         | 
| 14666 | 
            +
              },
         | 
| 14667 | 
            +
              ':past': function() {
         | 
| 14668 | 
            +
                throw new Error(':past is not supported.');
         | 
| 14669 | 
            +
              },
         | 
| 14670 | 
            +
              ':future': function() {
         | 
| 14671 | 
            +
                throw new Error(':future is not supported.');
         | 
| 14672 | 
            +
              },
         | 
| 14673 | 
            +
              // Non-standard, for compatibility purposes.
         | 
| 14674 | 
            +
              ':contains': function(param) {
         | 
| 14675 | 
            +
                return function(el) {
         | 
| 14676 | 
            +
                  var text = el.innerText || el.textContent || el.value || '';
         | 
| 14677 | 
            +
                  return !!~text.indexOf(param);
         | 
| 14678 | 
            +
                };
         | 
| 14679 | 
            +
              },
         | 
| 14680 | 
            +
              ':has': function(param) {
         | 
| 14681 | 
            +
                return function(el) {
         | 
| 14682 | 
            +
                  return zest(param, el).length > 0;
         | 
| 14683 | 
            +
                };
         | 
| 14684 | 
            +
              }
         | 
| 14685 | 
            +
              // Potentially add more pseudo selectors for
         | 
| 14686 | 
            +
              // compatibility with sizzle and most other
         | 
| 14687 | 
            +
              // selector engines (?).
         | 
| 14688 | 
            +
            };
         | 
| 14689 | 
            +
             | 
| 14690 | 
            +
            /**
         | 
| 14691 | 
            +
             * Attribute Operators
         | 
| 14692 | 
            +
             */
         | 
| 14693 | 
            +
             | 
| 14694 | 
            +
            var operators = {
         | 
| 14695 | 
            +
              '-': function() {
         | 
| 14696 | 
            +
                return true;
         | 
| 14697 | 
            +
              },
         | 
| 14698 | 
            +
              '=': function(attr, val) {
         | 
| 14699 | 
            +
                return attr === val;
         | 
| 14700 | 
            +
              },
         | 
| 14701 | 
            +
              '*=': function(attr, val) {
         | 
| 14702 | 
            +
                return attr.indexOf(val) !== -1;
         | 
| 14703 | 
            +
              },
         | 
| 14704 | 
            +
              '~=': function(attr, val) {
         | 
| 14705 | 
            +
                var i = attr.indexOf(val)
         | 
| 14706 | 
            +
                  , f
         | 
| 14707 | 
            +
                  , l;
         | 
| 14708 | 
            +
             | 
| 14709 | 
            +
                if (i === -1) return;
         | 
| 14710 | 
            +
                f = attr[i - 1];
         | 
| 14711 | 
            +
                l = attr[i + val.length];
         | 
| 14712 | 
            +
             | 
| 14713 | 
            +
                return (!f || f === ' ') && (!l || l === ' ');
         | 
| 14714 | 
            +
              },
         | 
| 14715 | 
            +
              '|=': function(attr, val) {
         | 
| 14716 | 
            +
                var i = attr.indexOf(val)
         | 
| 14717 | 
            +
                  , l;
         | 
| 14718 | 
            +
             | 
| 14719 | 
            +
                if (i !== 0) return;
         | 
| 14720 | 
            +
                l = attr[i + val.length];
         | 
| 14721 | 
            +
             | 
| 14722 | 
            +
                return l === '-' || !l;
         | 
| 14723 | 
            +
              },
         | 
| 14724 | 
            +
              '^=': function(attr, val) {
         | 
| 14725 | 
            +
                return attr.indexOf(val) === 0;
         | 
| 14726 | 
            +
              },
         | 
| 14727 | 
            +
              '$=': function(attr, val) {
         | 
| 14728 | 
            +
                return attr.indexOf(val) + val.length === attr.length;
         | 
| 14729 | 
            +
              },
         | 
| 14730 | 
            +
              // non-standard
         | 
| 14731 | 
            +
              '!=': function(attr, val) {
         | 
| 14732 | 
            +
                return attr !== val;
         | 
| 14733 | 
            +
              }
         | 
| 14734 | 
            +
            };
         | 
| 14735 | 
            +
             | 
| 14736 | 
            +
            /**
         | 
| 14737 | 
            +
             * Combinator Logic
         | 
| 14738 | 
            +
             */
         | 
| 14739 | 
            +
             | 
| 14740 | 
            +
            var combinators = {
         | 
| 14741 | 
            +
              ' ': function(test) {
         | 
| 14742 | 
            +
                return function(el) {
         | 
| 14743 | 
            +
                  while (el = el.parentNode) {
         | 
| 14744 | 
            +
                    if (test(el)) return el;
         | 
| 14745 | 
            +
                  }
         | 
| 14746 | 
            +
                };
         | 
| 14747 | 
            +
              },
         | 
| 14748 | 
            +
              '>': function(test) {
         | 
| 14749 | 
            +
                return function(el) {
         | 
| 14750 | 
            +
                  return test(el = el.parentNode) && el;
         | 
| 14751 | 
            +
                };
         | 
| 14752 | 
            +
              },
         | 
| 14753 | 
            +
              '+': function(test) {
         | 
| 14754 | 
            +
                return function(el) {
         | 
| 14755 | 
            +
                  return test(el = prev(el)) && el;
         | 
| 14756 | 
            +
                };
         | 
| 14757 | 
            +
              },
         | 
| 14758 | 
            +
              '~': function(test) {
         | 
| 14759 | 
            +
                return function(el) {
         | 
| 14760 | 
            +
                  while (el = prev(el)) {
         | 
| 14761 | 
            +
                    if (test(el)) return el;
         | 
| 14762 | 
            +
                  }
         | 
| 14763 | 
            +
                };
         | 
| 14764 | 
            +
              },
         | 
| 14765 | 
            +
              'noop': function(test) {
         | 
| 14766 | 
            +
                return function(el) {
         | 
| 14767 | 
            +
                  return test(el) && el;
         | 
| 14768 | 
            +
                };
         | 
| 14769 | 
            +
              },
         | 
| 14770 | 
            +
              'ref': function(test, name) {
         | 
| 14771 | 
            +
                var node;
         | 
| 14772 | 
            +
             | 
| 14773 | 
            +
                function ref(el) {
         | 
| 14774 | 
            +
                  var doc = el.ownerDocument
         | 
| 14775 | 
            +
                    , nodes = doc.getElementsByTagName('*')
         | 
| 14776 | 
            +
                    , i = nodes.length;
         | 
| 14777 | 
            +
             | 
| 14778 | 
            +
                  while (i--) {
         | 
| 14779 | 
            +
                    node = nodes[i];
         | 
| 14780 | 
            +
                    if (ref.test(el)) {
         | 
| 14781 | 
            +
                      node = null;
         | 
| 14782 | 
            +
                      return true;
         | 
| 14783 | 
            +
                    }
         | 
| 14784 | 
            +
                  }
         | 
| 14785 | 
            +
             | 
| 14786 | 
            +
                  node = null;
         | 
| 14787 | 
            +
                }
         | 
| 14788 | 
            +
             | 
| 14789 | 
            +
                ref.combinator = function(el) {
         | 
| 14790 | 
            +
                  if (!node || !node.getAttribute) return;
         | 
| 14791 | 
            +
             | 
| 14792 | 
            +
                  var attr = node.getAttribute(name) || '';
         | 
| 14793 | 
            +
                  if (attr[0] === '#') attr = attr.substring(1);
         | 
| 14794 | 
            +
             | 
| 14795 | 
            +
                  if (attr === el.id && test(node)) {
         | 
| 14796 | 
            +
                    return node;
         | 
| 14797 | 
            +
                  }
         | 
| 14798 | 
            +
                };
         | 
| 14799 | 
            +
             | 
| 14800 | 
            +
                return ref;
         | 
| 14801 | 
            +
              }
         | 
| 14802 | 
            +
            };
         | 
| 14803 | 
            +
             | 
| 14804 | 
            +
            /**
         | 
| 14805 | 
            +
             * Grammar
         | 
| 14806 | 
            +
             */
         | 
| 14807 | 
            +
             | 
| 14808 | 
            +
            var rules = {
         | 
| 14809 | 
            +
              qname: /^ *([\w\-]+|\*)/,
         | 
| 14810 | 
            +
              simple: /^(?:([.#][\w\-]+)|pseudo|attr)/,
         | 
| 14811 | 
            +
              ref: /^ *\/([\w\-]+)\/ */,
         | 
| 14812 | 
            +
              combinator: /^(?: +([^ \w*]) +|( )+|([^ \w*]))(?! *$)/,
         | 
| 14813 | 
            +
              attr: /^\[([\w\-]+)(?:([^\w]?=)(inside))?\]/,
         | 
| 14814 | 
            +
              pseudo: /^(:[\w\-]+)(?:\((inside)\))?/,
         | 
| 14815 | 
            +
              inside: /(?:"(?:\\"|[^"])*"|'(?:\\'|[^'])*'|<[^"'>]*>|\\["'>]|[^"'>])*/
         | 
| 14816 | 
            +
            };
         | 
| 14817 | 
            +
             | 
| 14818 | 
            +
            rules.inside = replace(rules.inside, '[^"\'>]*', rules.inside);
         | 
| 14819 | 
            +
            rules.attr = replace(rules.attr, 'inside', makeInside('\\[', '\\]'));
         | 
| 14820 | 
            +
            rules.pseudo = replace(rules.pseudo, 'inside', makeInside('\\(', '\\)'));
         | 
| 14821 | 
            +
            rules.simple = replace(rules.simple, 'pseudo', rules.pseudo);
         | 
| 14822 | 
            +
            rules.simple = replace(rules.simple, 'attr', rules.attr);
         | 
| 14823 | 
            +
             | 
| 14824 | 
            +
            /**
         | 
| 14825 | 
            +
             * Compiling
         | 
| 14826 | 
            +
             */
         | 
| 14827 | 
            +
             | 
| 14828 | 
            +
            var compile = function(sel) {
         | 
| 14829 | 
            +
              var sel = sel.replace(/^\s+|\s+$/g, '')
         | 
| 14830 | 
            +
                , test
         | 
| 14831 | 
            +
                , filter = []
         | 
| 14832 | 
            +
                , buff = []
         | 
| 14833 | 
            +
                , subject
         | 
| 14834 | 
            +
                , qname
         | 
| 14835 | 
            +
                , cap
         | 
| 14836 | 
            +
                , op
         | 
| 14837 | 
            +
                , ref;
         | 
| 14838 | 
            +
             | 
| 14839 | 
            +
              while (sel) {
         | 
| 14840 | 
            +
                if (cap = rules.qname.exec(sel)) {
         | 
| 14841 | 
            +
                  sel = sel.substring(cap[0].length);
         | 
| 14842 | 
            +
                  qname = cap[1];
         | 
| 14843 | 
            +
                  buff.push(tok(qname, true));
         | 
| 14844 | 
            +
                } else if (cap = rules.simple.exec(sel)) {
         | 
| 14845 | 
            +
                  sel = sel.substring(cap[0].length);
         | 
| 14846 | 
            +
                  qname = '*';
         | 
| 14847 | 
            +
                  buff.push(tok(qname, true));
         | 
| 14848 | 
            +
                  buff.push(tok(cap));
         | 
| 14849 | 
            +
                } else {
         | 
| 14850 | 
            +
                  throw new Error('Invalid selector.');
         | 
| 14851 | 
            +
                }
         | 
| 14852 | 
            +
             | 
| 14853 | 
            +
                while (cap = rules.simple.exec(sel)) {
         | 
| 14854 | 
            +
                  sel = sel.substring(cap[0].length);
         | 
| 14855 | 
            +
                  buff.push(tok(cap));
         | 
| 14856 | 
            +
                }
         | 
| 14857 | 
            +
             | 
| 14858 | 
            +
                if (sel[0] === '!') {
         | 
| 14859 | 
            +
                  sel = sel.substring(1);
         | 
| 14860 | 
            +
                  subject = makeSubject();
         | 
| 14861 | 
            +
                  subject.qname = qname;
         | 
| 14862 | 
            +
                  buff.push(subject.simple);
         | 
| 14863 | 
            +
                }
         | 
| 14864 | 
            +
             | 
| 14865 | 
            +
                if (cap = rules.ref.exec(sel)) {
         | 
| 14866 | 
            +
                  sel = sel.substring(cap[0].length);
         | 
| 14867 | 
            +
                  ref = combinators.ref(makeSimple(buff), cap[1]);
         | 
| 14868 | 
            +
                  filter.push(ref.combinator);
         | 
| 14869 | 
            +
                  buff = [];
         | 
| 14870 | 
            +
                  continue;
         | 
| 14871 | 
            +
                }
         | 
| 14872 | 
            +
             | 
| 14873 | 
            +
                if (cap = rules.combinator.exec(sel)) {
         | 
| 14874 | 
            +
                  sel = sel.substring(cap[0].length);
         | 
| 14875 | 
            +
                  op = cap[1] || cap[2] || cap[3];
         | 
| 14876 | 
            +
                  if (op === ',') {
         | 
| 14877 | 
            +
                    filter.push(combinators.noop(makeSimple(buff)));
         | 
| 14878 | 
            +
                    break;
         | 
| 14879 | 
            +
                  }
         | 
| 14880 | 
            +
                } else {
         | 
| 14881 | 
            +
                  op = 'noop';
         | 
| 14882 | 
            +
                }
         | 
| 14883 | 
            +
             | 
| 14884 | 
            +
                filter.push(combinators[op](makeSimple(buff)));
         | 
| 14885 | 
            +
                buff = [];
         | 
| 14886 | 
            +
              }
         | 
| 14887 | 
            +
             | 
| 14888 | 
            +
              test = makeTest(filter);
         | 
| 14889 | 
            +
              test.qname = qname;
         | 
| 14890 | 
            +
              test.sel = sel;
         | 
| 14891 | 
            +
             | 
| 14892 | 
            +
              if (subject) {
         | 
| 14893 | 
            +
                subject.lname = test.qname;
         | 
| 14894 | 
            +
             | 
| 14895 | 
            +
                subject.test = test;
         | 
| 14896 | 
            +
                subject.qname = subject.qname;
         | 
| 14897 | 
            +
                subject.sel = test.sel;
         | 
| 14898 | 
            +
                test = subject;
         | 
| 14899 | 
            +
              }
         | 
| 14900 | 
            +
             | 
| 14901 | 
            +
              if (ref) {
         | 
| 14902 | 
            +
                ref.test = test;
         | 
| 14903 | 
            +
                ref.qname = test.qname;
         | 
| 14904 | 
            +
                ref.sel = test.sel;
         | 
| 14905 | 
            +
                test = ref;
         | 
| 14906 | 
            +
              }
         | 
| 14907 | 
            +
             | 
| 14908 | 
            +
              return test;
         | 
| 14909 | 
            +
            };
         | 
| 14910 | 
            +
             | 
| 14911 | 
            +
            var tok = function(cap, qname) {
         | 
| 14912 | 
            +
              // qname
         | 
| 14913 | 
            +
              if (qname) {
         | 
| 14914 | 
            +
                return cap === '*'
         | 
| 14915 | 
            +
                  ? selectors['*']
         | 
| 14916 | 
            +
                  : selectors.type(cap);
         | 
| 14917 | 
            +
              }
         | 
| 14918 | 
            +
             | 
| 14919 | 
            +
              // class/id
         | 
| 14920 | 
            +
              if (cap[1]) {
         | 
| 14921 | 
            +
                return cap[1][0] === '.'
         | 
| 14922 | 
            +
                  ? selectors.attr('class', '~=', cap[1].substring(1))
         | 
| 14923 | 
            +
                  : selectors.attr('id', '=', cap[1].substring(1));
         | 
| 14924 | 
            +
              }
         | 
| 14925 | 
            +
             | 
| 14926 | 
            +
              // pseudo-name
         | 
| 14927 | 
            +
              // inside-pseudo
         | 
| 14928 | 
            +
              if (cap[2]) {
         | 
| 14929 | 
            +
                return cap[3]
         | 
| 14930 | 
            +
                  ? selectors[cap[2]](unquote(cap[3]))
         | 
| 14931 | 
            +
                  : selectors[cap[2]];
         | 
| 14932 | 
            +
              }
         | 
| 14933 | 
            +
             | 
| 14934 | 
            +
              // attr name
         | 
| 14935 | 
            +
              // attr op
         | 
| 14936 | 
            +
              // attr value
         | 
| 14937 | 
            +
              if (cap[4]) {
         | 
| 14938 | 
            +
                var i;
         | 
| 14939 | 
            +
                if (cap[6]) {
         | 
| 14940 | 
            +
                  i = cap[6].length;
         | 
| 14941 | 
            +
                  cap[6] = cap[6].replace(/ +i$/, '');
         | 
| 14942 | 
            +
                  i = i > cap[6].length;
         | 
| 14943 | 
            +
                }
         | 
| 14944 | 
            +
                return selectors.attr(cap[4], cap[5] || '-', unquote(cap[6]), i);
         | 
| 14945 | 
            +
              }
         | 
| 14946 | 
            +
             | 
| 14947 | 
            +
              throw new Error('Unknown Selector.');
         | 
| 14948 | 
            +
            };
         | 
| 14949 | 
            +
             | 
| 14950 | 
            +
            var makeSimple = function(func) {
         | 
| 14951 | 
            +
              var l = func.length
         | 
| 14952 | 
            +
                , i;
         | 
| 14953 | 
            +
             | 
| 14954 | 
            +
              // Potentially make sure
         | 
| 14955 | 
            +
              // `el` is truthy.
         | 
| 14956 | 
            +
              if (l < 2) return func[0];
         | 
| 14957 | 
            +
             | 
| 14958 | 
            +
              return function(el) {
         | 
| 14959 | 
            +
                if (!el) return;
         | 
| 14960 | 
            +
                for (i = 0; i < l; i++) {
         | 
| 14961 | 
            +
                  if (!func[i](el)) return;
         | 
| 14962 | 
            +
                }
         | 
| 14963 | 
            +
                return true;
         | 
| 14964 | 
            +
              };
         | 
| 14965 | 
            +
            };
         | 
| 14966 | 
            +
             | 
| 14967 | 
            +
            var makeTest = function(func) {
         | 
| 14968 | 
            +
              if (func.length < 2) {
         | 
| 14969 | 
            +
                return function(el) {
         | 
| 14970 | 
            +
                  return !!func[0](el);
         | 
| 14971 | 
            +
                };
         | 
| 14972 | 
            +
              }
         | 
| 14973 | 
            +
              return function(el) {
         | 
| 14974 | 
            +
                var i = func.length;
         | 
| 14975 | 
            +
                while (i--) {
         | 
| 14976 | 
            +
                  if (!(el = func[i](el))) return;
         | 
| 14977 | 
            +
                }
         | 
| 14978 | 
            +
                return true;
         | 
| 14979 | 
            +
              };
         | 
| 14980 | 
            +
            };
         | 
| 14981 | 
            +
             | 
| 14982 | 
            +
            var makeSubject = function() {
         | 
| 14983 | 
            +
              var target;
         | 
| 14984 | 
            +
             | 
| 14985 | 
            +
              function subject(el) {
         | 
| 14986 | 
            +
                var node = el.ownerDocument
         | 
| 14987 | 
            +
                  , scope = node.getElementsByTagName(subject.lname)
         | 
| 14988 | 
            +
                  , i = scope.length;
         | 
| 14989 | 
            +
             | 
| 14990 | 
            +
                while (i--) {
         | 
| 14991 | 
            +
                  if (subject.test(scope[i]) && target === el) {
         | 
| 14992 | 
            +
                    target = null;
         | 
| 14993 | 
            +
                    return true;
         | 
| 14994 | 
            +
                  }
         | 
| 14995 | 
            +
                }
         | 
| 14996 | 
            +
             | 
| 14997 | 
            +
                target = null;
         | 
| 14998 | 
            +
              }
         | 
| 14999 | 
            +
             | 
| 15000 | 
            +
              subject.simple = function(el) {
         | 
| 15001 | 
            +
                target = el;
         | 
| 15002 | 
            +
                return true;
         | 
| 15003 | 
            +
              };
         | 
| 15004 | 
            +
             | 
| 15005 | 
            +
              return subject;
         | 
| 15006 | 
            +
            };
         | 
| 15007 | 
            +
             | 
| 15008 | 
            +
            var compileGroup = function(sel) {
         | 
| 15009 | 
            +
              var test = compile(sel)
         | 
| 15010 | 
            +
                , tests = [ test ];
         | 
| 15011 | 
            +
             | 
| 15012 | 
            +
              while (test.sel) {
         | 
| 15013 | 
            +
                test = compile(test.sel);
         | 
| 15014 | 
            +
                tests.push(test);
         | 
| 15015 | 
            +
              }
         | 
| 15016 | 
            +
             | 
| 15017 | 
            +
              if (tests.length < 2) return test;
         | 
| 15018 | 
            +
             | 
| 15019 | 
            +
              return function(el) {
         | 
| 15020 | 
            +
                var l = tests.length
         | 
| 15021 | 
            +
                  , i = 0;
         | 
| 15022 | 
            +
             | 
| 15023 | 
            +
                for (; i < l; i++) {
         | 
| 15024 | 
            +
                  if (tests[i](el)) return true;
         | 
| 15025 | 
            +
                }
         | 
| 15026 | 
            +
              };
         | 
| 15027 | 
            +
            };
         | 
| 15028 | 
            +
             | 
| 15029 | 
            +
            /**
         | 
| 15030 | 
            +
             * Selection
         | 
| 15031 | 
            +
             */
         | 
| 15032 | 
            +
             | 
| 15033 | 
            +
            var find = function(sel, node) {
         | 
| 15034 | 
            +
              var results = []
         | 
| 15035 | 
            +
                , test = compile(sel)
         | 
| 15036 | 
            +
                , scope = node.getElementsByTagName(test.qname)
         | 
| 15037 | 
            +
                , i = 0
         | 
| 15038 | 
            +
                , el;
         | 
| 15039 | 
            +
             | 
| 15040 | 
            +
              while (el = scope[i++]) {
         | 
| 15041 | 
            +
                if (test(el)) results.push(el);
         | 
| 15042 | 
            +
              }
         | 
| 15043 | 
            +
             | 
| 15044 | 
            +
              if (test.sel) {
         | 
| 15045 | 
            +
                while (test.sel) {
         | 
| 15046 | 
            +
                  test = compile(test.sel);
         | 
| 15047 | 
            +
                  scope = node.getElementsByTagName(test.qname);
         | 
| 15048 | 
            +
                  i = 0;
         | 
| 15049 | 
            +
                  while (el = scope[i++]) {
         | 
| 15050 | 
            +
                    if (test(el) && !~indexOf.call(results, el)) {
         | 
| 15051 | 
            +
                      results.push(el);
         | 
| 15052 | 
            +
                    }
         | 
| 15053 | 
            +
                  }
         | 
| 15054 | 
            +
                }
         | 
| 15055 | 
            +
                results.sort(order);
         | 
| 15056 | 
            +
              }
         | 
| 15057 | 
            +
             | 
| 15058 | 
            +
              return results;
         | 
| 15059 | 
            +
            };
         | 
| 15060 | 
            +
             | 
| 15061 | 
            +
            /**
         | 
| 15062 | 
            +
             * Native
         | 
| 15063 | 
            +
             */
         | 
| 15064 | 
            +
             | 
| 15065 | 
            +
            var select = (function() {
         | 
| 15066 | 
            +
              var slice = (function() {
         | 
| 15067 | 
            +
                try {
         | 
| 15068 | 
            +
                  Array.prototype.slice.call(document.getElementsByTagName('zest'));
         | 
| 15069 | 
            +
                  return Array.prototype.slice;
         | 
| 15070 | 
            +
                } catch(e) {
         | 
| 15071 | 
            +
                  e = null;
         | 
| 15072 | 
            +
                  return function() {
         | 
| 15073 | 
            +
                    var a = [], i = 0, l = this.length;
         | 
| 15074 | 
            +
                    for (; i < l; i++) a.push(this[i]);
         | 
| 15075 | 
            +
                    return a;
         | 
| 15076 | 
            +
                  };
         | 
| 15077 | 
            +
                }
         | 
| 15078 | 
            +
              })();
         | 
| 15079 | 
            +
             | 
| 15080 | 
            +
              if (document.querySelectorAll) {
         | 
| 15081 | 
            +
                return function(sel, node) {
         | 
| 15082 | 
            +
                  try {
         | 
| 15083 | 
            +
                    return slice.call(node.querySelectorAll(sel));
         | 
| 15084 | 
            +
                  } catch(e) {
         | 
| 15085 | 
            +
                    return find(sel, node);
         | 
| 15086 | 
            +
                  }
         | 
| 15087 | 
            +
                };
         | 
| 15088 | 
            +
              }
         | 
| 15089 | 
            +
             | 
| 15090 | 
            +
              return function(sel, node) {
         | 
| 15091 | 
            +
                try {
         | 
| 15092 | 
            +
                  if (sel[0] === '#' && /^#[\w\-]+$/.test(sel)) {
         | 
| 15093 | 
            +
                    return [node.getElementById(sel.substring(1))];
         | 
| 15094 | 
            +
                  }
         | 
| 15095 | 
            +
                  if (sel[0] === '.' && /^\.[\w\-]+$/.test(sel)) {
         | 
| 15096 | 
            +
                    sel = node.getElementsByClassName(sel.substring(1));
         | 
| 15097 | 
            +
                    return slice.call(sel);
         | 
| 15098 | 
            +
                  }
         | 
| 15099 | 
            +
                  if (/^[\w\-]+$/.test(sel)) {
         | 
| 15100 | 
            +
                    return slice.call(node.getElementsByTagName(sel));
         | 
| 15101 | 
            +
                  }
         | 
| 15102 | 
            +
                } catch(e) {
         | 
| 15103 | 
            +
                  ;
         | 
| 15104 | 
            +
                }
         | 
| 15105 | 
            +
                return find(sel, node);
         | 
| 15106 | 
            +
              };
         | 
| 15107 | 
            +
            })();
         | 
| 15108 | 
            +
             | 
| 15109 | 
            +
            /**
         | 
| 15110 | 
            +
             * Zest
         | 
| 15111 | 
            +
             */
         | 
| 15112 | 
            +
             | 
| 15113 | 
            +
            var zest = function(sel, node) {
         | 
| 15114 | 
            +
              try {
         | 
| 15115 | 
            +
                sel = select(sel, node || document);
         | 
| 15116 | 
            +
              } catch(e) {
         | 
| 15117 | 
            +
                if (window.ZEST_DEBUG) {
         | 
| 15118 | 
            +
                  console.log(e.stack || e + '');
         | 
| 15119 | 
            +
                }
         | 
| 15120 | 
            +
                sel = [];
         | 
| 15121 | 
            +
              }
         | 
| 15122 | 
            +
              return sel;
         | 
| 15123 | 
            +
            };
         | 
| 15124 | 
            +
             | 
| 15125 | 
            +
            /**
         | 
| 15126 | 
            +
             * Expose
         | 
| 15127 | 
            +
             */
         | 
| 15128 | 
            +
             | 
| 15129 | 
            +
            zest.selectors = selectors;
         | 
| 15130 | 
            +
            zest.operators = operators;
         | 
| 15131 | 
            +
            zest.combinators = combinators;
         | 
| 15132 | 
            +
            zest.compile = compileGroup;
         | 
| 15133 | 
            +
             | 
| 15134 | 
            +
            zest.matches = function(el, sel) {
         | 
| 15135 | 
            +
              return !!compileGroup(sel)(el);
         | 
| 15136 | 
            +
            };
         | 
| 15137 | 
            +
             | 
| 15138 | 
            +
            zest.cache = function() {
         | 
| 15139 | 
            +
              if (compile.raw) return;
         | 
| 15140 | 
            +
             | 
| 15141 | 
            +
              var raw = compile
         | 
| 15142 | 
            +
                , cache = {};
         | 
| 15143 | 
            +
             | 
| 15144 | 
            +
              compile = function(sel) {
         | 
| 15145 | 
            +
                return cache[sel]
         | 
| 15146 | 
            +
                  || (cache[sel] = raw(sel));
         | 
| 15147 | 
            +
              };
         | 
| 15148 | 
            +
             | 
| 15149 | 
            +
              compile.raw = raw;
         | 
| 15150 | 
            +
              zest._cache = cache;
         | 
| 15151 | 
            +
            };
         | 
| 15152 | 
            +
             | 
| 15153 | 
            +
            zest.noCache = function() {
         | 
| 15154 | 
            +
              if (!compile.raw) return;
         | 
| 15155 | 
            +
              compile = compile.raw;
         | 
| 15156 | 
            +
              delete zest._cache;
         | 
| 15157 | 
            +
            };
         | 
| 15158 | 
            +
             | 
| 15159 | 
            +
            zest.noConflict = function() {
         | 
| 15160 | 
            +
              window.zest = old;
         | 
| 15161 | 
            +
              return zest;
         | 
| 15162 | 
            +
            };
         | 
| 15163 | 
            +
             | 
| 15164 | 
            +
            zest.noNative = function() {
         | 
| 15165 | 
            +
              select = find;
         | 
| 15166 | 
            +
            };
         | 
| 15167 | 
            +
             | 
| 15168 | 
            +
            if (typeof module !== 'undefined') {
         | 
| 15169 | 
            +
              module.exports = zest;
         | 
| 15170 | 
            +
            } else {
         | 
| 15171 | 
            +
              this.zest = zest;
         | 
| 15172 | 
            +
            }
         | 
| 15173 | 
            +
             | 
| 15174 | 
            +
            if (window.ZEST_DEBUG) {
         | 
| 15175 | 
            +
              zest.noNative();
         | 
| 15176 | 
            +
            } else {
         | 
| 15177 | 
            +
              zest.cache();
         | 
| 15178 | 
            +
            }
         | 
| 15179 | 
            +
             | 
| 15180 | 
            +
            }).call(function() {
         | 
| 15181 | 
            +
              return this || (typeof window !== 'undefined' ? window : global);
         | 
| 15182 | 
            +
            }());
         | 
| 15183 | 
            +
             | 
| 15184 | 
            +
            /*!
         | 
| 15185 | 
            +
              * Reqwest! A general purpose XHR connection manager
         | 
| 15186 | 
            +
              * (c) Dustin Diaz 2011
         | 
| 15187 | 
            +
              * https://github.com/ded/reqwest
         | 
| 15188 | 
            +
              * license MIT
         | 
| 15189 | 
            +
              */
         | 
| 15190 | 
            +
            !function (name, definition) {
         | 
| 15191 | 
            +
              if (typeof module != 'undefined') module.exports = definition()
         | 
| 15192 | 
            +
              else if (typeof define == 'function' && define.amd) define(name, definition)
         | 
| 15193 | 
            +
              else this[name] = definition()
         | 
| 15194 | 
            +
            }('reqwest', function () {
         | 
| 15195 | 
            +
             | 
| 15196 | 
            +
              var context = this
         | 
| 15197 | 
            +
                , win = window
         | 
| 15198 | 
            +
                , doc = document
         | 
| 15199 | 
            +
                , old = context.reqwest
         | 
| 15200 | 
            +
                , twoHundo = /^20\d$/
         | 
| 15201 | 
            +
                , byTag = 'getElementsByTagName'
         | 
| 15202 | 
            +
                , readyState = 'readyState'
         | 
| 15203 | 
            +
                , contentType = 'Content-Type'
         | 
| 15204 | 
            +
                , requestedWith = 'X-Requested-With'
         | 
| 15205 | 
            +
                , head = doc[byTag]('head')[0]
         | 
| 15206 | 
            +
                , uniqid = 0
         | 
| 15207 | 
            +
                , lastValue // data stored by the most recent JSONP callback
         | 
| 15208 | 
            +
                , xmlHttpRequest = 'XMLHttpRequest'
         | 
| 15209 | 
            +
                , isArray = typeof Array.isArray == 'function' ? Array.isArray : function (a) {
         | 
| 15210 | 
            +
                    return a instanceof Array
         | 
| 15211 | 
            +
                  }
         | 
| 15212 | 
            +
                , defaultHeaders = {
         | 
| 15213 | 
            +
                      contentType: 'application/x-www-form-urlencoded'
         | 
| 15214 | 
            +
                    , accept: {
         | 
| 15215 | 
            +
                          '*':  'text/javascript, text/html, application/xml, text/xml, */*'
         | 
| 15216 | 
            +
                        , xml:  'application/xml, text/xml'
         | 
| 15217 | 
            +
                        , html: 'text/html'
         | 
| 15218 | 
            +
                        , text: 'text/plain'
         | 
| 15219 | 
            +
                        , json: 'application/json, text/javascript'
         | 
| 15220 | 
            +
                        , js:   'application/javascript, text/javascript'
         | 
| 15221 | 
            +
                      }
         | 
| 15222 | 
            +
                    , requestedWith: xmlHttpRequest
         | 
| 15223 | 
            +
                  }
         | 
| 15224 | 
            +
                , xhr = win[xmlHttpRequest] ?
         | 
| 15225 | 
            +
                    function () {
         | 
| 15226 | 
            +
                      return new XMLHttpRequest()
         | 
| 15227 | 
            +
                    } :
         | 
| 15228 | 
            +
                    function () {
         | 
| 15229 | 
            +
                      return new ActiveXObject('Microsoft.XMLHTTP')
         | 
| 15230 | 
            +
                    }
         | 
| 15231 | 
            +
             | 
| 15232 | 
            +
              function handleReadyState(o, success, error) {
         | 
| 15233 | 
            +
                return function () {
         | 
| 15234 | 
            +
                  if (o && o[readyState] == 4) {
         | 
| 15235 | 
            +
                    if (twoHundo.test(o.status)) {
         | 
| 15236 | 
            +
                      success(o)
         | 
| 15237 | 
            +
                    } else {
         | 
| 15238 | 
            +
                      error(o)
         | 
| 15239 | 
            +
                    }
         | 
| 15240 | 
            +
                  }
         | 
| 15241 | 
            +
                }
         | 
| 15242 | 
            +
              }
         | 
| 15243 | 
            +
             | 
| 15244 | 
            +
              function setHeaders(http, o) {
         | 
| 15245 | 
            +
                var headers = o.headers || {}, h
         | 
| 15246 | 
            +
                headers.Accept = headers.Accept || defaultHeaders.accept[o.type] || defaultHeaders.accept['*']
         | 
| 15247 | 
            +
                // breaks cross-origin requests with legacy browsers
         | 
| 15248 | 
            +
                if (!o.crossOrigin && !headers[requestedWith]) headers[requestedWith] = defaultHeaders.requestedWith
         | 
| 15249 | 
            +
                if (!headers[contentType]) headers[contentType] = o.contentType || defaultHeaders.contentType
         | 
| 15250 | 
            +
                for (h in headers) {
         | 
| 15251 | 
            +
                  headers.hasOwnProperty(h) && http.setRequestHeader(h, headers[h])
         | 
| 15252 | 
            +
                }
         | 
| 15253 | 
            +
              }
         | 
| 15254 | 
            +
             | 
| 15255 | 
            +
              function generalCallback(data) {
         | 
| 15256 | 
            +
                lastValue = data
         | 
| 15257 | 
            +
              }
         | 
| 15258 | 
            +
             | 
| 15259 | 
            +
              function urlappend(url, s) {
         | 
| 15260 | 
            +
                return url + (/\?/.test(url) ? '&' : '?') + s
         | 
| 15261 | 
            +
              }
         | 
| 15262 | 
            +
             | 
| 15263 | 
            +
              function handleJsonp(o, fn, err, url) {
         | 
| 15264 | 
            +
                var reqId = uniqid++
         | 
| 15265 | 
            +
                  , cbkey = o.jsonpCallback || 'callback' // the 'callback' key
         | 
| 15266 | 
            +
                  , cbval = o.jsonpCallbackName || ('reqwest_' + reqId) // the 'callback' value
         | 
| 15267 | 
            +
                  , cbreg = new RegExp('((^|\\?|&)' + cbkey + ')=([^&]+)')
         | 
| 15268 | 
            +
                  , match = url.match(cbreg)
         | 
| 15269 | 
            +
                  , script = doc.createElement('script')
         | 
| 15270 | 
            +
                  , loaded = 0
         | 
| 15271 | 
            +
             | 
| 15272 | 
            +
                if (match) {
         | 
| 15273 | 
            +
                  if (match[3] === '?') {
         | 
| 15274 | 
            +
                    url = url.replace(cbreg, '$1=' + cbval) // wildcard callback func name
         | 
| 15275 | 
            +
                  } else {
         | 
| 15276 | 
            +
                    cbval = match[3] // provided callback func name
         | 
| 15277 | 
            +
                  }
         | 
| 15278 | 
            +
                } else {
         | 
| 15279 | 
            +
                  url = urlappend(url, cbkey + '=' + cbval) // no callback details, add 'em
         | 
| 15280 | 
            +
                }
         | 
| 15281 | 
            +
             | 
| 15282 | 
            +
                win[cbval] = generalCallback
         | 
| 15283 | 
            +
             | 
| 15284 | 
            +
                script.type = 'text/javascript'
         | 
| 15285 | 
            +
                script.src = url
         | 
| 15286 | 
            +
                script.async = true
         | 
| 15287 | 
            +
                if (typeof script.onreadystatechange !== 'undefined') {
         | 
| 15288 | 
            +
                    // need this for IE due to out-of-order onreadystatechange(), binding script
         | 
| 15289 | 
            +
                    // execution to an event listener gives us control over when the script
         | 
| 15290 | 
            +
                    // is executed. See http://jaubourg.net/2010/07/loading-script-as-onclick-handler-of.html
         | 
| 15291 | 
            +
                    script.event = 'onclick'
         | 
| 15292 | 
            +
                    script.htmlFor = script.id = '_reqwest_' + reqId
         | 
| 15293 | 
            +
                }
         | 
| 15294 | 
            +
             | 
| 15295 | 
            +
                script.onload = script.onreadystatechange = function () {
         | 
| 15296 | 
            +
                  if ((script[readyState] && script[readyState] !== 'complete' && script[readyState] !== 'loaded') || loaded) {
         | 
| 15297 | 
            +
                    return false
         | 
| 15298 | 
            +
                  }
         | 
| 15299 | 
            +
                  script.onload = script.onreadystatechange = null
         | 
| 15300 | 
            +
                  script.onclick && script.onclick()
         | 
| 15301 | 
            +
                  // Call the user callback with the last value stored and clean up values and scripts.
         | 
| 15302 | 
            +
                  o.success && o.success(lastValue)
         | 
| 15303 | 
            +
                  lastValue = undefined
         | 
| 15304 | 
            +
                  head.removeChild(script)
         | 
| 15305 | 
            +
                  loaded = 1
         | 
| 15306 | 
            +
                }
         | 
| 15307 | 
            +
             | 
| 15308 | 
            +
                // Add the script to the DOM head
         | 
| 15309 | 
            +
                head.appendChild(script)
         | 
| 15310 | 
            +
              }
         | 
| 15311 | 
            +
             | 
| 15312 | 
            +
              function getRequest(o, fn, err) {
         | 
| 15313 | 
            +
                var method = (o.method || 'GET').toUpperCase()
         | 
| 15314 | 
            +
                  , url = typeof o === 'string' ? o : o.url
         | 
| 15315 | 
            +
                  // convert non-string objects to query-string form unless o.processData is false
         | 
| 15316 | 
            +
                  , data = (o.processData !== false && o.data && typeof o.data !== 'string')
         | 
| 15317 | 
            +
                    ? reqwest.toQueryString(o.data)
         | 
| 15318 | 
            +
                    : (o.data || null)
         | 
| 15319 | 
            +
                  , http
         | 
| 15320 | 
            +
             | 
| 15321 | 
            +
                // if we're working on a GET request and we have data then we should append
         | 
| 15322 | 
            +
                // query string to end of URL and not post data
         | 
| 15323 | 
            +
                if ((o.type == 'jsonp' || method == 'GET') && data) {
         | 
| 15324 | 
            +
                  url = urlappend(url, data)
         | 
| 15325 | 
            +
                  data = null
         | 
| 15326 | 
            +
                }
         | 
| 15327 | 
            +
             | 
| 15328 | 
            +
                if (o.type == 'jsonp') return handleJsonp(o, fn, err, url)
         | 
| 15329 | 
            +
             | 
| 15330 | 
            +
                http = xhr()
         | 
| 15331 | 
            +
                http.open(method, url, true)
         | 
| 15332 | 
            +
                setHeaders(http, o)
         | 
| 15333 | 
            +
                http.onreadystatechange = handleReadyState(http, fn, err)
         | 
| 15334 | 
            +
                o.before && o.before(http)
         | 
| 15335 | 
            +
                http.send(data)
         | 
| 15336 | 
            +
                return http
         | 
| 15337 | 
            +
              }
         | 
| 15338 | 
            +
             | 
| 15339 | 
            +
              function Reqwest(o, fn) {
         | 
| 15340 | 
            +
                this.o = o
         | 
| 15341 | 
            +
                this.fn = fn
         | 
| 15342 | 
            +
                init.apply(this, arguments)
         | 
| 15343 | 
            +
              }
         | 
| 15344 | 
            +
             | 
| 15345 | 
            +
              function setType(url) {
         | 
| 15346 | 
            +
                var m = url.match(/\.(json|jsonp|html|xml)(\?|$)/)
         | 
| 15347 | 
            +
                return m ? m[1] : 'js'
         | 
| 15348 | 
            +
              }
         | 
| 15349 | 
            +
             | 
| 15350 | 
            +
              function init(o, fn) {
         | 
| 15351 | 
            +
                this.url = typeof o == 'string' ? o : o.url
         | 
| 15352 | 
            +
                this.timeout = null
         | 
| 15353 | 
            +
                var type = o.type || setType(this.url)
         | 
| 15354 | 
            +
                  , self = this
         | 
| 15355 | 
            +
                fn = fn || function () {}
         | 
| 15356 | 
            +
             | 
| 15357 | 
            +
                if (o.timeout) {
         | 
| 15358 | 
            +
                  this.timeout = setTimeout(function () {
         | 
| 15359 | 
            +
                    self.abort()
         | 
| 15360 | 
            +
                  }, o.timeout)
         | 
| 15361 | 
            +
                }
         | 
| 15362 | 
            +
             | 
| 15363 | 
            +
                function complete(resp) {
         | 
| 15364 | 
            +
                  o.timeout && clearTimeout(self.timeout)
         | 
| 15365 | 
            +
                  self.timeout = null
         | 
| 15366 | 
            +
                  o.complete && o.complete(resp)
         | 
| 15367 | 
            +
                }
         | 
| 15368 | 
            +
             | 
| 15369 | 
            +
                function success(resp) {
         | 
| 15370 | 
            +
                  var r = resp.responseText
         | 
| 15371 | 
            +
                  if (r) {
         | 
| 15372 | 
            +
                    switch (type) {
         | 
| 15373 | 
            +
                    case 'json':
         | 
| 15374 | 
            +
                      try {
         | 
| 15375 | 
            +
                        resp = win.JSON ? win.JSON.parse(r) : eval('(' + r + ')')
         | 
| 15376 | 
            +
                      } catch (err) {
         | 
| 15377 | 
            +
                        return error(resp, 'Could not parse JSON in response', err)
         | 
| 15378 | 
            +
                      }
         | 
| 15379 | 
            +
                      break;
         | 
| 15380 | 
            +
                    case 'js':
         | 
| 15381 | 
            +
                      resp = eval(r)
         | 
| 15382 | 
            +
                      break;
         | 
| 15383 | 
            +
                    case 'html':
         | 
| 15384 | 
            +
                      resp = r
         | 
| 15385 | 
            +
                      break;
         | 
| 15386 | 
            +
                    }
         | 
| 15387 | 
            +
                  }
         | 
| 15388 | 
            +
             | 
| 15389 | 
            +
                  fn(resp)
         | 
| 15390 | 
            +
                  o.success && o.success(resp)
         | 
| 15391 | 
            +
             | 
| 15392 | 
            +
                  complete(resp)
         | 
| 15393 | 
            +
                }
         | 
| 15394 | 
            +
             | 
| 15395 | 
            +
                function error(resp, msg, t) {
         | 
| 15396 | 
            +
                  o.error && o.error(resp, msg, t)
         | 
| 15397 | 
            +
                  complete(resp)
         | 
| 15398 | 
            +
                }
         | 
| 15399 | 
            +
             | 
| 15400 | 
            +
                this.request = getRequest(o, success, error)
         | 
| 15401 | 
            +
              }
         | 
| 15402 | 
            +
             | 
| 15403 | 
            +
              Reqwest.prototype = {
         | 
| 15404 | 
            +
                abort: function () {
         | 
| 15405 | 
            +
                  this.request.abort()
         | 
| 15406 | 
            +
                }
         | 
| 15407 | 
            +
             | 
| 15408 | 
            +
              , retry: function () {
         | 
| 15409 | 
            +
                  init.call(this, this.o, this.fn)
         | 
| 15410 | 
            +
                }
         | 
| 15411 | 
            +
              }
         | 
| 15412 | 
            +
             | 
| 15413 | 
            +
              function reqwest(o, fn) {
         | 
| 15414 | 
            +
                return new Reqwest(o, fn)
         | 
| 15415 | 
            +
              }
         | 
| 15416 | 
            +
             | 
| 15417 | 
            +
              // normalize newline variants according to spec -> CRLF
         | 
| 15418 | 
            +
              function normalize(s) {
         | 
| 15419 | 
            +
                return s ? s.replace(/\r?\n/g, '\r\n') : ''
         | 
| 15420 | 
            +
              }
         | 
| 15421 | 
            +
             | 
| 15422 | 
            +
              function serial(el, cb) {
         | 
| 15423 | 
            +
                var n = el.name
         | 
| 15424 | 
            +
                  , t = el.tagName.toLowerCase()
         | 
| 15425 | 
            +
                  , optCb = function(o) {
         | 
| 15426 | 
            +
                      // IE gives value="" even where there is no value attribute
         | 
| 15427 | 
            +
                      // 'specified' ref: http://www.w3.org/TR/DOM-Level-3-Core/core.html#ID-862529273
         | 
| 15428 | 
            +
                      if (o && !o.disabled)
         | 
| 15429 | 
            +
                        cb(n, normalize(o.attributes.value && o.attributes.value.specified ? o.value : o.text))
         | 
| 15430 | 
            +
                    }
         | 
| 15431 | 
            +
             | 
| 15432 | 
            +
                // don't serialize elements that are disabled or without a name
         | 
| 15433 | 
            +
                if (el.disabled || !n) return;
         | 
| 15434 | 
            +
             | 
| 15435 | 
            +
                switch (t) {
         | 
| 15436 | 
            +
                case 'input':
         | 
| 15437 | 
            +
                  if (!/reset|button|image|file/i.test(el.type)) {
         | 
| 15438 | 
            +
                    var ch = /checkbox/i.test(el.type)
         | 
| 15439 | 
            +
                      , ra = /radio/i.test(el.type)
         | 
| 15440 | 
            +
                      , val = el.value;
         | 
| 15441 | 
            +
                    // WebKit gives us "" instead of "on" if a checkbox has no value, so correct it here
         | 
| 15442 | 
            +
                    (!(ch || ra) || el.checked) && cb(n, normalize(ch && val === '' ? 'on' : val))
         | 
| 15443 | 
            +
                  }
         | 
| 15444 | 
            +
                  break;
         | 
| 15445 | 
            +
                case 'textarea':
         | 
| 15446 | 
            +
                  cb(n, normalize(el.value))
         | 
| 15447 | 
            +
                  break;
         | 
| 15448 | 
            +
                case 'select':
         | 
| 15449 | 
            +
                  if (el.type.toLowerCase() === 'select-one') {
         | 
| 15450 | 
            +
                    optCb(el.selectedIndex >= 0 ? el.options[el.selectedIndex] : null)
         | 
| 15451 | 
            +
                  } else {
         | 
| 15452 | 
            +
                    for (var i = 0; el.length && i < el.length; i++) {
         | 
| 15453 | 
            +
                      el.options[i].selected && optCb(el.options[i])
         | 
| 15454 | 
            +
                    }
         | 
| 15455 | 
            +
                  }
         | 
| 15456 | 
            +
                  break;
         | 
| 15457 | 
            +
                }
         | 
| 15458 | 
            +
              }
         | 
| 15459 | 
            +
             | 
| 15460 | 
            +
              // collect up all form elements found from the passed argument elements all
         | 
| 15461 | 
            +
              // the way down to child elements; pass a '<form>' or form fields.
         | 
| 15462 | 
            +
              // called with 'this'=callback to use for serial() on each element
         | 
| 15463 | 
            +
              function eachFormElement() {
         | 
| 15464 | 
            +
                var cb = this
         | 
| 15465 | 
            +
                  , e, i, j
         | 
| 15466 | 
            +
                  , serializeSubtags = function(e, tags) {
         | 
| 15467 | 
            +
                    for (var i = 0; i < tags.length; i++) {
         | 
| 15468 | 
            +
                      var fa = e[byTag](tags[i])
         | 
| 15469 | 
            +
                      for (j = 0; j < fa.length; j++) serial(fa[j], cb)
         | 
| 15470 | 
            +
                    }
         | 
| 15471 | 
            +
                  }
         | 
| 15472 | 
            +
             | 
| 15473 | 
            +
                for (i = 0; i < arguments.length; i++) {
         | 
| 15474 | 
            +
                  e = arguments[i]
         | 
| 15475 | 
            +
                  if (/input|select|textarea/i.test(e.tagName)) serial(e, cb)
         | 
| 15476 | 
            +
                  serializeSubtags(e, [ 'input', 'select', 'textarea' ])
         | 
| 15477 | 
            +
                }
         | 
| 15478 | 
            +
              }
         | 
| 15479 | 
            +
             | 
| 15480 | 
            +
              // standard query string style serialization
         | 
| 15481 | 
            +
              function serializeQueryString() {
         | 
| 15482 | 
            +
                return reqwest.toQueryString(reqwest.serializeArray.apply(null, arguments))
         | 
| 15483 | 
            +
              }
         | 
| 15484 | 
            +
             | 
| 15485 | 
            +
              // { 'name': 'value', ... } style serialization
         | 
| 15486 | 
            +
              function serializeHash() {
         | 
| 15487 | 
            +
                var hash = {}
         | 
| 15488 | 
            +
                eachFormElement.apply(function (name, value) {
         | 
| 15489 | 
            +
                  if (name in hash) {
         | 
| 15490 | 
            +
                    hash[name] && !isArray(hash[name]) && (hash[name] = [hash[name]])
         | 
| 15491 | 
            +
                    hash[name].push(value)
         | 
| 15492 | 
            +
                  } else hash[name] = value
         | 
| 15493 | 
            +
                }, arguments)
         | 
| 15494 | 
            +
                return hash
         | 
| 15495 | 
            +
              }
         | 
| 15496 | 
            +
             | 
| 15497 | 
            +
              // [ { name: 'name', value: 'value' }, ... ] style serialization
         | 
| 15498 | 
            +
              reqwest.serializeArray = function () {
         | 
| 15499 | 
            +
                var arr = []
         | 
| 15500 | 
            +
                eachFormElement.apply(function(name, value) {
         | 
| 15501 | 
            +
                  arr.push({name: name, value: value})
         | 
| 15502 | 
            +
                }, arguments)
         | 
| 15503 | 
            +
                return arr
         | 
| 15504 | 
            +
              }
         | 
| 15505 | 
            +
             | 
| 15506 | 
            +
              reqwest.serialize = function () {
         | 
| 15507 | 
            +
                if (arguments.length === 0) return ''
         | 
| 15508 | 
            +
                var opt, fn
         | 
| 15509 | 
            +
                  , args = Array.prototype.slice.call(arguments, 0)
         | 
| 15510 | 
            +
             | 
| 15511 | 
            +
                opt = args.pop()
         | 
| 15512 | 
            +
                opt && opt.nodeType && args.push(opt) && (opt = null)
         | 
| 15513 | 
            +
                opt && (opt = opt.type)
         | 
| 15514 | 
            +
             | 
| 15515 | 
            +
                if (opt == 'map') fn = serializeHash
         | 
| 15516 | 
            +
                else if (opt == 'array') fn = reqwest.serializeArray
         | 
| 15517 | 
            +
                else fn = serializeQueryString
         | 
| 15518 | 
            +
             | 
| 15519 | 
            +
                return fn.apply(null, args)
         | 
| 15520 | 
            +
              }
         | 
| 15521 | 
            +
             | 
| 15522 | 
            +
              reqwest.toQueryString = function (o) {
         | 
| 15523 | 
            +
                var qs = '', i
         | 
| 15524 | 
            +
                  , enc = encodeURIComponent
         | 
| 15525 | 
            +
                  , push = function (k, v) {
         | 
| 15526 | 
            +
                      qs += enc(k) + '=' + enc(v) + '&'
         | 
| 15527 | 
            +
                    }
         | 
| 15528 | 
            +
             | 
| 15529 | 
            +
                if (isArray(o)) {
         | 
| 15530 | 
            +
                  for (i = 0; o && i < o.length; i++) push(o[i].name, o[i].value)
         | 
| 15531 | 
            +
                } else {
         | 
| 15532 | 
            +
                  for (var k in o) {
         | 
| 15533 | 
            +
                    if (!Object.hasOwnProperty.call(o, k)) continue;
         | 
| 15534 | 
            +
                    var v = o[k]
         | 
| 15535 | 
            +
                    if (isArray(v)) {
         | 
| 15536 | 
            +
                      for (i = 0; i < v.length; i++) push(k, v[i])
         | 
| 15537 | 
            +
                    } else push(k, o[k])
         | 
| 15538 | 
            +
                  }
         | 
| 15539 | 
            +
                }
         | 
| 15540 | 
            +
             | 
| 15541 | 
            +
                // spaces should be + according to spec
         | 
| 15542 | 
            +
                return qs.replace(/&$/, '').replace(/%20/g,'+')
         | 
| 15543 | 
            +
              }
         | 
| 15544 | 
            +
             | 
| 15545 | 
            +
              // jQuery and Zepto compatibility, differences can be remapped here so you can call
         | 
| 15546 | 
            +
              // .ajax.compat(options, callback)
         | 
| 15547 | 
            +
              reqwest.compat = function (o, fn) {
         | 
| 15548 | 
            +
                if (o) {
         | 
| 15549 | 
            +
                  o.type && (o.method = o.type) && delete o.type
         | 
| 15550 | 
            +
                  o.dataType && (o.type = o.dataType)
         | 
| 15551 | 
            +
                  o.jsonpCallback && (o.jsonpCallbackName = o.jsonpCallback) && delete o.jsonpCallback
         | 
| 15552 | 
            +
                  o.jsonp && (o.jsonpCallback = o.jsonp)
         | 
| 15553 | 
            +
                }
         | 
| 15554 | 
            +
                return new Reqwest(o, fn)
         | 
| 15555 | 
            +
              }
         | 
| 15556 | 
            +
             | 
| 15557 | 
            +
              return reqwest
         | 
| 15558 | 
            +
            });
         | 
| 15559 | 
            +
             | 
| 15560 | 
            +
            (function() {
         | 
| 15561 | 
            +
              var SAFARI_CONTAINS_IS_BROKEN, version;
         | 
| 15562 | 
            +
             | 
| 15563 | 
            +
              if (/Safari/.test(navigator.userAgent)) {
         | 
| 15564 | 
            +
                version = /WebKit\/(\S+)/.exec(navigator.userAgent);
         | 
| 15565 | 
            +
                if (version && parseFloat(version) < 540) {
         | 
| 15566 | 
            +
                  SAFARI_CONTAINS_IS_BROKEN = true;
         | 
| 15567 | 
            +
                }
         | 
| 15568 | 
            +
              }
         | 
| 15569 | 
            +
             | 
| 15570 | 
            +
              (typeof window !== "undefined" && window !== null ? window : global).containsNode = function(parent, child) {
         | 
| 15571 | 
            +
                if (parent === child) {
         | 
| 15572 | 
            +
                  return true;
         | 
| 15573 | 
            +
                }
         | 
| 15574 | 
            +
                if (parent.contains && !SAFARI_CONTAINS_IS_BROKEN) {
         | 
| 15575 | 
            +
                  return parent.contains(child);
         | 
| 15576 | 
            +
                }
         | 
| 15577 | 
            +
                if (parent.compareDocumentPosition) {
         | 
| 15578 | 
            +
                  return !!(parent.compareDocumentPosition(child) & 16);
         | 
| 15579 | 
            +
                }
         | 
| 15580 | 
            +
                while (child && parent !== child) {
         | 
| 15581 | 
            +
                  child = child.parentNode;
         | 
| 15582 | 
            +
                }
         | 
| 15583 | 
            +
                return child === parent;
         | 
| 15584 | 
            +
              };
         | 
| 15585 | 
            +
             | 
| 15586 | 
            +
            }).call(this);
         | 
| 15587 | 
            +
             | 
| 15588 | 
            +
            (function() {
         | 
| 15589 | 
            +
              Batman.extend(Batman.DOM, {
         | 
| 15590 | 
            +
                querySelectorAll: function(node, selector) {
         | 
| 15591 | 
            +
                  return zest(selector, node);
         | 
| 15592 | 
            +
                },
         | 
| 15593 | 
            +
                querySelector: function(node, selector) {
         | 
| 15594 | 
            +
                  return zest(selector, node)[0];
         | 
| 15595 | 
            +
                },
         | 
| 15596 | 
            +
                setInnerHTML: function(node, html) {
         | 
| 15597 | 
            +
                  return node != null ? node.innerHTML = html : void 0;
         | 
| 15598 | 
            +
                },
         | 
| 15599 | 
            +
                containsNode: function(parent, child) {
         | 
| 15600 | 
            +
                  if (!child) {
         | 
| 15601 | 
            +
                    child = parent;
         | 
| 15602 | 
            +
                    parent = document.body;
         | 
| 15603 | 
            +
                  }
         | 
| 15604 | 
            +
                  return window.containsNode(parent, child);
         | 
| 15605 | 
            +
                },
         | 
| 15606 | 
            +
                textContent: function(node) {
         | 
| 15607 | 
            +
                  var _ref;
         | 
| 15608 | 
            +
                  return (_ref = node.textContent) != null ? _ref : node.innerText;
         | 
| 15609 | 
            +
                },
         | 
| 15610 | 
            +
                destroyNode: function(node) {
         | 
| 15611 | 
            +
                  var _ref;
         | 
| 15612 | 
            +
                  Batman.DOM.cleanupNode(node);
         | 
| 15613 | 
            +
                  return node != null ? (_ref = node.parentNode) != null ? _ref.removeChild(node) : void 0 : void 0;
         | 
| 15614 | 
            +
                }
         | 
| 15615 | 
            +
              });
         | 
| 15616 | 
            +
             | 
| 15617 | 
            +
              Batman.extend(Batman.Request.prototype, {
         | 
| 15618 | 
            +
                _parseResponseHeaders: function(xhr) {
         | 
| 15619 | 
            +
                  var headers;
         | 
| 15620 | 
            +
                  return headers = xhr.getAllResponseHeaders().split('\n').reduce(function(acc, header) {
         | 
| 15621 | 
            +
                    var key, matches, value;
         | 
| 15622 | 
            +
                    if (matches = header.match(/([^:]*):\s*(.*)/)) {
         | 
| 15623 | 
            +
                      key = matches[1];
         | 
| 15624 | 
            +
                      value = matches[2];
         | 
| 15625 | 
            +
                      acc[key] = value;
         | 
| 15626 | 
            +
                    }
         | 
| 15627 | 
            +
                    return acc;
         | 
| 15628 | 
            +
                  }, {});
         | 
| 15629 | 
            +
                },
         | 
| 15630 | 
            +
                send: function(data) {
         | 
| 15631 | 
            +
                  var options, xhr, _ref,
         | 
| 15632 | 
            +
                    _this = this;
         | 
| 15633 | 
            +
                  if (data == null) {
         | 
| 15634 | 
            +
                    data = this.get('data');
         | 
| 15635 | 
            +
                  }
         | 
| 15636 | 
            +
                  this.fire('loading');
         | 
| 15637 | 
            +
                  options = {
         | 
| 15638 | 
            +
                    url: this.get('url'),
         | 
| 15639 | 
            +
                    method: this.get('method'),
         | 
| 15640 | 
            +
                    type: this.get('type'),
         | 
| 15641 | 
            +
                    headers: this.get('headers'),
         | 
| 15642 | 
            +
                    success: function(response) {
         | 
| 15643 | 
            +
                      _this.mixin({
         | 
| 15644 | 
            +
                        xhr: xhr,
         | 
| 15645 | 
            +
                        response: response,
         | 
| 15646 | 
            +
                        status: typeof xhr !== "undefined" && xhr !== null ? xhr.status : void 0,
         | 
| 15647 | 
            +
                        responseHeaders: _this._parseResponseHeaders(xhr)
         | 
| 15648 | 
            +
                      });
         | 
| 15649 | 
            +
                      return _this.fire('success', response);
         | 
| 15650 | 
            +
                    },
         | 
| 15651 | 
            +
                    error: function(xhr) {
         | 
| 15652 | 
            +
                      _this.mixin({
         | 
| 15653 | 
            +
                        xhr: xhr,
         | 
| 15654 | 
            +
                        response: xhr.responseText || xhr.content,
         | 
| 15655 | 
            +
                        status: xhr.status,
         | 
| 15656 | 
            +
                        responseHeaders: _this._parseResponseHeaders(xhr)
         | 
| 15657 | 
            +
                      });
         | 
| 15658 | 
            +
                      xhr.request = _this;
         | 
| 15659 | 
            +
                      return _this.fire('error', xhr);
         | 
| 15660 | 
            +
                    },
         | 
| 15661 | 
            +
                    complete: function() {
         | 
| 15662 | 
            +
                      return _this.fire('loaded');
         | 
| 15663 | 
            +
                    }
         | 
| 15664 | 
            +
                  };
         | 
| 15665 | 
            +
                  if ((_ref = options.method) === 'PUT' || _ref === 'POST') {
         | 
| 15666 | 
            +
                    if (this.hasFileUploads()) {
         | 
| 15667 | 
            +
                      options.data = this.constructor.objectToFormData(data);
         | 
| 15668 | 
            +
                    } else {
         | 
| 15669 | 
            +
                      options.contentType = this.get('contentType');
         | 
| 15670 | 
            +
                      options.data = Batman.URI.queryFromParams(data);
         | 
| 15671 | 
            +
                    }
         | 
| 15672 | 
            +
                  } else {
         | 
| 15673 | 
            +
                    options.data = data;
         | 
| 15674 | 
            +
                  }
         | 
| 15675 | 
            +
                  return xhr = (reqwest(options)).request;
         | 
| 15676 | 
            +
                }
         | 
| 15677 | 
            +
              });
         | 
| 15678 | 
            +
             | 
| 15679 | 
            +
            }).call(this);
         | 
| 15680 | 
            +
             | 
| 15681 | 
            +
            (function() {
         | 
| 15682 | 
            +
             | 
| 15683 | 
            +
             | 
| 13243 15684 | 
             
            }).call(this);
         |