From bd9dfa7c772a9e169a665edf90c16973f9fd1f9d Mon Sep 17 00:00:00 2001 From: Benjamin ter Kuile Date: Fri, 17 Jul 2015 15:26:59 +0200 Subject: [PATCH] intermediate commit --- Gemfile | 16 +- Gemfile.lock | 287 +- .../supplier/app/helpers/can.js.coffee | 6 +- .../app/initializers/current.js.coffee | 8 + .../routes/application_route.js.coffee.erb | 1 + .../javascripts/supplier/app/store.js.coffee | 16 +- config/application.rb | 2 +- vendor/assets/ember/development/ember-data.js | 12749 ---- vendor/assets/ember/development/ember.js | 49742 ---------------- vendor/assets/ember/production/ember-data.js | 5 - vendor/assets/ember/production/ember.js | 14 - 11 files changed, 172 insertions(+), 62674 deletions(-) create mode 100644 app/assets/javascripts/supplier/app/initializers/current.js.coffee delete mode 100644 vendor/assets/ember/development/ember-data.js delete mode 100644 vendor/assets/ember/development/ember.js delete mode 100644 vendor/assets/ember/production/ember-data.js delete mode 100644 vendor/assets/ember/production/ember.js diff --git a/Gemfile b/Gemfile index 9bbd2afb..2f48132d 100644 --- a/Gemfile +++ b/Gemfile @@ -1,7 +1,7 @@ source 'https://rails-assets.org' source 'https://rubygems.org' -gem 'rails', '4.2.0' +gem 'rails', '~> 4.2.3' gem 'rack-cors', require: 'rack/cors' # Bundle edge Rails instead: @@ -18,10 +18,7 @@ gem 'active_model_serializers', '0.9.0' # explicitly outside assets group :assets do gem 'jquery-rails' gem 'jquery-ui-rails' - gem 'ember-source', '1.8.1'#, github: 'emberjs/ember.js', require: 'ember/source' - gem 'ember-rails' - gem 'ember_script-rails', github: 'ghempton/ember-script-rails' - gem 'sass-rails', '~> 5.0.0' + gem 'sass-rails' #, '~> 5.0.0' gem 'coffee-rails' #, '~> 3.2.1' #gem 'twitter-bootstrap-rails' # Only for mobile assets precompile, not used in this project @@ -36,13 +33,16 @@ group :assets do #gem 'therubyracer', platforms: :ruby gem 'uglifier', '>= 1.0.3' - #gem "emblem-source", github: "machty/emblem.js" - gem 'emblem-source', '0.3.18' + + gem 'ember-rails' + gem 'ember-source', '~> 1.13.0' gem 'emblem-rails' gem 'ember-validations-rails' + gem 'ember-emblem-template' gem 'foundation-rails' #, github: 'bterkuile/foundation-rails' gem 'ace-rails-ap' + gem 'pickadate-rails' #gem 'mustache' #, require: 'mustache/railtie' end @@ -65,7 +65,7 @@ gem "omniauth-instagram" #gem 'simple_form' gem 'active_decorator' #, path: '/Users/bterkuile/companytools/development/rails/components/active_decorator' #gem 'cmtool', github: 'bterkuile/cmtool' -gem 'paperclip' #, '3.5.2' # cmtool +gem 'paperclip', ['>= 4.2.4', '!= 4.3.0'] #, '3.5.2' # cmtool #gem 'cmtool', path: './../cmtool' gem 'cmtool', github: 'bterkuile/cmtool' gem 'kaminari' diff --git a/Gemfile.lock b/Gemfile.lock index b905e475..beac6e55 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,12 +1,16 @@ GIT remote: git://github.com/bterkuile/cmtool.git - revision: 1b82ab178409684e504e70b6403bc4eb8425c432 + revision: 49b61a502624b00aaf3a96c0bd43085ef9f85d75 specs: cmtool (1.0.0) + ace-rails-ap bourbon email_validator + font-awesome-rails + foundation-rails jquery-rails paperclip + pickadate-rails slim-rails tinymce-rails @@ -26,79 +30,72 @@ GIT couch_potato (>= 0.2.15) rest-client (>= 1.4.2) -GIT - remote: git://github.com/ghempton/ember-script-rails.git - revision: 9a1f09b0c53bf51c37c35490cc76cd7dfe461234 - specs: - ember_script-rails (0.0.3) - ember_script (>= 0.0.4) - rails - GEM remote: https://rails-assets.org/ remote: https://rubygems.org/ specs: - ace-rails-ap (3.0.2) - actionmailer (4.2.0) - actionpack (= 4.2.0) - actionview (= 4.2.0) - activejob (= 4.2.0) + ace-rails-ap (3.0.3) + actionmailer (4.2.3) + actionpack (= 4.2.3) + actionview (= 4.2.3) + activejob (= 4.2.3) mail (~> 2.5, >= 2.5.4) rails-dom-testing (~> 1.0, >= 1.0.5) - actionpack (4.2.0) - actionview (= 4.2.0) - activesupport (= 4.2.0) - rack (~> 1.6.0) + actionpack (4.2.3) + actionview (= 4.2.3) + activesupport (= 4.2.3) + rack (~> 1.6) rack-test (~> 0.6.2) rails-dom-testing (~> 1.0, >= 1.0.5) - rails-html-sanitizer (~> 1.0, >= 1.0.1) - actionview (4.2.0) - activesupport (= 4.2.0) + rails-html-sanitizer (~> 1.0, >= 1.0.2) + actionview (4.2.3) + activesupport (= 4.2.3) builder (~> 3.1) erubis (~> 2.7.0) rails-dom-testing (~> 1.0, >= 1.0.5) - rails-html-sanitizer (~> 1.0, >= 1.0.1) + rails-html-sanitizer (~> 1.0, >= 1.0.2) + active-model-adapter-source (1.13.4) + ember-data-source (>= 1.13, < 3.0) active_attr (0.8.5) activemodel (>= 3.0.2, < 5.0) activesupport (>= 3.0.2, < 5.0) - active_decorator (0.5.1) + active_decorator (0.5.3) active_model_serializers (0.9.0) activemodel (>= 3.2) - activejob (4.2.0) - activesupport (= 4.2.0) + activejob (4.2.3) + activesupport (= 4.2.3) globalid (>= 0.3.0) - activemodel (4.2.0) - activesupport (= 4.2.0) + activemodel (4.2.3) + activesupport (= 4.2.3) builder (~> 3.1) - activerecord (4.2.0) - activemodel (= 4.2.0) - activesupport (= 4.2.0) + activerecord (4.2.3) + activemodel (= 4.2.3) + activesupport (= 4.2.3) arel (~> 6.0) - activesupport (4.2.0) + activesupport (4.2.3) i18n (~> 0.7) json (~> 1.7, >= 1.7.7) minitest (~> 5.1) thread_safe (~> 0.3, >= 0.3.4) tzinfo (~> 1.1) - addressable (2.3.7) - airbrussh (0.4.1) + addressable (2.3.8) + airbrussh (0.6.0) sshkit (>= 1.6.1, != 1.7.0) - arel (6.0.0) - barber (0.6.0) - ember-source - execjs - handlebars-source (>= 1.0.0.rc.4) + arel (6.0.2) + barber (0.9.1) + ember-source (>= 1.0, < 2) + execjs (>= 1.2, < 3) barber-emblem (0.1.2) barber (>= 0.4.1) emblem-source bcrypt (3.1.10) binding_of_caller (0.7.2) debug_inspector (>= 0.0.1) - bourbon (4.2.2) + bourbon (4.2.3) sass (~> 3.4) thor builder (3.2.2) - cancancan (1.10.1) + cancancan (1.12.0) capistrano (3.4.0) i18n rake (>= 10.0.0) @@ -106,13 +103,13 @@ GEM capistrano-bundler (1.1.4) capistrano (~> 3.1) sshkit (~> 1.2) - capistrano-rails (1.1.2) + capistrano-rails (1.1.3) capistrano (~> 3.1) capistrano-bundler (~> 1.1) capistrano-rvm (0.1.2) capistrano (~> 3.0) sshkit (~> 1.2) - capistrano3-puma (1.0.0) + capistrano3-puma (1.1.0) capistrano (~> 3.0) puma (>= 2.6) capybara (2.4.4) @@ -121,14 +118,14 @@ GEM rack (>= 1.0.0) rack-test (>= 0.5.4) xpath (~> 2.0) - capybara-screenshot (1.0.5) + capybara-screenshot (1.0.10) capybara (>= 1.0, < 3) - colored launchy celluloid (0.16.0) timers (~> 4.0.0) childprocess (0.5.6) ffi (~> 1.0, >= 1.0.11) + chunky_png (1.3.4) climate_control (0.0.3) activesupport (>= 3.0) cocaine (0.5.7) @@ -137,11 +134,10 @@ GEM coffee-rails (4.1.0) coffee-script (>= 2.2.0) railties (>= 4.0.0, < 5.0) - coffee-script (2.3.0) + coffee-script (2.4.1) coffee-script-source execjs - coffee-script-source (1.9.1) - colored (1.2) + coffee-script-source (1.9.1.1) colorize (0.7.7) cookiejar (0.3.2) couch_potato (1.4.0) @@ -155,19 +151,18 @@ GEM crack (0.4.2) safe_yaml (~> 1.0.0) debug_inspector (0.0.2) - devise (3.4.1) + devise (3.5.1) bcrypt (~> 3.0) orm_adapter (~> 0.1) railties (>= 3.2.6, < 5) responders thread_safe (~> 0.1) warden (~> 1.2.3) - devise-i18n (0.11.4) + devise-i18n (0.12.1) diff-lcs (1.2.5) docile (1.1.5) domain_name (0.5.24) unf (>= 0.0.5, < 1.0.0) - dotenv (1.0.2) em-http-request (1.1.2) addressable (>= 2.3.4) cookiejar @@ -176,35 +171,35 @@ GEM http_parser.rb (>= 0.6.0) em-socksify (0.3.0) eventmachine (>= 1.0.0.beta.4) - email_validator (1.5.0) + email_validator (1.6.0) activemodel - ember-data-source (1.0.0.beta.15) - ember-source (~> 1.8) - ember-rails (0.16.4) + ember-data-source (1.13.5) + ember-source (>= 1.8, < 3.0) + ember-emblem-template (0.2.2) + barber (>= 0.9.0) + sprockets (>= 2.1, < 3.0) + ember-handlebars-template (0.3.0) + barber (>= 0.9.0) + sprockets (>= 2.1, < 3.3) + tilt + ember-rails (0.19.0) + active-model-adapter-source (>= 1.13.0) active_model_serializers - barber (>= 0.6.0) - ember-data-source (>= 1.0.0.beta.5) - ember-source (>= 1.1.0) - execjs (>= 1.2) - handlebars-source (> 1.0.0, < 3) + ember-data-source (>= 1.13.0) + ember-handlebars-template (>= 0.1.1, < 1.0) + ember-source (>= 1.8.0) jquery-rails (>= 1.0.17) railties (>= 3.1) - ember-source (1.8.1) - handlebars-source (~> 1.0) + ember-source (1.13.4.1) ember-validations-rails (1.0.0) railties - ember_script (0.0.5) - ember_script-source (>= 0.0.2) - execjs - tilt - ember_script-source (0.0.14) emblem-rails (0.2.2) barber-emblem (~> 0.1.1) ember-rails (>= 0.14.0) - emblem-source (0.3.18) + emblem-source (0.4.0) erubis (2.7.0) eventmachine (1.0.7) - execjs (2.4.0) + execjs (2.5.2) factory_girl (4.5.0) activesupport (>= 3.0.0) factory_girl_rails (4.5.0) @@ -220,16 +215,15 @@ GEM multi_json (>= 1.0.0) rack (>= 1.0.0) websocket-driver (>= 0.5.1) - faye-websocket (0.9.2) + faye-websocket (0.10.0) eventmachine (>= 0.12.0) websocket-driver (>= 0.5.1) ffi (1.9.10) font-awesome-rails (4.3.0.0) railties (>= 3.2, < 5.0) - foreman (0.77.0) - dotenv (~> 1.0.2) + foreman (0.78.0) thor (~> 0.19.1) - foundation-rails (5.5.1.0) + foundation-rails (5.5.2.1) railties (>= 3.1.0) sass (>= 3.3.0, < 3.5) fuubar (2.0.0) @@ -237,42 +231,41 @@ GEM ruby-progressbar (~> 1.4) gherkin (2.12.2) multi_json (~> 1.3) - globalid (0.3.4) + globalid (0.3.5) activesupport (>= 4.1.0) - handlebars-source (1.3.0) - hashie (3.4.0) + hashie (3.4.2) hike (1.2.3) hitimes (1.2.2) http-cookie (1.0.2) domain_name (~> 0.5) http_parser.rb (0.6.0) i18n (0.7.0) - iso_country_codes (0.6.1) - jquery-rails (4.0.3) + iso_country_codes (0.7.1) + jquery-rails (4.0.4) rails-dom-testing (~> 1.0) railties (>= 4.2.0) thor (>= 0.14, < 2.0) - jquery-ui-rails (5.0.3) + jquery-ui-rails (5.0.5) railties (>= 3.2.16) - js-routes (1.0.0) + js-routes (1.0.1) railties (>= 3.2) sprockets-rails json (1.8.3) - jwt (1.3.0) + jwt (1.5.1) kaminari (0.16.3) actionpack (>= 3.0.0) activesupport (>= 3.0.0) launchy (2.4.3) addressable (~> 2.3) - letter_opener (1.3.0) + letter_opener (1.4.1) launchy (~> 2.2) - loofah (2.0.1) + loofah (2.0.2) nokogiri (>= 1.5.9) mail (2.6.3) mime-types (>= 1.16, < 3) method_source (0.8.2) mime-types (2.6.1) - mini_magick (4.1.0) + mini_magick (4.2.7) mini_portile (0.6.2) minitest (5.7.0) multi_json (1.11.2) @@ -299,44 +292,43 @@ GEM omniauth-instagram (1.0.1) omniauth (~> 1.0) omniauth-oauth2 (~> 1.0) - omniauth-oauth2 (1.2.0) - faraday (>= 0.8, < 0.10) - multi_json (~> 1.3) + omniauth-oauth2 (1.3.1) oauth2 (~> 1.0) omniauth (~> 1.2) orm_adapter (0.5.0) - paperclip (4.2.1) - activemodel (>= 3.0.0) - activesupport (>= 3.0.0) - cocaine (~> 0.5.3) + paperclip (4.2.4) + activemodel (>= 3.2.0) + activesupport (>= 3.2.0) + cocaine (~> 0.5.5) mime-types + pickadate-rails (3.5.6.0) + railties (>= 3.1.0) pry (0.10.1) coderay (~> 1.1.0) method_source (~> 0.8.1) slop (~> 3.4) - pry-rails (0.3.3) + pry-rails (0.3.4) pry (>= 0.9.10) - puma (2.11.3) - rack (>= 1.1, < 2.0) + puma (2.12.1) quiet_assets (1.1.0) railties (>= 3.1, < 5.0) - rack (1.6.0) - rack-cors (0.3.1) + rack (1.6.4) + rack-cors (0.4.0) rack-test (0.6.3) rack (>= 1.0) - rails (4.2.0) - actionmailer (= 4.2.0) - actionpack (= 4.2.0) - actionview (= 4.2.0) - activejob (= 4.2.0) - activemodel (= 4.2.0) - activerecord (= 4.2.0) - activesupport (= 4.2.0) + rails (4.2.3) + actionmailer (= 4.2.3) + actionpack (= 4.2.3) + actionview (= 4.2.3) + activejob (= 4.2.3) + activemodel (= 4.2.3) + activerecord (= 4.2.3) + activesupport (= 4.2.3) bundler (>= 1.3.0, < 2.0) - railties (= 4.2.0) + railties (= 4.2.3) sprockets-rails - rails-assets-ember-qunit (0.2.10) - rails-assets-qunit (1.17.1) + rails-assets-ember-qunit (0.4.1) + rails-assets-qunit (1.18.0) rails-deprecated_sanitizer (1.0.3) activesupport (>= 4.2.0.alpha) rails-dom-testing (1.0.6) @@ -345,9 +337,9 @@ GEM rails-deprecated_sanitizer (>= 1.0.1) rails-html-sanitizer (1.0.2) loofah (~> 2.0) - railties (4.2.0) - actionpack (= 4.2.0) - activesupport (= 4.2.0) + railties (4.2.3) + actionpack (= 4.2.3) + activesupport (= 4.2.3) rake (>= 0.8.7) thor (>= 0.18.1, < 2.0) rake (10.4.2) @@ -357,36 +349,37 @@ GEM http-cookie (>= 1.0.2, < 2.0) mime-types (>= 1.16, < 3.0) netrc (~> 0.7) - rqrcode (0.4.2) - rspec (3.2.0) - rspec-core (~> 3.2.0) - rspec-expectations (~> 3.2.0) - rspec-mocks (~> 3.2.0) - rspec-core (3.2.1) - rspec-support (~> 3.2.0) - rspec-expectations (3.2.0) + rqrcode (0.6.0) + chunky_png + rspec (3.3.0) + rspec-core (~> 3.3.0) + rspec-expectations (~> 3.3.0) + rspec-mocks (~> 3.3.0) + rspec-core (3.3.2) + rspec-support (~> 3.3.0) + rspec-expectations (3.3.1) diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.2.0) + rspec-support (~> 3.3.0) rspec-its (1.2.0) rspec-core (>= 3.0.0) rspec-expectations (>= 3.0.0) - rspec-mocks (3.2.1) + rspec-mocks (3.3.2) diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.2.0) - rspec-rails (3.2.1) + rspec-support (~> 3.3.0) + rspec-rails (3.3.3) actionpack (>= 3.0, < 4.3) activesupport (>= 3.0, < 4.3) railties (>= 3.0, < 4.3) - rspec-core (~> 3.2.0) - rspec-expectations (~> 3.2.0) - rspec-mocks (~> 3.2.0) - rspec-support (~> 3.2.0) - rspec-support (3.2.2) - ruby-progressbar (1.7.1) + rspec-core (~> 3.3.0) + rspec-expectations (~> 3.3.0) + rspec-mocks (~> 3.3.0) + rspec-support (~> 3.3.0) + rspec-support (3.3.0) + ruby-progressbar (1.7.5) rubyzip (1.1.7) safe_yaml (1.0.4) - sass (3.4.13) - sass-rails (5.0.1) + sass (3.4.16) + sass-rails (5.0.3) railties (>= 4.0.0, < 5.0) sass (~> 3.1) sprockets (>= 2.8, < 4.0) @@ -397,12 +390,12 @@ GEM multi_json (~> 1.0) rubyzip (~> 1.0) websocket (~> 1.0) - simplecov (0.9.2) + simplecov (0.10.0) docile (~> 1.1.0) - multi_json (~> 1.0) - simplecov-html (~> 0.9.0) - simplecov-html (0.9.0) - slim (3.0.3) + json (~> 1.8) + simplecov-html (~> 0.10.0) + simplecov-html (0.10.0) + slim (3.0.6) temple (~> 0.7.3) tilt (>= 1.3.3, < 2.1) slim-rails (3.0.1) @@ -415,12 +408,12 @@ GEM spring (1.3.6) spring-commands-rspec (1.0.4) spring (>= 0.9.1) - sprockets (2.12.3) + sprockets (2.12.4) hike (~> 1.2) multi_json (~> 1.0) rack (~> 1.0) tilt (~> 1.1, != 1.3.0) - sprockets-rails (2.2.4) + sprockets-rails (2.3.2) actionpack (>= 3.0) activesupport (>= 3.0) sprockets (>= 2.8, < 4.0) @@ -428,9 +421,9 @@ GEM colorize (>= 0.7.0) net-scp (>= 1.1.2) net-ssh (>= 2.8.0) - sucker_punch (1.4.0) + sucker_punch (1.5.0) celluloid (~> 0.16.0) - temple (0.7.5) + temple (0.7.6) test_squad (0.0.1) rails thor (0.19.1) @@ -440,7 +433,7 @@ GEM hitimes tinymce-rails (4.1.6) railties (>= 3.1.1) - turnip (1.2.4) + turnip (1.3.1) gherkin (>= 2.5) rspec (>= 2.14.0, < 4.0) tzinfo (1.2.2) @@ -458,11 +451,11 @@ GEM binding_of_caller (>= 0.7.2) railties (~> 4.0) sprockets-rails (>= 2.0, < 4.0) - webmock (1.20.4) + webmock (1.21.0) addressable (>= 2.3.6) crack (>= 0.3.2) websocket (1.2.2) - websocket-driver (0.5.3) + websocket-driver (0.6.1) websocket-extensions (>= 0.1.0) websocket-extensions (0.1.2) xpath (2.0.0) @@ -491,12 +484,11 @@ DEPENDENCIES devise devise-i18n devise_simply_stored! + ember-emblem-template ember-rails - ember-source (= 1.8.1) + ember-source (~> 1.13.0) ember-validations-rails - ember_script-rails! emblem-rails - emblem-source (= 0.3.18) factory_girl_rails faye font-awesome-rails @@ -514,18 +506,19 @@ DEPENDENCIES naught omniauth-facebook omniauth-instagram - paperclip + paperclip (>= 4.2.4, != 4.3.0) + pickadate-rails pry-rails puma quiet_assets rack-cors - rails (= 4.2.0) + rails (~> 4.2.3) rails-assets-ember-qunit rails-assets-qunit rqrcode rspec-its rspec-rails - sass-rails (~> 5.0.0) + sass-rails selenium-webdriver simplecov simply_stored! diff --git a/app/assets/javascripts/supplier/app/helpers/can.js.coffee b/app/assets/javascripts/supplier/app/helpers/can.js.coffee index 5f1680ac..59008723 100644 --- a/app/assets/javascripts/supplier/app/helpers/can.js.coffee +++ b/app/assets/javascripts/supplier/app/helpers/can.js.coffee @@ -1,5 +1,7 @@ Ember.Handlebars.registerHelper 'can', (operation, resource, options)-> - if operation is 'manage' and @get('current_employee.manager') + #if operation is 'manage' and @get('current_employee.manager') + #App.__container__.lookup('globals:current').get('employee.manager') + if operation is 'manage' and options.data.view and options.data.view.get('controller.current_employee.manager') options.fn @ else - options.inverse @ + options.inverse @ if options.inverse diff --git a/app/assets/javascripts/supplier/app/initializers/current.js.coffee b/app/assets/javascripts/supplier/app/initializers/current.js.coffee new file mode 100644 index 00000000..aad4e8cf --- /dev/null +++ b/app/assets/javascripts/supplier/app/initializers/current.js.coffee @@ -0,0 +1,8 @@ +App.initializer + name: 'injectCurrent' + initialize: (container, app)-> + container.optionsForType 'globals', instantiate: false, singleton: true + container.register 'globals:current', Em.Object.create() + + container.typeInjection 'controller', 'current', 'globals:current' + container.typeInjection 'route', 'current', 'globals:current' diff --git a/app/assets/javascripts/supplier/app/routes/application_route.js.coffee.erb b/app/assets/javascripts/supplier/app/routes/application_route.js.coffee.erb index 2afd906b..383d9bfe 100644 --- a/app/assets/javascripts/supplier/app/routes/application_route.js.coffee.erb +++ b/app/assets/javascripts/supplier/app/routes/application_route.js.coffee.erb @@ -14,6 +14,7 @@ App.ApplicationRoute = Ember.Route.extend setupController: (controller)-> controller.set 'supplier', @supplier controller.set 'employee', @employee + controller.set 'current.employee', @employee # @set 'supplier', @store.find('supplier', supplier_id) #controller.set 'sections', @sections #controller.set 'product_categories', @product_categories diff --git a/app/assets/javascripts/supplier/app/store.js.coffee b/app/assets/javascripts/supplier/app/store.js.coffee index e86fb568..f5d5f423 100644 --- a/app/assets/javascripts/supplier/app/store.js.coffee +++ b/app/assets/javascripts/supplier/app/store.js.coffee @@ -1,8 +1,12 @@ App.ApplicationSerializer = DS.ActiveModelSerializer -App.ApplicationStore = DS.Store.extend - adapter: DS.ActiveModelAdapter.extend - namespace: 'supplier' - ## user underscored paths - #pathForType: (type)-> - #Ember.String.pluralize(Ember.String.decamelize(type)) +App.ApplicationStore = DS.Store +#adapter: DS.ActiveModelAdapter.extend + #namespace: 'supplier' + ## user underscored paths + #pathForType: (type)-> + #Ember.String.pluralize(Ember.String.decamelize(type)) +App.ApplicationAdapter = DS.ActiveModelAdapter.extend + namespace: 'supplier' + #headers: + #"Accept": "application/json, text/javascript; q=0.01" diff --git a/config/application.rb b/config/application.rb index c7b226d9..ad9602aa 100644 --- a/config/application.rb +++ b/config/application.rb @@ -103,7 +103,7 @@ module Qwaiter end - config.handlebars.templates_root = %w[supplier/app/templates waiter/app/templates user/app/templates] if defined?(Ember::Rails) && defined?(Handlebars) + #config.handlebars.templates_root = %w[supplier/app/templates waiter/app/templates user/app/templates] if defined?(Ember::Rails) && defined?(Handlebars) config.generators do |g| g.orm :simply_stored diff --git a/vendor/assets/ember/development/ember-data.js b/vendor/assets/ember/development/ember-data.js deleted file mode 100644 index e8433e42..00000000 --- a/vendor/assets/ember/development/ember-data.js +++ /dev/null @@ -1,12749 +0,0 @@ -// Fetched from channel: release, with url http://builds.emberjs.com/beta/ember-data.js -// Fetched on: 2014-11-24T13:02:13Z -(function(global){ -var define, requireModule, require, requirejs; - -(function() { - - var _isArray; - if (!Array.isArray) { - _isArray = function (x) { - return Object.prototype.toString.call(x) === "[object Array]"; - }; - } else { - _isArray = Array.isArray; - } - - var registry = {}, seen = {}, state = {}; - var FAILED = false; - - define = function(name, deps, callback) { - - if (!_isArray(deps)) { - callback = deps; - deps = []; - } - - registry[name] = { - deps: deps, - callback: callback - }; - }; - - function reify(deps, name, seen) { - var length = deps.length; - var reified = new Array(length); - var dep; - var exports; - - for (var i = 0, l = length; i < l; i++) { - dep = deps[i]; - if (dep === 'exports') { - exports = reified[i] = seen; - } else { - reified[i] = require(resolve(dep, name)); - } - } - - return { - deps: reified, - exports: exports - }; - } - - requirejs = require = requireModule = function(name) { - if (state[name] !== FAILED && - seen.hasOwnProperty(name)) { - return seen[name]; - } - - if (!registry[name]) { - throw new Error('Could not find module ' + name); - } - - var mod = registry[name]; - var reified; - var module; - var loaded = false; - - seen[name] = { }; // placeholder for run-time cycles - - try { - reified = reify(mod.deps, name, seen[name]); - module = mod.callback.apply(this, reified.deps); - loaded = true; - } finally { - if (!loaded) { - state[name] = FAILED; - } - } - - return reified.exports ? seen[name] : (seen[name] = module); - }; - - function resolve(child, name) { - if (child.charAt(0) !== '.') { return child; } - - var parts = child.split('/'); - var nameParts = name.split('/'); - var parentBase; - - if (nameParts.length === 1) { - parentBase = nameParts; - } else { - parentBase = nameParts.slice(0, -1); - } - - for (var i = 0, l = parts.length; i < l; i++) { - var part = parts[i]; - - if (part === '..') { parentBase.pop(); } - else if (part === '.') { continue; } - else { parentBase.push(part); } - } - - return parentBase.join('/'); - } - - requirejs.entries = requirejs._eak_seen = registry; - requirejs.clear = function(){ - requirejs.entries = requirejs._eak_seen = registry = {}; - seen = state = {}; - }; -})(); - -define("activemodel-adapter", - ["activemodel-adapter/system","exports"], - function(__dependency1__, __exports__) { - "use strict"; - var ActiveModelAdapter = __dependency1__.ActiveModelAdapter; - var ActiveModelSerializer = __dependency1__.ActiveModelSerializer; - - __exports__.ActiveModelAdapter = ActiveModelAdapter; - __exports__.ActiveModelSerializer = ActiveModelSerializer; - }); -define("activemodel-adapter/setup-container", - ["ember-data/system/container_proxy","activemodel-adapter/system/active_model_serializer","activemodel-adapter/system/active_model_adapter","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __exports__) { - "use strict"; - var ContainerProxy = __dependency1__["default"]; - var ActiveModelSerializer = __dependency2__["default"]; - var ActiveModelAdapter = __dependency3__["default"]; - - __exports__["default"] = function setupActiveModelAdapter(container, application){ - var proxy = new ContainerProxy(container); - proxy.registerDeprecations([ - { deprecated: 'serializer:_ams', valid: 'serializer:-active-model' }, - { deprecated: 'adapter:_ams', valid: 'adapter:-active-model' } - ]); - - container.register('serializer:-active-model', ActiveModelSerializer); - container.register('adapter:-active-model', ActiveModelAdapter); - }; - }); -define("activemodel-adapter/system", - ["activemodel-adapter/system/active_model_adapter","activemodel-adapter/system/active_model_serializer","exports"], - function(__dependency1__, __dependency2__, __exports__) { - "use strict"; - var ActiveModelAdapter = __dependency1__["default"]; - var ActiveModelSerializer = __dependency2__["default"]; - - __exports__.ActiveModelAdapter = ActiveModelAdapter; - __exports__.ActiveModelSerializer = ActiveModelSerializer; - }); -define("activemodel-adapter/system/active_model_adapter", - ["ember-data/adapters","ember-data/system/adapter","ember-inflector","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __exports__) { - "use strict"; - var RESTAdapter = __dependency1__.RESTAdapter; - var InvalidError = __dependency2__.InvalidError; - var pluralize = __dependency3__.pluralize; - - /** - @module ember-data - */ - - var forEach = Ember.EnumerableUtils.forEach; - var decamelize = Ember.String.decamelize, - underscore = Ember.String.underscore; - - /** - The ActiveModelAdapter is a subclass of the RESTAdapter designed to integrate - with a JSON API that uses an underscored naming convention instead of camelCasing. - It has been designed to work out of the box with the - [active_model_serializers](http://github.com/rails-api/active_model_serializers) - Ruby gem. This Adapter expects specific settings using ActiveModel::Serializers, - `embed :ids, include: true` which sideloads the records. - - This adapter extends the DS.RESTAdapter by making consistent use of the camelization, - decamelization and pluralization methods to normalize the serialized JSON into a - format that is compatible with a conventional Rails backend and Ember Data. - - ## JSON Structure - - The ActiveModelAdapter expects the JSON returned from your server to follow - the REST adapter conventions substituting underscored keys for camelcased ones. - - Unlike the DS.RESTAdapter, async relationship keys must be the singular form - of the relationship name, followed by "_id" for DS.belongsTo relationships, - or "_ids" for DS.hasMany relationships. - - ### Conventional Names - - Attribute names in your JSON payload should be the underscored versions of - the attributes in your Ember.js models. - - For example, if you have a `Person` model: - - ```js - App.FamousPerson = DS.Model.extend({ - firstName: DS.attr('string'), - lastName: DS.attr('string'), - occupation: DS.attr('string') - }); - ``` - - The JSON returned should look like this: - - ```js - { - "famous_person": { - "id": 1, - "first_name": "Barack", - "last_name": "Obama", - "occupation": "President" - } - } - ``` - - Let's imagine that `Occupation` is just another model: - - ```js - App.Person = DS.Model.extend({ - firstName: DS.attr('string'), - lastName: DS.attr('string'), - occupation: DS.belongsTo('occupation') - }); - - App.Occupation = DS.Model.extend({ - name: DS.attr('string'), - salary: DS.attr('number'), - people: DS.hasMany('person') - }); - ``` - - The JSON needed to avoid extra server calls, should look like this: - - ```js - { - "people": [{ - "id": 1, - "first_name": "Barack", - "last_name": "Obama", - "occupation_id": 1 - }], - - "occupations": [{ - "id": 1, - "name": "President", - "salary": 100000, - "person_ids": [1] - }] - } - ``` - - @class ActiveModelAdapter - @constructor - @namespace DS - @extends DS.RESTAdapter - **/ - - var ActiveModelAdapter = RESTAdapter.extend({ - defaultSerializer: '-active-model', - /** - The ActiveModelAdapter overrides the `pathForType` method to build - underscored URLs by decamelizing and pluralizing the object type name. - - ```js - this.pathForType("famousPerson"); - //=> "famous_people" - ``` - - @method pathForType - @param {String} type - @return String - */ - pathForType: function(type) { - var decamelized = decamelize(type); - var underscored = underscore(decamelized); - return pluralize(underscored); - }, - - /** - The ActiveModelAdapter overrides the `ajaxError` method - to return a DS.InvalidError for all 422 Unprocessable Entity - responses. - - A 422 HTTP response from the server generally implies that the request - was well formed but the API was unable to process it because the - content was not semantically correct or meaningful per the API. - - For more information on 422 HTTP Error code see 11.2 WebDAV RFC 4918 - https://tools.ietf.org/html/rfc4918#section-11.2 - - @method ajaxError - @param {Object} jqXHR - @return error - */ - ajaxError: function(jqXHR) { - var error = this._super(jqXHR); - - if (jqXHR && jqXHR.status === 422) { - var response = Ember.$.parseJSON(jqXHR.responseText), - errors = {}; - - if (response.errors !== undefined) { - var jsonErrors = response.errors; - - forEach(Ember.keys(jsonErrors), function(key) { - errors[Ember.String.camelize(key)] = jsonErrors[key]; - }); - } - - return new InvalidError(errors); - } else { - return error; - } - } - }); - - __exports__["default"] = ActiveModelAdapter; - }); -define("activemodel-adapter/system/active_model_serializer", - ["ember-inflector","ember-data/serializers/rest_serializer","exports"], - function(__dependency1__, __dependency2__, __exports__) { - "use strict"; - var singularize = __dependency1__.singularize; - var RESTSerializer = __dependency2__["default"]; - /** - @module ember-data - */ - - var get = Ember.get, - forEach = Ember.EnumerableUtils.forEach, - camelize = Ember.String.camelize, - capitalize = Ember.String.capitalize, - decamelize = Ember.String.decamelize, - underscore = Ember.String.underscore; - /** - The ActiveModelSerializer is a subclass of the RESTSerializer designed to integrate - with a JSON API that uses an underscored naming convention instead of camelCasing. - It has been designed to work out of the box with the - [active_model_serializers](http://github.com/rails-api/active_model_serializers) - Ruby gem. This Serializer expects specific settings using ActiveModel::Serializers, - `embed :ids, include: true` which sideloads the records. - - This serializer extends the DS.RESTSerializer by making consistent - use of the camelization, decamelization and pluralization methods to - normalize the serialized JSON into a format that is compatible with - a conventional Rails backend and Ember Data. - - ## JSON Structure - - The ActiveModelSerializer expects the JSON returned from your server - to follow the REST adapter conventions substituting underscored keys - for camelcased ones. - - ### Conventional Names - - Attribute names in your JSON payload should be the underscored versions of - the attributes in your Ember.js models. - - For example, if you have a `Person` model: - - ```js - App.FamousPerson = DS.Model.extend({ - firstName: DS.attr('string'), - lastName: DS.attr('string'), - occupation: DS.attr('string') - }); - ``` - - The JSON returned should look like this: - - ```js - { - "famous_person": { - "id": 1, - "first_name": "Barack", - "last_name": "Obama", - "occupation": "President" - } - } - ``` - - Let's imagine that `Occupation` is just another model: - - ```js - App.Person = DS.Model.extend({ - firstName: DS.attr('string'), - lastName: DS.attr('string'), - occupation: DS.belongsTo('occupation') - }); - - App.Occupation = DS.Model.extend({ - name: DS.attr('string'), - salary: DS.attr('number'), - people: DS.hasMany('person') - }); - ``` - - The JSON needed to avoid extra server calls, should look like this: - - ```js - { - "people": [{ - "id": 1, - "first_name": "Barack", - "last_name": "Obama", - "occupation_id": 1 - }], - - "occupations": [{ - "id": 1, - "name": "President", - "salary": 100000, - "person_ids": [1] - }] - } - ``` - - @class ActiveModelSerializer - @namespace DS - @extends DS.RESTSerializer - */ - var ActiveModelSerializer = RESTSerializer.extend({ - // SERIALIZE - - /** - Converts camelCased attributes to underscored when serializing. - - @method keyForAttribute - @param {String} attribute - @return String - */ - keyForAttribute: function(attr) { - return decamelize(attr); - }, - - /** - Underscores relationship names and appends "_id" or "_ids" when serializing - relationship keys. - - @method keyForRelationship - @param {String} key - @param {String} kind - @return String - */ - keyForRelationship: function(rawKey, kind) { - var key = decamelize(rawKey); - if (kind === "belongsTo") { - return key + "_id"; - } else if (kind === "hasMany") { - return singularize(key) + "_ids"; - } else { - return key; - } - }, - - /* - Does not serialize hasMany relationships by default. - */ - serializeHasMany: Ember.K, - - /** - Underscores the JSON root keys when serializing. - - @method serializeIntoHash - @param {Object} hash - @param {subclass of DS.Model} type - @param {DS.Model} record - @param {Object} options - */ - serializeIntoHash: function(data, type, record, options) { - var root = underscore(decamelize(type.typeKey)); - data[root] = this.serialize(record, options); - }, - - /** - Serializes a polymorphic type as a fully capitalized model name. - - @method serializePolymorphicType - @param {DS.Model} record - @param {Object} json - @param {Object} relationship - */ - serializePolymorphicType: function(record, json, relationship) { - var key = relationship.key; - var belongsTo = get(record, key); - var jsonKey = underscore(key + "_type"); - - if (Ember.isNone(belongsTo)) { - json[jsonKey] = null; - } else { - json[jsonKey] = capitalize(camelize(belongsTo.constructor.typeKey)); - } - }, - - // EXTRACT - - /** - Add extra step to `DS.RESTSerializer.normalize` so links are normalized. - - If your payload looks like: - - ```js - { - "post": { - "id": 1, - "title": "Rails is omakase", - "links": { "flagged_comments": "api/comments/flagged" } - } - } - ``` - - The normalized version would look like this - - ```js - { - "post": { - "id": 1, - "title": "Rails is omakase", - "links": { "flaggedComments": "api/comments/flagged" } - } - } - ``` - - @method normalize - @param {subclass of DS.Model} type - @param {Object} hash - @param {String} prop - @return Object - */ - - normalize: function(type, hash, prop) { - this.normalizeLinks(hash); - - return this._super(type, hash, prop); - }, - - /** - Convert `snake_cased` links to `camelCase` - - @method normalizeLinks - @param {Object} data - */ - - normalizeLinks: function(data){ - if (data.links) { - var links = data.links; - - for (var link in links) { - var camelizedLink = camelize(link); - - if (camelizedLink !== link) { - links[camelizedLink] = links[link]; - delete links[link]; - } - } - } - }, - - /** - Normalize the polymorphic type from the JSON. - - Normalize: - ```js - { - id: "1" - minion: { type: "evil_minion", id: "12"} - } - ``` - - To: - ```js - { - id: "1" - minion: { type: "evilMinion", id: "12"} - } - ``` - - @method normalizeRelationships - @private - */ - normalizeRelationships: function(type, hash) { - - if (this.keyForRelationship) { - type.eachRelationship(function(key, relationship) { - var payloadKey, payload; - if (relationship.options.polymorphic) { - payloadKey = this.keyForAttribute(key); - payload = hash[payloadKey]; - if (payload && payload.type) { - payload.type = this.typeForRoot(payload.type); - } else if (payload && relationship.kind === "hasMany") { - var self = this; - forEach(payload, function(single) { - single.type = self.typeForRoot(single.type); - }); - } - } else { - payloadKey = this.keyForRelationship(key, relationship.kind); - if (!hash.hasOwnProperty(payloadKey)) { return; } - payload = hash[payloadKey]; - } - - hash[key] = payload; - - if (key !== payloadKey) { - delete hash[payloadKey]; - } - }, this); - } - } - }); - - __exports__["default"] = ActiveModelSerializer; - }); -define("ember-data", - ["ember-data/core","ember-data/ext/date","ember-data/system/promise_proxies","ember-data/system/store","ember-data/system/model","ember-data/system/adapter","ember-data/system/debug","ember-data/system/record_arrays","ember-data/system/record_array_manager","ember-data/adapters","ember-data/serializers/json_serializer","ember-data/serializers/rest_serializer","ember-inflector","ember-data/serializers/embedded_records_mixin","activemodel-adapter","ember-data/transforms","ember-data/system/relationships","ember-data/ember-initializer","ember-data/setup-container","ember-data/system/container_proxy","ember-data/system/relationships/relationship","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __dependency11__, __dependency12__, __dependency13__, __dependency14__, __dependency15__, __dependency16__, __dependency17__, __dependency18__, __dependency19__, __dependency20__, __dependency21__, __exports__) { - "use strict"; - /** - Ember Data - - @module ember-data - @main ember-data - */ - - // support RSVP 2.x via resolve, but prefer RSVP 3.x's Promise.cast - Ember.RSVP.Promise.cast = Ember.RSVP.Promise.cast || Ember.RSVP.resolve; - - var DS = __dependency1__["default"]; - - var PromiseArray = __dependency3__.PromiseArray; - var PromiseObject = __dependency3__.PromiseObject; - var Store = __dependency4__.Store; - var Model = __dependency5__.Model; - var Errors = __dependency5__.Errors; - var RootState = __dependency5__.RootState; - var attr = __dependency5__.attr; - var InvalidError = __dependency6__.InvalidError; - var Adapter = __dependency6__.Adapter; - var DebugAdapter = __dependency7__["default"]; - var RecordArray = __dependency8__.RecordArray; - var FilteredRecordArray = __dependency8__.FilteredRecordArray; - var AdapterPopulatedRecordArray = __dependency8__.AdapterPopulatedRecordArray; - var ManyArray = __dependency8__.ManyArray; - var RecordArrayManager = __dependency9__["default"]; - var RESTAdapter = __dependency10__.RESTAdapter; - var FixtureAdapter = __dependency10__.FixtureAdapter; - var JSONSerializer = __dependency11__["default"]; - var RESTSerializer = __dependency12__["default"]; - var EmbeddedRecordsMixin = __dependency14__["default"]; - var ActiveModelAdapter = __dependency15__.ActiveModelAdapter; - var ActiveModelSerializer = __dependency15__.ActiveModelSerializer; - - var Transform = __dependency16__.Transform; - var DateTransform = __dependency16__.DateTransform; - var NumberTransform = __dependency16__.NumberTransform; - var StringTransform = __dependency16__.StringTransform; - var BooleanTransform = __dependency16__.BooleanTransform; - - var hasMany = __dependency17__.hasMany; - var belongsTo = __dependency17__.belongsTo; - var setupContainer = __dependency19__["default"]; - - var ContainerProxy = __dependency20__["default"]; - var Relationship = __dependency21__.Relationship; - - DS.Store = Store; - DS.PromiseArray = PromiseArray; - DS.PromiseObject = PromiseObject; - - DS.Model = Model; - DS.RootState = RootState; - DS.attr = attr; - DS.Errors = Errors; - - DS.Adapter = Adapter; - DS.InvalidError = InvalidError; - - DS.DebugAdapter = DebugAdapter; - - DS.RecordArray = RecordArray; - DS.FilteredRecordArray = FilteredRecordArray; - DS.AdapterPopulatedRecordArray = AdapterPopulatedRecordArray; - DS.ManyArray = ManyArray; - - DS.RecordArrayManager = RecordArrayManager; - - DS.RESTAdapter = RESTAdapter; - DS.FixtureAdapter = FixtureAdapter; - - DS.RESTSerializer = RESTSerializer; - DS.JSONSerializer = JSONSerializer; - - DS.Transform = Transform; - DS.DateTransform = DateTransform; - DS.StringTransform = StringTransform; - DS.NumberTransform = NumberTransform; - DS.BooleanTransform = BooleanTransform; - - DS.ActiveModelAdapter = ActiveModelAdapter; - DS.ActiveModelSerializer = ActiveModelSerializer; - DS.EmbeddedRecordsMixin = EmbeddedRecordsMixin; - - DS.belongsTo = belongsTo; - DS.hasMany = hasMany; - - DS.Relationship = Relationship; - - DS.ContainerProxy = ContainerProxy; - - DS._setupContainer = setupContainer; - - Ember.lookup.DS = DS; - - __exports__["default"] = DS; - }); -define("ember-data/adapters", - ["ember-data/adapters/fixture_adapter","ember-data/adapters/rest_adapter","exports"], - function(__dependency1__, __dependency2__, __exports__) { - "use strict"; - /** - @module ember-data - */ - - var FixtureAdapter = __dependency1__["default"]; - var RESTAdapter = __dependency2__["default"]; - - __exports__.RESTAdapter = RESTAdapter; - __exports__.FixtureAdapter = FixtureAdapter; - }); -define("ember-data/adapters/fixture_adapter", - ["ember-data/system/adapter","exports"], - function(__dependency1__, __exports__) { - "use strict"; - /** - @module ember-data - */ - - var get = Ember.get; - var fmt = Ember.String.fmt; - var indexOf = Ember.EnumerableUtils.indexOf; - - var counter = 0; - - var Adapter = __dependency1__["default"]; - - /** - `DS.FixtureAdapter` is an adapter that loads records from memory. - It's primarily used for development and testing. You can also use - `DS.FixtureAdapter` while working on the API but is not ready to - integrate yet. It is a fully functioning adapter. All CRUD methods - are implemented. You can also implement query logic that a remote - system would do. It's possible to develop your entire application - with `DS.FixtureAdapter`. - - For information on how to use the `FixtureAdapter` in your - application please see the [FixtureAdapter - guide](/guides/models/the-fixture-adapter/). - - @class FixtureAdapter - @namespace DS - @extends DS.Adapter - */ - __exports__["default"] = Adapter.extend({ - // by default, fixtures are already in normalized form - serializer: null, - - /** - If `simulateRemoteResponse` is `true` the `FixtureAdapter` will - wait a number of milliseconds before resolving promises with the - fixture values. The wait time can be configured via the `latency` - property. - - @property simulateRemoteResponse - @type {Boolean} - @default true - */ - simulateRemoteResponse: true, - - /** - By default the `FixtureAdapter` will simulate a wait of the - `latency` milliseconds before resolving promises with the fixture - values. This behavior can be turned off via the - `simulateRemoteResponse` property. - - @property latency - @type {Number} - @default 50 - */ - latency: 50, - - /** - Implement this method in order to provide data associated with a type - - @method fixturesForType - @param {Subclass of DS.Model} type - @return {Array} - */ - fixturesForType: function(type) { - if (type.FIXTURES) { - var fixtures = Ember.A(type.FIXTURES); - return fixtures.map(function(fixture){ - var fixtureIdType = typeof fixture.id; - if(fixtureIdType !== "number" && fixtureIdType !== "string"){ - throw new Error(fmt('the id property must be defined as a number or string for fixture %@', [fixture])); - } - fixture.id = fixture.id + ''; - return fixture; - }); - } - return null; - }, - - /** - Implement this method in order to query fixtures data - - @method queryFixtures - @param {Array} fixture - @param {Object} query - @param {Subclass of DS.Model} type - @return {Promise|Array} - */ - queryFixtures: function(fixtures, query, type) { - Ember.assert('Not implemented: You must override the DS.FixtureAdapter::queryFixtures method to support querying the fixture store.'); - }, - - /** - @method updateFixtures - @param {Subclass of DS.Model} type - @param {Array} fixture - */ - updateFixtures: function(type, fixture) { - if(!type.FIXTURES) { - type.FIXTURES = []; - } - - var fixtures = type.FIXTURES; - - this.deleteLoadedFixture(type, fixture); - - fixtures.push(fixture); - }, - - /** - Implement this method in order to provide json for CRUD methods - - @method mockJSON - @param {Subclass of DS.Model} type - @param {DS.Model} record - */ - mockJSON: function(store, type, record) { - return store.serializerFor(type).serialize(record, { includeId: true }); - }, - - /** - @method generateIdForRecord - @param {DS.Store} store - @param {DS.Model} record - @return {String} id - */ - generateIdForRecord: function(store) { - return "fixture-" + counter++; - }, - - /** - @method find - @param {DS.Store} store - @param {subclass of DS.Model} type - @param {String} id - @return {Promise} promise - */ - find: function(store, type, id) { - var fixtures = this.fixturesForType(type); - var fixture; - - Ember.assert("Unable to find fixtures for model type "+type.toString() +". If you're defining your fixtures using `Model.FIXTURES = ...`, please change it to `Model.reopenClass({ FIXTURES: ... })`.", fixtures); - - if (fixtures) { - fixture = Ember.A(fixtures).findBy('id', id); - } - - if (fixture) { - return this.simulateRemoteCall(function() { - return fixture; - }, this); - } - }, - - /** - @method findMany - @param {DS.Store} store - @param {subclass of DS.Model} type - @param {Array} ids - @return {Promise} promise - */ - findMany: function(store, type, ids) { - var fixtures = this.fixturesForType(type); - - Ember.assert("Unable to find fixtures for model type "+type.toString(), fixtures); - - if (fixtures) { - fixtures = fixtures.filter(function(item) { - return indexOf(ids, item.id) !== -1; - }); - } - - if (fixtures) { - return this.simulateRemoteCall(function() { - return fixtures; - }, this); - } - }, - - /** - @private - @method findAll - @param {DS.Store} store - @param {subclass of DS.Model} type - @param {String} sinceToken - @return {Promise} promise - */ - findAll: function(store, type) { - var fixtures = this.fixturesForType(type); - - Ember.assert("Unable to find fixtures for model type "+type.toString(), fixtures); - - return this.simulateRemoteCall(function() { - return fixtures; - }, this); - }, - - /** - @private - @method findQuery - @param {DS.Store} store - @param {subclass of DS.Model} type - @param {Object} query - @param {DS.AdapterPopulatedRecordArray} recordArray - @return {Promise} promise - */ - findQuery: function(store, type, query, array) { - var fixtures = this.fixturesForType(type); - - Ember.assert("Unable to find fixtures for model type " + type.toString(), fixtures); - - fixtures = this.queryFixtures(fixtures, query, type); - - if (fixtures) { - return this.simulateRemoteCall(function() { - return fixtures; - }, this); - } - }, - - /** - @method createRecord - @param {DS.Store} store - @param {subclass of DS.Model} type - @param {DS.Model} record - @return {Promise} promise - */ - createRecord: function(store, type, record) { - var fixture = this.mockJSON(store, type, record); - - this.updateFixtures(type, fixture); - - return this.simulateRemoteCall(function() { - return fixture; - }, this); - }, - - /** - @method updateRecord - @param {DS.Store} store - @param {subclass of DS.Model} type - @param {DS.Model} record - @return {Promise} promise - */ - updateRecord: function(store, type, record) { - var fixture = this.mockJSON(store, type, record); - - this.updateFixtures(type, fixture); - - return this.simulateRemoteCall(function() { - return fixture; - }, this); - }, - - /** - @method deleteRecord - @param {DS.Store} store - @param {subclass of DS.Model} type - @param {DS.Model} record - @return {Promise} promise - */ - deleteRecord: function(store, type, record) { - this.deleteLoadedFixture(type, record); - - return this.simulateRemoteCall(function() { - // no payload in a deletion - return null; - }); - }, - - /* - @method deleteLoadedFixture - @private - @param type - @param record - */ - deleteLoadedFixture: function(type, record) { - var existingFixture = this.findExistingFixture(type, record); - - if (existingFixture) { - var index = indexOf(type.FIXTURES, existingFixture); - type.FIXTURES.splice(index, 1); - return true; - } - }, - - /* - @method findExistingFixture - @private - @param type - @param record - */ - findExistingFixture: function(type, record) { - var fixtures = this.fixturesForType(type); - var id = get(record, 'id'); - - return this.findFixtureById(fixtures, id); - }, - - /* - @method findFixtureById - @private - @param fixtures - @param id - */ - findFixtureById: function(fixtures, id) { - return Ember.A(fixtures).find(function(r) { - if (''+get(r, 'id') === ''+id) { - return true; - } else { - return false; - } - }); - }, - - /* - @method simulateRemoteCall - @private - @param callback - @param context - */ - simulateRemoteCall: function(callback, context) { - var adapter = this; - - return new Ember.RSVP.Promise(function(resolve) { - var value = Ember.copy(callback.call(context), true); - if (get(adapter, 'simulateRemoteResponse')) { - // Schedule with setTimeout - Ember.run.later(function() { - resolve(value); - }, get(adapter, 'latency')); - } else { - // Asynchronous, but at the of the runloop with zero latency - Ember.run.schedule('actions', null, function() { - resolve(value); - }); - } - }, "DS: FixtureAdapter#simulateRemoteCall"); - } - }); - }); -define("ember-data/adapters/rest_adapter", - ["ember-data/system/adapter","ember-data/system/map","exports"], - function(__dependency1__, __dependency2__, __exports__) { - "use strict"; - /** - @module ember-data - */ - - var Adapter = __dependency1__.Adapter; - var InvalidError = __dependency1__.InvalidError; - var MapWithDefault = __dependency2__.MapWithDefault; - var get = Ember.get; - var forEach = Ember.ArrayPolyfills.forEach; - - /** - The REST adapter allows your store to communicate with an HTTP server by - transmitting JSON via XHR. Most Ember.js apps that consume a JSON API - should use the REST adapter. - - This adapter is designed around the idea that the JSON exchanged with - the server should be conventional. - - ## JSON Structure - - The REST adapter expects the JSON returned from your server to follow - these conventions. - - ### Object Root - - The JSON payload should be an object that contains the record inside a - root property. For example, in response to a `GET` request for - `/posts/1`, the JSON should look like this: - - ```js - { - "post": { - "id": 1, - "title": "I'm Running to Reform the W3C's Tag", - "author": "Yehuda Katz" - } - } - ``` - - Similarly, in response to a `GET` request for `/posts`, the JSON should - look like this: - - ```js - { - "posts": [ - { - "id": 1, - "title": "I'm Running to Reform the W3C's Tag", - "author": "Yehuda Katz" - }, - { - "id": 2, - "title": "Rails is omakase", - "author": "D2H" - } - ] - } - ``` - - ### Conventional Names - - Attribute names in your JSON payload should be the camelCased versions of - the attributes in your Ember.js models. - - For example, if you have a `Person` model: - - ```js - App.Person = DS.Model.extend({ - firstName: DS.attr('string'), - lastName: DS.attr('string'), - occupation: DS.attr('string') - }); - ``` - - The JSON returned should look like this: - - ```js - { - "person": { - "id": 5, - "firstName": "Barack", - "lastName": "Obama", - "occupation": "President" - } - } - ``` - - ## Customization - - ### Endpoint path customization - - Endpoint paths can be prefixed with a `namespace` by setting the namespace - property on the adapter: - - ```js - DS.RESTAdapter.reopen({ - namespace: 'api/1' - }); - ``` - Requests for `App.Person` would now target `/api/1/people/1`. - - ### Host customization - - An adapter can target other hosts by setting the `host` property. - - ```js - DS.RESTAdapter.reopen({ - host: 'https://api.example.com' - }); - ``` - - ### Headers customization - - Some APIs require HTTP headers, e.g. to provide an API key. Arbitrary - headers can be set as key/value pairs on the `RESTAdapter`'s `headers` - object and Ember Data will send them along with each ajax request. - - - ```js - App.ApplicationAdapter = DS.RESTAdapter.extend({ - headers: { - "API_KEY": "secret key", - "ANOTHER_HEADER": "Some header value" - } - }); - ``` - - `headers` can also be used as a computed property to support dynamic - headers. In the example below, the `session` object has been - injected into an adapter by Ember's container. - - ```js - App.ApplicationAdapter = DS.RESTAdapter.extend({ - headers: function() { - return { - "API_KEY": this.get("session.authToken"), - "ANOTHER_HEADER": "Some header value" - }; - }.property("session.authToken") - }); - ``` - - In some cases, your dynamic headers may require data from some - object outside of Ember's observer system (for example - `document.cookie`). You can use the - [volatile](/api/classes/Ember.ComputedProperty.html#method_volatile) - function to set the property into a non-cached mode causing the headers to - be recomputed with every request. - - ```js - App.ApplicationAdapter = DS.RESTAdapter.extend({ - headers: function() { - return { - "API_KEY": Ember.get(document.cookie.match(/apiKey\=([^;]*)/), "1"), - "ANOTHER_HEADER": "Some header value" - }; - }.property().volatile() - }); - ``` - - @class RESTAdapter - @constructor - @namespace DS - @extends DS.Adapter - */ - __exports__["default"] = Adapter.extend({ - defaultSerializer: '-rest', - - /** - By default the RESTAdapter will send each find request coming from a `store.find` - or from accessing a relationship separately to the server. If your server supports passing - ids as a query string, you can set coalesceFindRequests to true to coalesce all find requests - within a single runloop. - - For example, if you have an initial payload of - ```javascript - post: { - id:1, - comments: [1,2] - } - ``` - - By default calling `post.get('comments')` will trigger the following requests(assuming the - comments haven't been loaded before): - - ``` - GET /comments/1 - GET /comments/2 - ``` - - If you set coalesceFindRequests to `true` it will instead trigger the following request: - - ``` - GET /comments?ids[]=1&ids[]=2 - ``` - - Setting coalesceFindRequests to `true` also works for `store.find` requests and `belongsTo` - relationships accessed within the same runloop. If you set `coalesceFindRequests: true` - - ```javascript - store.find('comment', 1); - store.find('comment', 2); - ``` - - will also send a request to: `GET /comments?ids[]=1&ids[]=2` - - Note: Requests coalescing rely on URL building strategy. So if you override `buildUrl` in your app - `groupRecordsForFindMany` more likely should be overriden as well in order for coalescing to work. - - @property coalesceFindRequests - @type {boolean} - */ - coalesceFindRequests: false, - - /** - Endpoint paths can be prefixed with a `namespace` by setting the namespace - property on the adapter: - - ```javascript - DS.RESTAdapter.reopen({ - namespace: 'api/1' - }); - ``` - - Requests for `App.Post` would now target `/api/1/post/`. - - @property namespace - @type {String} - */ - - /** - An adapter can target other hosts by setting the `host` property. - - ```javascript - DS.RESTAdapter.reopen({ - host: 'https://api.example.com' - }); - ``` - - Requests for `App.Post` would now target `https://api.example.com/post/`. - - @property host - @type {String} - */ - - /** - Some APIs require HTTP headers, e.g. to provide an API - key. Arbitrary headers can be set as key/value pairs on the - `RESTAdapter`'s `headers` object and Ember Data will send them - along with each ajax request. For dynamic headers see [headers - customization](/api/data/classes/DS.RESTAdapter.html#toc_headers-customization). - - ```javascript - App.ApplicationAdapter = DS.RESTAdapter.extend({ - headers: { - "API_KEY": "secret key", - "ANOTHER_HEADER": "Some header value" - } - }); - ``` - - @property headers - @type {Object} - */ - - /** - Called by the store in order to fetch the JSON for a given - type and ID. - - The `find` method makes an Ajax request to a URL computed by `buildURL`, and returns a - promise for the resulting payload. - - This method performs an HTTP `GET` request with the id provided as part of the query string. - - @method find - @param {DS.Store} store - @param {subclass of DS.Model} type - @param {String} id - @param {DS.Model} record - @return {Promise} promise - */ - find: function(store, type, id, record) { - return this.ajax(this.buildURL(type.typeKey, id, record), 'GET'); - }, - - /** - Called by the store in order to fetch a JSON array for all - of the records for a given type. - - The `findAll` method makes an Ajax (HTTP GET) request to a URL computed by `buildURL`, and returns a - promise for the resulting payload. - - @private - @method findAll - @param {DS.Store} store - @param {subclass of DS.Model} type - @param {String} sinceToken - @return {Promise} promise - */ - findAll: function(store, type, sinceToken) { - var query; - - if (sinceToken) { - query = { since: sinceToken }; - } - - return this.ajax(this.buildURL(type.typeKey), 'GET', { data: query }); - }, - - /** - Called by the store in order to fetch a JSON array for - the records that match a particular query. - - The `findQuery` method makes an Ajax (HTTP GET) request to a URL computed by `buildURL`, and returns a - promise for the resulting payload. - - The `query` argument is a simple JavaScript object that will be passed directly - to the server as parameters. - - @private - @method findQuery - @param {DS.Store} store - @param {subclass of DS.Model} type - @param {Object} query - @return {Promise} promise - */ - findQuery: function(store, type, query) { - return this.ajax(this.buildURL(type.typeKey), 'GET', { data: query }); - }, - - /** - Called by the store in order to fetch several records together if `coalesceFindRequests` is true - - For example, if the original payload looks like: - - ```js - { - "id": 1, - "title": "Rails is omakase", - "comments": [ 1, 2, 3 ] - } - ``` - - The IDs will be passed as a URL-encoded Array of IDs, in this form: - - ``` - ids[]=1&ids[]=2&ids[]=3 - ``` - - Many servers, such as Rails and PHP, will automatically convert this URL-encoded array - into an Array for you on the server-side. If you want to encode the - IDs, differently, just override this (one-line) method. - - The `findMany` method makes an Ajax (HTTP GET) request to a URL computed by `buildURL`, and returns a - promise for the resulting payload. - - @method findMany - @param {DS.Store} store - @param {subclass of DS.Model} type - @param {Array} ids - @param {Array} records - @return {Promise} promise - */ - findMany: function(store, type, ids, records) { - return this.ajax(this.buildURL(type.typeKey, ids, records), 'GET', { data: { ids: ids } }); - }, - - /** - Called by the store in order to fetch a JSON array for - the unloaded records in a has-many relationship that were originally - specified as a URL (inside of `links`). - - For example, if your original payload looks like this: - - ```js - { - "post": { - "id": 1, - "title": "Rails is omakase", - "links": { "comments": "/posts/1/comments" } - } - } - ``` - - This method will be called with the parent record and `/posts/1/comments`. - - The `findHasMany` method will make an Ajax (HTTP GET) request to the originally specified URL. - If the URL is host-relative (starting with a single slash), the - request will use the host specified on the adapter (if any). - - @method findHasMany - @param {DS.Store} store - @param {DS.Model} record - @param {String} url - @return {Promise} promise - */ - findHasMany: function(store, record, url, relationship) { - var host = get(this, 'host'); - var id = get(record, 'id'); - var type = record.constructor.typeKey; - - if (host && url.charAt(0) === '/' && url.charAt(1) !== '/') { - url = host + url; - } - - return this.ajax(this.urlPrefix(url, this.buildURL(type, id)), 'GET'); - }, - - /** - Called by the store in order to fetch a JSON array for - the unloaded records in a belongs-to relationship that were originally - specified as a URL (inside of `links`). - - For example, if your original payload looks like this: - - ```js - { - "person": { - "id": 1, - "name": "Tom Dale", - "links": { "group": "/people/1/group" } - } - } - ``` - - This method will be called with the parent record and `/people/1/group`. - - The `findBelongsTo` method will make an Ajax (HTTP GET) request to the originally specified URL. - - @method findBelongsTo - @param {DS.Store} store - @param {DS.Model} record - @param {String} url - @return {Promise} promise - */ - findBelongsTo: function(store, record, url, relationship) { - var id = get(record, 'id'); - var type = record.constructor.typeKey; - - return this.ajax(this.urlPrefix(url, this.buildURL(type, id)), 'GET'); - }, - - /** - Called by the store when a newly created record is - saved via the `save` method on a model record instance. - - The `createRecord` method serializes the record and makes an Ajax (HTTP POST) request - to a URL computed by `buildURL`. - - See `serialize` for information on how to customize the serialized form - of a record. - - @method createRecord - @param {DS.Store} store - @param {subclass of DS.Model} type - @param {DS.Model} record - @return {Promise} promise - */ - createRecord: function(store, type, record) { - var data = {}; - var serializer = store.serializerFor(type.typeKey); - - serializer.serializeIntoHash(data, type, record, { includeId: true }); - - return this.ajax(this.buildURL(type.typeKey, null, record), "POST", { data: data }); - }, - - /** - Called by the store when an existing record is saved - via the `save` method on a model record instance. - - The `updateRecord` method serializes the record and makes an Ajax (HTTP PUT) request - to a URL computed by `buildURL`. - - See `serialize` for information on how to customize the serialized form - of a record. - - @method updateRecord - @param {DS.Store} store - @param {subclass of DS.Model} type - @param {DS.Model} record - @return {Promise} promise - */ - updateRecord: function(store, type, record) { - var data = {}; - var serializer = store.serializerFor(type.typeKey); - - serializer.serializeIntoHash(data, type, record); - - var id = get(record, 'id'); - - return this.ajax(this.buildURL(type.typeKey, id, record), "PUT", { data: data }); - }, - - /** - Called by the store when a record is deleted. - - The `deleteRecord` method makes an Ajax (HTTP DELETE) request to a URL computed by `buildURL`. - - @method deleteRecord - @param {DS.Store} store - @param {subclass of DS.Model} type - @param {DS.Model} record - @return {Promise} promise - */ - deleteRecord: function(store, type, record) { - var id = get(record, 'id'); - - return this.ajax(this.buildURL(type.typeKey, id, record), "DELETE"); - }, - - /** - Builds a URL for a given type and optional ID. - - By default, it pluralizes the type's name (for example, 'post' - becomes 'posts' and 'person' becomes 'people'). To override the - pluralization see [pathForType](#method_pathForType). - - If an ID is specified, it adds the ID to the path generated - for the type, separated by a `/`. - - @method buildURL - @param {String} type - @param {String} id - @param {DS.Model} record - @return {String} url - */ - buildURL: function(type, id, record) { - var url = [], - host = get(this, 'host'), - prefix = this.urlPrefix(); - - if (type) { url.push(this.pathForType(type)); } - - //We might get passed in an array of ids from findMany - //in which case we don't want to modify the url, as the - //ids will be passed in through a query param - if (id && !Ember.isArray(id)) { url.push(encodeURIComponent(id)); } - - if (prefix) { url.unshift(prefix); } - - url = url.join('/'); - if (!host && url) { url = '/' + url; } - - return url; - }, - - /** - @method urlPrefix - @private - @param {String} path - @param {String} parentUrl - @return {String} urlPrefix - */ - urlPrefix: function(path, parentURL) { - var host = get(this, 'host'); - var namespace = get(this, 'namespace'); - var url = []; - - if (path) { - // Absolute path - if (path.charAt(0) === '/') { - if (host) { - path = path.slice(1); - url.push(host); - } - // Relative path - } else if (!/^http(s)?:\/\//.test(path)) { - url.push(parentURL); - } - } else { - if (host) { url.push(host); } - if (namespace) { url.push(namespace); } - } - - if (path) { - url.push(path); - } - - return url.join('/'); - }, - - _stripIDFromURL: function(store, record) { - var type = store.modelFor(record); - var url = this.buildURL(type.typeKey, record.get('id'), record); - - var expandedURL = url.split('/'); - //Case when the url is of the format ...something/:id - var lastSegment = expandedURL[ expandedURL.length - 1 ]; - var id = record.get('id'); - if (lastSegment === id) { - expandedURL[expandedURL.length - 1] = ""; - } else if(endsWith(lastSegment, '?id=' + id)) { - //Case when the url is of the format ...something?id=:id - expandedURL[expandedURL.length - 1] = lastSegment.substring(0, lastSegment.length - id.length - 1); - } - - return expandedURL.join('/'); - }, - - /** - Organize records into groups, each of which is to be passed to separate - calls to `findMany`. - - This implementation groups together records that have the same base URL but - differing ids. For example `/comments/1` and `/comments/2` will be grouped together - because we know findMany can coalesce them together as `/comments?ids[]=1&ids[]=2` - - It also supports urls where ids are passed as a query param, such as `/comments?id=1` - but not those where there is more than 1 query param such as `/comments?id=2&name=David` - Currently only the query param of `id` is supported. If you need to support others, please - override this or the `_stripIDFromURL` method. - - It does not group records that have differing base urls, such as for example: `/posts/1/comments/2` - and `/posts/2/comments/3` - - @method groupRecordsForFindMany - @param {Array} records - @return {Array} an array of arrays of records, each of which is to be - loaded separately by `findMany`. - */ - groupRecordsForFindMany: function (store, records) { - var groups = MapWithDefault.create({defaultValue: function(){return [];}}); - var adapter = this; - - forEach.call(records, function(record){ - var baseUrl = adapter._stripIDFromURL(store, record); - groups.get(baseUrl).push(record); - }); - - function splitGroupToFitInUrl(group, maxUrlLength) { - var baseUrl = adapter._stripIDFromURL(store, group[0]); - var idsSize = 0; - var splitGroups = [[]]; - - forEach.call(group, function(record) { - var additionalLength = '&ids[]='.length + record.get('id.length'); - if (baseUrl.length + idsSize + additionalLength >= maxUrlLength) { - idsSize = 0; - splitGroups.push([]); - } - - idsSize += additionalLength; - - var lastGroupIndex = splitGroups.length - 1; - splitGroups[lastGroupIndex].push(record); - }); - - return splitGroups; - } - - var groupsArray = []; - groups.forEach(function(group, key){ - // http://stackoverflow.com/questions/417142/what-is-the-maximum-length-of-a-url-in-different-browsers - var maxUrlLength = 2048; - var splitGroups = splitGroupToFitInUrl(group, maxUrlLength); - - forEach.call(splitGroups, function(splitGroup) { - groupsArray.push(splitGroup); - }); - }); - - return groupsArray; - }, - - /** - Determines the pathname for a given type. - - By default, it pluralizes the type's name (for example, - 'post' becomes 'posts' and 'person' becomes 'people'). - - ### Pathname customization - - For example if you have an object LineItem with an - endpoint of "/line_items/". - - ```js - App.ApplicationAdapter = DS.RESTAdapter.extend({ - pathForType: function(type) { - var decamelized = Ember.String.decamelize(type); - return Ember.String.pluralize(decamelized); - } - }); - ``` - - @method pathForType - @param {String} type - @return {String} path - **/ - pathForType: function(type) { - var camelized = Ember.String.camelize(type); - return Ember.String.pluralize(camelized); - }, - - /** - Takes an ajax response, and returns a relevant error. - - Returning a `DS.InvalidError` from this method will cause the - record to transition into the `invalid` state and make the - `errors` object available on the record. - - ```javascript - App.ApplicationAdapter = DS.RESTAdapter.extend({ - ajaxError: function(jqXHR) { - var error = this._super(jqXHR); - - if (jqXHR && jqXHR.status === 422) { - var jsonErrors = Ember.$.parseJSON(jqXHR.responseText)["errors"]; - - return new DS.InvalidError(jsonErrors); - } else { - return error; - } - } - }); - ``` - - Note: As a correctness optimization, the default implementation of - the `ajaxError` method strips out the `then` method from jquery's - ajax response (jqXHR). This is important because the jqXHR's - `then` method fulfills the promise with itself resulting in a - circular "thenable" chain which may cause problems for some - promise libraries. - - @method ajaxError - @param {Object} jqXHR - @param {Object} responseText - @return {Object} jqXHR - */ - ajaxError: function(jqXHR, responseText) { - if (jqXHR && typeof jqXHR === 'object') { - jqXHR.then = null; - } - - return jqXHR; - }, - - /** - Takes an ajax response, and returns the json payload. - - By default this hook just returns the jsonPayload passed to it. - You might want to override it in two cases: - - 1. Your API might return useful results in the request headers. - If you need to access these, you can override this hook to copy them - from jqXHR to the payload object so they can be processed in you serializer. - - - 2. Your API might return errors as successful responses with status code - 200 and an Errors text or object. You can return a DS.InvalidError from - this hook and it will automatically reject the promise and put your record - into the invald state. - - @method ajaxError - @param {Object} jqXHR - @param {Object} jsonPayload - @return {Object} jqXHR - */ - - ajaxSuccess: function(jqXHR, jsonPayload) { - return jsonPayload; - }, - - /** - Takes a URL, an HTTP method and a hash of data, and makes an - HTTP request. - - When the server responds with a payload, Ember Data will call into `extractSingle` - or `extractArray` (depending on whether the original query was for one record or - many records). - - By default, `ajax` method has the following behavior: - - * It sets the response `dataType` to `"json"` - * If the HTTP method is not `"GET"`, it sets the `Content-Type` to be - `application/json; charset=utf-8` - * If the HTTP method is not `"GET"`, it stringifies the data passed in. The - data is the serialized record in the case of a save. - * Registers success and failure handlers. - - @method ajax - @private - @param {String} url - @param {String} type The request type GET, POST, PUT, DELETE etc. - @param {Object} hash - @return {Promise} promise - */ - ajax: function(url, type, options) { - var adapter = this; - - return new Ember.RSVP.Promise(function(resolve, reject) { - var hash = adapter.ajaxOptions(url, type, options); - - hash.success = function(json, textStatus, jqXHR) { - json = adapter.ajaxSuccess(jqXHR, json); - if (json instanceof InvalidError) { - Ember.run(null, reject, json); - } else { - Ember.run(null, resolve, json); - } - }; - - hash.error = function(jqXHR, textStatus, errorThrown) { - Ember.run(null, reject, adapter.ajaxError(jqXHR, jqXHR.responseText)); - }; - - Ember.$.ajax(hash); - }, "DS: RESTAdapter#ajax " + type + " to " + url); - }, - - /** - @method ajaxOptions - @private - @param {String} url - @param {String} type The request type GET, POST, PUT, DELETE etc. - @param {Object} hash - @return {Object} hash - */ - ajaxOptions: function(url, type, options) { - var hash = options || {}; - hash.url = url; - hash.type = type; - hash.dataType = 'json'; - hash.context = this; - - if (hash.data && type !== 'GET') { - hash.contentType = 'application/json; charset=utf-8'; - hash.data = JSON.stringify(hash.data); - } - - var headers = get(this, 'headers'); - if (headers !== undefined) { - hash.beforeSend = function (xhr) { - forEach.call(Ember.keys(headers), function(key) { - xhr.setRequestHeader(key, headers[key]); - }); - }; - } - - return hash; - } - }); - - //From http://stackoverflow.com/questions/280634/endswith-in-javascript - function endsWith(string, suffix){ - if (typeof String.prototype.endsWith !== 'function') { - return string.indexOf(suffix, string.length - suffix.length) !== -1; - } else { - return string.endsWith(suffix); - } - } - }); -define("ember-data/core", - ["exports"], - function(__exports__) { - "use strict"; - /** - @module ember-data - */ - - /** - All Ember Data methods and functions are defined inside of this namespace. - - @class DS - @static - */ - var DS; - if ('undefined' === typeof DS) { - /** - @property VERSION - @type String - @default '1.0.0-beta.11' - @static - */ - DS = Ember.Namespace.create({ - VERSION: '1.0.0-beta.11' - }); - - if (Ember.libraries) { - Ember.libraries.registerCoreLibrary('Ember Data', DS.VERSION); - } - } - - __exports__["default"] = DS; - }); -define("ember-data/ember-initializer", - ["ember-data/setup-container"], - function(__dependency1__) { - "use strict"; - var setupContainer = __dependency1__["default"]; - - var K = Ember.K; - - /** - @module ember-data - */ - - /* - - This code initializes Ember-Data onto an Ember application. - - If an Ember.js developer defines a subclass of DS.Store on their application, - as `App.ApplicationStore` (or via a module system that resolves to `store:application`) - this code will automatically instantiate it and make it available on the - router. - - Additionally, after an application's controllers have been injected, they will - each have the store made available to them. - - For example, imagine an Ember.js application with the following classes: - - App.ApplicationStore = DS.Store.extend({ - adapter: 'custom' - }); - - App.PostsController = Ember.ArrayController.extend({ - // ... - }); - - When the application is initialized, `App.ApplicationStore` will automatically be - instantiated, and the instance of `App.PostsController` will have its `store` - property set to that instance. - - Note that this code will only be run if the `ember-application` package is - loaded. If Ember Data is being used in an environment other than a - typical application (e.g., node.js where only `ember-runtime` is available), - this code will be ignored. - */ - - Ember.onLoad('Ember.Application', function(Application) { - - Application.initializer({ - name: "ember-data", - initialize: setupContainer - }); - - // Deprecated initializers to satisfy old code that depended on them - - Application.initializer({ - name: "store", - after: "ember-data", - initialize: K - }); - - Application.initializer({ - name: "activeModelAdapter", - before: "store", - initialize: K - }); - - Application.initializer({ - name: "transforms", - before: "store", - initialize: K - }); - - Application.initializer({ - name: "data-adapter", - before: "store", - initialize: K - }); - - Application.initializer({ - name: "injectStore", - before: "store", - initialize: K - }); - }); - }); -define("ember-data/ext/date", - [], - function() { - "use strict"; - /** - @module ember-data - */ - - /** - Date.parse with progressive enhancement for ISO 8601 - - © 2011 Colin Snover - - Released under MIT license. - - @class Date - @namespace Ember - @static - */ - Ember.Date = Ember.Date || {}; - - var origParse = Date.parse, numericKeys = [ 1, 4, 5, 6, 7, 10, 11 ]; - - /** - @method parse - @param {Date} date - @return {Number} timestamp - */ - Ember.Date.parse = function (date) { - var timestamp, struct, minutesOffset = 0; - - // ES5 §15.9.4.2 states that the string should attempt to be parsed as a Date Time String Format string - // before falling back to any implementation-specific date parsing, so that’s what we do, even if native - // implementations could be faster - // 1 YYYY 2 MM 3 DD 4 HH 5 mm 6 ss 7 msec 8 Z 9 ± 10 tzHH 11 tzmm - if ((struct = /^(\d{4}|[+\-]\d{6})(?:-(\d{2})(?:-(\d{2}))?)?(?:T(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{3}))?)?(?:(Z)|([+\-])(\d{2})(?::(\d{2}))?)?)?$/.exec(date))) { - // avoid NaN timestamps caused by “undefined” values being passed to Date.UTC - for (var i = 0, k; (k = numericKeys[i]); ++i) { - struct[k] = +struct[k] || 0; - } - - // allow undefined days and months - struct[2] = (+struct[2] || 1) - 1; - struct[3] = +struct[3] || 1; - - if (struct[8] !== 'Z' && struct[9] !== undefined) { - minutesOffset = struct[10] * 60 + struct[11]; - - if (struct[9] === '+') { - minutesOffset = 0 - minutesOffset; - } - } - - timestamp = Date.UTC(struct[1], struct[2], struct[3], struct[4], struct[5] + minutesOffset, struct[6], struct[7]); - } - else { - timestamp = origParse ? origParse(date) : NaN; - } - - return timestamp; - }; - - if (Ember.EXTEND_PROTOTYPES === true || Ember.EXTEND_PROTOTYPES.Date) { - Date.parse = Ember.Date.parse; - } - }); -define("ember-data/initializers/data_adapter", - ["ember-data/system/debug/debug_adapter","exports"], - function(__dependency1__, __exports__) { - "use strict"; - var DebugAdapter = __dependency1__["default"]; - - /** - Configures a container with injections on Ember applications - for the Ember-Data store. Accepts an optional namespace argument. - - @method initializeStoreInjections - @param {Ember.Container} container - */ - __exports__["default"] = function initializeDebugAdapter(container){ - container.register('data-adapter:main', DebugAdapter); - }; - }); -define("ember-data/initializers/store", - ["ember-data/serializers","ember-data/adapters","ember-data/system/container_proxy","ember-data/system/store","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __exports__) { - "use strict"; - var JSONSerializer = __dependency1__.JSONSerializer; - var RESTSerializer = __dependency1__.RESTSerializer; - var RESTAdapter = __dependency2__.RESTAdapter; - var ContainerProxy = __dependency3__["default"]; - var Store = __dependency4__["default"]; - - /** - Configures a container for use with an Ember-Data - store. Accepts an optional namespace argument. - - @method initializeStore - @param {Ember.Container} container - @param {Object} [application] an application namespace - */ - __exports__["default"] = function initializeStore(container, application){ - Ember.deprecate('Specifying a custom Store for Ember Data on your global namespace as `App.Store` ' + - 'has been deprecated. Please use `App.ApplicationStore` instead.', !(application && application.Store)); - - container.register('store:main', container.lookupFactory('store:application') || (application && application.Store) || Store); - - // allow older names to be looked up - - var proxy = new ContainerProxy(container); - proxy.registerDeprecations([ - { deprecated: 'serializer:_default', valid: 'serializer:-default' }, - { deprecated: 'serializer:_rest', valid: 'serializer:-rest' }, - { deprecated: 'adapter:_rest', valid: 'adapter:-rest' } - ]); - - // new go forward paths - container.register('serializer:-default', JSONSerializer); - container.register('serializer:-rest', RESTSerializer); - container.register('adapter:-rest', RESTAdapter); - - // Eagerly generate the store so defaultStore is populated. - // TODO: Do this in a finisher hook - container.lookup('store:main'); - }; - }); -define("ember-data/initializers/store_injections", - ["exports"], - function(__exports__) { - "use strict"; - /** - Configures a container with injections on Ember applications - for the Ember-Data store. Accepts an optional namespace argument. - - @method initializeStoreInjections - @param {Ember.Container} container - */ - __exports__["default"] = function initializeStoreInjections(container){ - container.injection('controller', 'store', 'store:main'); - container.injection('route', 'store', 'store:main'); - container.injection('serializer', 'store', 'store:main'); - container.injection('data-adapter', 'store', 'store:main'); - }; - }); -define("ember-data/initializers/transforms", - ["ember-data/transforms","exports"], - function(__dependency1__, __exports__) { - "use strict"; - var BooleanTransform = __dependency1__.BooleanTransform; - var DateTransform = __dependency1__.DateTransform; - var StringTransform = __dependency1__.StringTransform; - var NumberTransform = __dependency1__.NumberTransform; - - /** - Configures a container for use with Ember-Data - transforms. - - @method initializeTransforms - @param {Ember.Container} container - */ - __exports__["default"] = function initializeTransforms(container){ - container.register('transform:boolean', BooleanTransform); - container.register('transform:date', DateTransform); - container.register('transform:number', NumberTransform); - container.register('transform:string', StringTransform); - }; - }); -define("ember-data/serializers", - ["ember-data/serializers/json_serializer","ember-data/serializers/rest_serializer","exports"], - function(__dependency1__, __dependency2__, __exports__) { - "use strict"; - var JSONSerializer = __dependency1__["default"]; - var RESTSerializer = __dependency2__["default"]; - - __exports__.JSONSerializer = JSONSerializer; - __exports__.RESTSerializer = RESTSerializer; - }); -define("ember-data/serializers/embedded_records_mixin", - ["exports"], - function(__exports__) { - "use strict"; - var get = Ember.get; - var forEach = Ember.EnumerableUtils.forEach; - var camelize = Ember.String.camelize; - - /** - ## Using Embedded Records - - `DS.EmbeddedRecordsMixin` supports serializing embedded records. - - To set up embedded records, include the mixin when extending a serializer - then define and configure embedded (model) relationships. - - Below is an example of a per-type serializer ('post' type). - - ```js - App.PostSerializer = DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, { - attrs: { - author: { embedded: 'always' }, - comments: { serialize: 'ids' } - } - }); - ``` - Note that this use of `{ embedded: 'always' }` is unrelated to - the `{ embedded: 'always' }` that is defined as an option on `DS.attr` as part of - defining a model while working with the ActiveModelSerializer. Nevertheless, - using `{ embedded: 'always' }` as an option to DS.attr is not a valid way to setup - embedded records. - - The `attrs` option for a resource `{ embedded: 'always' }` is shorthand for: - - ```js - { - serialize: 'records', - deserialize: 'records' - } - ``` - - ### Configuring Attrs - - A resource's `attrs` option may be set to use `ids`, `records` or false for the - `serialize` and `deserialize` settings. - - The `attrs` property can be set on the ApplicationSerializer or a per-type - serializer. - - In the case where embedded JSON is expected while extracting a payload (reading) - the setting is `deserialize: 'records'`, there is no need to use `ids` when - extracting as that is the default behavior without this mixin if you are using - the vanilla EmbeddedRecordsMixin. Likewise, to embed JSON in the payload while - serializing `serialize: 'records'` is the setting to use. There is an option of - not embedding JSON in the serialized payload by using `serialize: 'ids'`. If you - do not want the relationship sent at all, you can use `serialize: false`. - - - ### EmbeddedRecordsMixin defaults - If you do not overwrite `attrs` for a specific relationship, the `EmbeddedRecordsMixin` - will behave in the following way: - - BelongsTo: `{ serialize: 'id', deserialize: 'id' }` - HasMany: `{ serialize: false, deserialize: 'ids' }` - - ### Model Relationships - - Embedded records must have a model defined to be extracted and serialized. Note that - when defining any relationships on your model such as `belongsTo` and `hasMany`, you - should not both specify `async:true` and also indicate through the serializer's - `attrs` attribute that the related model should be embedded. If a model is - declared embedded, then do not use `async:true`. - - To successfully extract and serialize embedded records the model relationships - must be setup correcty See the - [defining relationships](/guides/models/defining-models/#toc_defining-relationships) - section of the **Defining Models** guide page. - - Records without an `id` property are not considered embedded records, model - instances must have an `id` property to be used with Ember Data. - - ### Example JSON payloads, Models and Serializers - - **When customizing a serializer it is important to grok what the customizations - are. Please read the docs for the methods this mixin provides, in case you need - to modify it to fit your specific needs.** - - For example review the docs for each method of this mixin: - * [normalize](/api/data/classes/DS.EmbeddedRecordsMixin.html#method_normalize) - * [serializeBelongsTo](/api/data/classes/DS.EmbeddedRecordsMixin.html#method_serializeBelongsTo) - * [serializeHasMany](/api/data/classes/DS.EmbeddedRecordsMixin.html#method_serializeHasMany) - - @class EmbeddedRecordsMixin - @namespace DS - */ - var EmbeddedRecordsMixin = Ember.Mixin.create({ - - /** - Normalize the record and recursively normalize/extract all the embedded records - while pushing them into the store as they are encountered - - A payload with an attr configured for embedded records needs to be extracted: - - ```js - { - "post": { - "id": "1" - "title": "Rails is omakase", - "comments": [{ - "id": "1", - "body": "Rails is unagi" - }, { - "id": "2", - "body": "Omakase O_o" - }] - } - } - ``` - @method normalize - @param {subclass of DS.Model} type - @param {Object} hash to be normalized - @param {String} key the hash has been referenced by - @return {Object} the normalized hash - **/ - normalize: function(type, hash, prop) { - var normalizedHash = this._super(type, hash, prop); - return extractEmbeddedRecords(this, this.store, type, normalizedHash); - }, - - keyForRelationship: function(key, type){ - if (this.hasDeserializeRecordsOption(key)) { - return this.keyForAttribute(key); - } else { - return this._super(key, type) || key; - } - }, - - /** - Serialize `belongsTo` relationship when it is configured as an embedded object. - - This example of an author model belongs to a post model: - - ```js - Post = DS.Model.extend({ - title: DS.attr('string'), - body: DS.attr('string'), - author: DS.belongsTo('author') - }); - - Author = DS.Model.extend({ - name: DS.attr('string'), - post: DS.belongsTo('post') - }); - ``` - - Use a custom (type) serializer for the post model to configure embedded author - - ```js - App.PostSerializer = DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, { - attrs: { - author: {embedded: 'always'} - } - }) - ``` - - A payload with an attribute configured for embedded records can serialize - the records together under the root attribute's payload: - - ```js - { - "post": { - "id": "1" - "title": "Rails is omakase", - "author": { - "id": "2" - "name": "dhh" - } - } - } - ``` - - @method serializeBelongsTo - @param {DS.Model} record - @param {Object} json - @param {Object} relationship - */ - serializeBelongsTo: function(record, json, relationship) { - var attr = relationship.key; - if (this.noSerializeOptionSpecified(attr)) { - this._super(record, json, relationship); - return; - } - var includeIds = this.hasSerializeIdsOption(attr); - var includeRecords = this.hasSerializeRecordsOption(attr); - var embeddedRecord = record.get(attr); - var key; - if (includeIds) { - key = this.keyForRelationship(attr, relationship.kind); - if (!embeddedRecord) { - json[key] = null; - } else { - json[key] = get(embeddedRecord, 'id'); - } - } else if (includeRecords) { - key = this.keyForAttribute(attr); - if (!embeddedRecord) { - json[key] = null; - } else { - json[key] = embeddedRecord.serialize({includeId: true}); - this.removeEmbeddedForeignKey(record, embeddedRecord, relationship, json[key]); - } - } - }, - - /** - Serialize `hasMany` relationship when it is configured as embedded objects. - - This example of a post model has many comments: - - ```js - Post = DS.Model.extend({ - title: DS.attr('string'), - body: DS.attr('string'), - comments: DS.hasMany('comment') - }); - - Comment = DS.Model.extend({ - body: DS.attr('string'), - post: DS.belongsTo('post') - }); - ``` - - Use a custom (type) serializer for the post model to configure embedded comments - - ```js - App.PostSerializer = DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, { - attrs: { - comments: {embedded: 'always'} - } - }) - ``` - - A payload with an attribute configured for embedded records can serialize - the records together under the root attribute's payload: - - ```js - { - "post": { - "id": "1" - "title": "Rails is omakase", - "body": "I want this for my ORM, I want that for my template language..." - "comments": [{ - "id": "1", - "body": "Rails is unagi" - }, { - "id": "2", - "body": "Omakase O_o" - }] - } - } - ``` - - The attrs options object can use more specific instruction for extracting and - serializing. When serializing, an option to embed `ids` or `records` can be set. - When extracting the only option is `records`. - - So `{embedded: 'always'}` is shorthand for: - `{serialize: 'records', deserialize: 'records'}` - - To embed the `ids` for a related object (using a hasMany relationship): - - ```js - App.PostSerializer = DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, { - attrs: { - comments: {serialize: 'ids', deserialize: 'records'} - } - }) - ``` - - ```js - { - "post": { - "id": "1" - "title": "Rails is omakase", - "body": "I want this for my ORM, I want that for my template language..." - "comments": ["1", "2"] - } - } - ``` - - @method serializeHasMany - @param {DS.Model} record - @param {Object} json - @param {Object} relationship - */ - serializeHasMany: function(record, json, relationship) { - var attr = relationship.key; - if (this.noSerializeOptionSpecified(attr)) { - this._super(record, json, relationship); - return; - } - var includeIds = this.hasSerializeIdsOption(attr); - var includeRecords = this.hasSerializeRecordsOption(attr); - var key; - if (includeIds) { - key = this.keyForRelationship(attr, relationship.kind); - json[key] = get(record, attr).mapBy('id'); - } else if (includeRecords) { - key = this.keyForAttribute(attr); - json[key] = get(record, attr).map(function(embeddedRecord) { - var serializedEmbeddedRecord = embeddedRecord.serialize({includeId: true}); - this.removeEmbeddedForeignKey(record, embeddedRecord, relationship, serializedEmbeddedRecord); - return serializedEmbeddedRecord; - }, this); - } - }, - - /** - When serializing an embedded record, modify the property (in the json payload) - that refers to the parent record (foreign key for relationship). - - Serializing a `belongsTo` relationship removes the property that refers to the - parent record - - Serializing a `hasMany` relationship does not remove the property that refers to - the parent record. - - @method removeEmbeddedForeignKey - @param {DS.Model} record - @param {DS.Model} embeddedRecord - @param {Object} relationship - @param {Object} json - */ - removeEmbeddedForeignKey: function (record, embeddedRecord, relationship, json) { - if (relationship.kind === 'hasMany') { - return; - } else if (relationship.kind === 'belongsTo') { - var parentRecord = record.constructor.inverseFor(relationship.key); - if (parentRecord) { - var name = parentRecord.name; - var embeddedSerializer = this.store.serializerFor(embeddedRecord.constructor); - var parentKey = embeddedSerializer.keyForRelationship(name, parentRecord.kind); - if (parentKey) { - delete json[parentKey]; - } - } - } - }, - - // checks config for attrs option to embedded (always) - serialize and deserialize - hasEmbeddedAlwaysOption: function (attr) { - var option = this.attrsOption(attr); - return option && option.embedded === 'always'; - }, - - // checks config for attrs option to serialize ids - hasSerializeRecordsOption: function(attr) { - var alwaysEmbed = this.hasEmbeddedAlwaysOption(attr); - var option = this.attrsOption(attr); - return alwaysEmbed || (option && (option.serialize === 'records')); - }, - - // checks config for attrs option to serialize records - hasSerializeIdsOption: function(attr) { - var option = this.attrsOption(attr); - return option && (option.serialize === 'ids' || option.serialize === 'id'); - }, - - // checks config for attrs option to serialize records - noSerializeOptionSpecified: function(attr) { - var option = this.attrsOption(attr); - return !(option && (option.serialize || option.embedded)); - }, - - // checks config for attrs option to deserialize records - // a defined option object for a resource is treated the same as - // `deserialize: 'records'` - hasDeserializeRecordsOption: function(attr) { - var alwaysEmbed = this.hasEmbeddedAlwaysOption(attr); - var option = this.attrsOption(attr); - return alwaysEmbed || (option && option.deserialize === 'records'); - }, - - attrsOption: function(attr) { - var attrs = this.get('attrs'); - return attrs && (attrs[camelize(attr)] || attrs[attr]); - } - }); - - // chooses a relationship kind to branch which function is used to update payload - // does not change payload if attr is not embedded - function extractEmbeddedRecords(serializer, store, type, partial) { - - type.eachRelationship(function(key, relationship) { - if (serializer.hasDeserializeRecordsOption(key)) { - var embeddedType = store.modelFor(relationship.type.typeKey); - if (relationship.kind === "hasMany") { - if (relationship.options.polymorphic) { - extractEmbeddedHasManyPolymorphic(store, key, partial); - } - else { - extractEmbeddedHasMany(store, key, embeddedType, partial); - } - } - if (relationship.kind === "belongsTo") { - extractEmbeddedBelongsTo(store, key, embeddedType, partial); - } - } - }); - - return partial; - } - - // handles embedding for `hasMany` relationship - function extractEmbeddedHasMany(store, key, embeddedType, hash) { - if (!hash[key]) { - return hash; - } - - var ids = []; - - var embeddedSerializer = store.serializerFor(embeddedType.typeKey); - forEach(hash[key], function(data) { - var embeddedRecord = embeddedSerializer.normalize(embeddedType, data, null); - store.push(embeddedType, embeddedRecord); - ids.push(embeddedRecord.id); - }); - - hash[key] = ids; - return hash; - } - - function extractEmbeddedHasManyPolymorphic(store, key, hash) { - if (!hash[key]) { - return hash; - } - - var ids = []; - - forEach(hash[key], function(data) { - var typeKey = data.type; - var embeddedSerializer = store.serializerFor(typeKey); - var embeddedType = store.modelFor(typeKey); - var primaryKey = get(embeddedSerializer, 'primaryKey'); - - var embeddedRecord = embeddedSerializer.normalize(embeddedType, data, null); - store.push(embeddedType, embeddedRecord); - ids.push({ id: embeddedRecord[primaryKey], type: typeKey }); - }); - - hash[key] = ids; - return hash; - } - - function extractEmbeddedBelongsTo(store, key, embeddedType, hash) { - if (!hash[key]) { - return hash; - } - - var embeddedSerializer = store.serializerFor(embeddedType.typeKey); - var embeddedRecord = embeddedSerializer.normalize(embeddedType, hash[key], null); - store.push(embeddedType, embeddedRecord); - - hash[key] = embeddedRecord.id; - //TODO Need to add a reference to the parent later so relationship works between both `belongsTo` records - return hash; - } - - __exports__["default"] = EmbeddedRecordsMixin; - }); -define("ember-data/serializers/json_serializer", - ["exports"], - function(__exports__) { - "use strict"; - var get = Ember.get; - var isNone = Ember.isNone; - var map = Ember.ArrayPolyfills.map; - var merge = Ember.merge; - - /** - In Ember Data a Serializer is used to serialize and deserialize - records when they are transferred in and out of an external source. - This process involves normalizing property names, transforming - attribute values and serializing relationships. - - For maximum performance Ember Data recommends you use the - [RESTSerializer](DS.RESTSerializer.html) or one of its subclasses. - - `JSONSerializer` is useful for simpler or legacy backends that may - not support the http://jsonapi.org/ spec. - - @class JSONSerializer - @namespace DS - */ - __exports__["default"] = Ember.Object.extend({ - /** - The primaryKey is used when serializing and deserializing - data. Ember Data always uses the `id` property to store the id of - the record. The external source may not always follow this - convention. In these cases it is useful to override the - primaryKey property to match the primaryKey of your external - store. - - Example - - ```javascript - App.ApplicationSerializer = DS.JSONSerializer.extend({ - primaryKey: '_id' - }); - ``` - - @property primaryKey - @type {String} - @default 'id' - */ - primaryKey: 'id', - - /** - The `attrs` object can be used to declare a simple mapping between - property names on `DS.Model` records and payload keys in the - serialized JSON object representing the record. An object with the - property `key` can also be used to designate the attribute's key on - the response payload. - - Example - - ```javascript - App.Person = DS.Model.extend({ - firstName: DS.attr('string'), - lastName: DS.attr('string'), - occupation: DS.attr('string'), - admin: DS.attr('boolean') - }); - - App.PersonSerializer = DS.JSONSerializer.extend({ - attrs: { - admin: 'is_admin', - occupation: {key: 'career'} - } - }); - ``` - - You can also remove attributes by setting the `serialize` key to - false in your mapping object. - - Example - - ```javascript - App.PersonSerializer = DS.JSONSerializer.extend({ - attrs: { - admin: {serialize: false}, - occupation: {key: 'career'} - } - }); - ``` - - When serialized: - - ```javascript - { - "career": "magician" - } - ``` - - Note that the `admin` is now not included in the payload. - - @property attrs - @type {Object} - */ - - /** - Given a subclass of `DS.Model` and a JSON object this method will - iterate through each attribute of the `DS.Model` and invoke the - `DS.Transform#deserialize` method on the matching property of the - JSON object. This method is typically called after the - serializer's `normalize` method. - - @method applyTransforms - @private - @param {subclass of DS.Model} type - @param {Object} data The data to transform - @return {Object} data The transformed data object - */ - applyTransforms: function(type, data) { - type.eachTransformedAttribute(function applyTransform(key, type) { - if (!data.hasOwnProperty(key)) { return; } - - var transform = this.transformFor(type); - data[key] = transform.deserialize(data[key]); - }, this); - - return data; - }, - - /** - Normalizes a part of the JSON payload returned by - the server. You should override this method, munge the hash - and call super if you have generic normalization to do. - - It takes the type of the record that is being normalized - (as a DS.Model class), the property where the hash was - originally found, and the hash to normalize. - - You can use this method, for example, to normalize underscored keys to camelized - or other general-purpose normalizations. - - Example - - ```javascript - App.ApplicationSerializer = DS.JSONSerializer.extend({ - normalize: function(type, hash) { - var fields = Ember.get(type, 'fields'); - fields.forEach(function(field) { - var payloadField = Ember.String.underscore(field); - if (field === payloadField) { return; } - - hash[field] = hash[payloadField]; - delete hash[payloadField]; - }); - return this._super.apply(this, arguments); - } - }); - ``` - - @method normalize - @param {subclass of DS.Model} type - @param {Object} hash - @return {Object} - */ - normalize: function(type, hash) { - if (!hash) { return hash; } - - this.normalizeId(hash); - this.normalizeAttributes(type, hash); - this.normalizeRelationships(type, hash); - - this.normalizeUsingDeclaredMapping(type, hash); - this.applyTransforms(type, hash); - return hash; - }, - - /** - You can use this method to normalize all payloads, regardless of whether they - represent single records or an array. - - For example, you might want to remove some extraneous data from the payload: - - ```js - App.ApplicationSerializer = DS.JSONSerializer.extend({ - normalizePayload: function(payload) { - delete payload.version; - delete payload.status; - return payload; - } - }); - ``` - - @method normalizePayload - @param {Object} payload - @return {Object} the normalized payload - */ - normalizePayload: function(payload) { - return payload; - }, - - /** - @method normalizeAttributes - @private - */ - normalizeAttributes: function(type, hash) { - var payloadKey; - - if (this.keyForAttribute) { - type.eachAttribute(function(key) { - payloadKey = this.keyForAttribute(key); - if (key === payloadKey) { return; } - if (!hash.hasOwnProperty(payloadKey)) { return; } - - hash[key] = hash[payloadKey]; - delete hash[payloadKey]; - }, this); - } - }, - - /** - @method normalizeRelationships - @private - */ - normalizeRelationships: function(type, hash) { - var payloadKey; - - if (this.keyForRelationship) { - type.eachRelationship(function(key, relationship) { - payloadKey = this.keyForRelationship(key, relationship.kind); - if (key === payloadKey) { return; } - if (!hash.hasOwnProperty(payloadKey)) { return; } - - hash[key] = hash[payloadKey]; - delete hash[payloadKey]; - }, this); - } - }, - - /** - @method normalizeUsingDeclaredMapping - @private - */ - normalizeUsingDeclaredMapping: function(type, hash) { - var attrs = get(this, 'attrs'), payloadKey, key; - - if (attrs) { - for (key in attrs) { - payloadKey = this._getMappedKey(key); - if (!hash.hasOwnProperty(payloadKey)) { continue; } - - if (payloadKey !== key) { - hash[key] = hash[payloadKey]; - delete hash[payloadKey]; - } - } - } - }, - - /** - @method normalizeId - @private - */ - normalizeId: function(hash) { - var primaryKey = get(this, 'primaryKey'); - - if (primaryKey === 'id') { return; } - - hash.id = hash[primaryKey]; - delete hash[primaryKey]; - }, - - /** - Looks up the property key that was set by the custom `attr` mapping - passed to the serializer. - - @method _getMappedKey - @private - @param {String} key - @return {String} key - */ - _getMappedKey: function(key) { - var attrs = get(this, 'attrs'); - var mappedKey; - if (attrs && attrs[key]) { - mappedKey = attrs[key]; - //We need to account for both the {title: 'post_title'} and - //{title: {key: 'post_title'}} forms - if (mappedKey.key){ - mappedKey = mappedKey.key; - } - if (typeof mappedKey === 'string'){ - key = mappedKey; - } - } - - return key; - }, - - /** - Check attrs.key.serialize property to inform if the `key` - can be serialized - - @method _canSerialize - @private - @param {String} key - @return {boolean} true if the key can be serialized - */ - _canSerialize: function(key) { - var attrs = get(this, 'attrs'); - - return !attrs || !attrs[key] || attrs[key].serialize !== false; - }, - - // SERIALIZE - /** - Called when a record is saved in order to convert the - record into JSON. - - By default, it creates a JSON object with a key for - each attribute and belongsTo relationship. - - For example, consider this model: - - ```javascript - App.Comment = DS.Model.extend({ - title: DS.attr(), - body: DS.attr(), - - author: DS.belongsTo('user') - }); - ``` - - The default serialization would create a JSON object like: - - ```javascript - { - "title": "Rails is unagi", - "body": "Rails? Omakase? O_O", - "author": 12 - } - ``` - - By default, attributes are passed through as-is, unless - you specified an attribute type (`DS.attr('date')`). If - you specify a transform, the JavaScript value will be - serialized when inserted into the JSON hash. - - By default, belongs-to relationships are converted into - IDs when inserted into the JSON hash. - - ## IDs - - `serialize` takes an options hash with a single option: - `includeId`. If this option is `true`, `serialize` will, - by default include the ID in the JSON object it builds. - - The adapter passes in `includeId: true` when serializing - a record for `createRecord`, but not for `updateRecord`. - - ## Customization - - Your server may expect a different JSON format than the - built-in serialization format. - - In that case, you can implement `serialize` yourself and - return a JSON hash of your choosing. - - ```javascript - App.PostSerializer = DS.JSONSerializer.extend({ - serialize: function(post, options) { - var json = { - POST_TTL: post.get('title'), - POST_BDY: post.get('body'), - POST_CMS: post.get('comments').mapBy('id') - } - - if (options.includeId) { - json.POST_ID_ = post.get('id'); - } - - return json; - } - }); - ``` - - ## Customizing an App-Wide Serializer - - If you want to define a serializer for your entire - application, you'll probably want to use `eachAttribute` - and `eachRelationship` on the record. - - ```javascript - App.ApplicationSerializer = DS.JSONSerializer.extend({ - serialize: function(record, options) { - var json = {}; - - record.eachAttribute(function(name) { - json[serverAttributeName(name)] = record.get(name); - }) - - record.eachRelationship(function(name, relationship) { - if (relationship.kind === 'hasMany') { - json[serverHasManyName(name)] = record.get(name).mapBy('id'); - } - }); - - if (options.includeId) { - json.ID_ = record.get('id'); - } - - return json; - } - }); - - function serverAttributeName(attribute) { - return attribute.underscore().toUpperCase(); - } - - function serverHasManyName(name) { - return serverAttributeName(name.singularize()) + "_IDS"; - } - ``` - - This serializer will generate JSON that looks like this: - - ```javascript - { - "TITLE": "Rails is omakase", - "BODY": "Yep. Omakase.", - "COMMENT_IDS": [ 1, 2, 3 ] - } - ``` - - ## Tweaking the Default JSON - - If you just want to do some small tweaks on the default JSON, - you can call super first and make the tweaks on the returned - JSON. - - ```javascript - App.PostSerializer = DS.JSONSerializer.extend({ - serialize: function(record, options) { - var json = this._super.apply(this, arguments); - - json.subject = json.title; - delete json.title; - - return json; - } - }); - ``` - - @method serialize - @param {subclass of DS.Model} record - @param {Object} options - @return {Object} json - */ - serialize: function(record, options) { - var json = {}; - - if (options && options.includeId) { - var id = get(record, 'id'); - - if (id) { - json[get(this, 'primaryKey')] = id; - } - } - - record.eachAttribute(function(key, attribute) { - this.serializeAttribute(record, json, key, attribute); - }, this); - - record.eachRelationship(function(key, relationship) { - if (relationship.kind === 'belongsTo') { - this.serializeBelongsTo(record, json, relationship); - } else if (relationship.kind === 'hasMany') { - this.serializeHasMany(record, json, relationship); - } - }, this); - - return json; - }, - - /** - You can use this method to customize how a serialized record is added to the complete - JSON hash to be sent to the server. By default the JSON Serializer does not namespace - the payload and just sends the raw serialized JSON object. - If your server expects namespaced keys, you should consider using the RESTSerializer. - Otherwise you can override this method to customize how the record is added to the hash. - - For example, your server may expect underscored root objects. - - ```js - App.ApplicationSerializer = DS.RESTSerializer.extend({ - serializeIntoHash: function(data, type, record, options) { - var root = Ember.String.decamelize(type.typeKey); - data[root] = this.serialize(record, options); - } - }); - ``` - - @method serializeIntoHash - @param {Object} hash - @param {subclass of DS.Model} type - @param {DS.Model} record - @param {Object} options - */ - serializeIntoHash: function(hash, type, record, options) { - merge(hash, this.serialize(record, options)); - }, - - /** - `serializeAttribute` can be used to customize how `DS.attr` - properties are serialized - - For example if you wanted to ensure all your attributes were always - serialized as properties on an `attributes` object you could - write: - - ```javascript - App.ApplicationSerializer = DS.JSONSerializer.extend({ - serializeAttribute: function(record, json, key, attributes) { - json.attributes = json.attributes || {}; - this._super(record, json.attributes, key, attributes); - } - }); - ``` - - @method serializeAttribute - @param {DS.Model} record - @param {Object} json - @param {String} key - @param {Object} attribute - */ - serializeAttribute: function(record, json, key, attribute) { - var type = attribute.type; - - if (this._canSerialize(key)) { - var value = get(record, key); - if (type) { - var transform = this.transformFor(type); - value = transform.serialize(value); - } - - // if provided, use the mapping provided by `attrs` in - // the serializer - var payloadKey = this._getMappedKey(key); - - if (payloadKey === key && this.keyForAttribute) { - payloadKey = this.keyForAttribute(key); - } - - json[payloadKey] = value; - } - }, - - /** - `serializeBelongsTo` can be used to customize how `DS.belongsTo` - properties are serialized. - - Example - - ```javascript - App.PostSerializer = DS.JSONSerializer.extend({ - serializeBelongsTo: function(record, json, relationship) { - var key = relationship.key; - - var belongsTo = get(record, key); - - key = this.keyForRelationship ? this.keyForRelationship(key, "belongsTo") : key; - - json[key] = Ember.isNone(belongsTo) ? belongsTo : belongsTo.toJSON(); - } - }); - ``` - - @method serializeBelongsTo - @param {DS.Model} record - @param {Object} json - @param {Object} relationship - */ - serializeBelongsTo: function(record, json, relationship) { - var key = relationship.key; - - if (this._canSerialize(key)) { - var belongsTo = get(record, key); - - // if provided, use the mapping provided by `attrs` in - // the serializer - var payloadKey = this._getMappedKey(key); - if (payloadKey === key && this.keyForRelationship) { - payloadKey = this.keyForRelationship(key, "belongsTo"); - } - - //Need to check whether the id is there for new&async records - if (isNone(belongsTo) || isNone(get(belongsTo, 'id'))) { - json[payloadKey] = null; - } else { - json[payloadKey] = get(belongsTo, 'id'); - } - - if (relationship.options.polymorphic) { - this.serializePolymorphicType(record, json, relationship); - } - } - }, - - /** - `serializeHasMany` can be used to customize how `DS.hasMany` - properties are serialized. - - Example - - ```javascript - App.PostSerializer = DS.JSONSerializer.extend({ - serializeHasMany: function(record, json, relationship) { - var key = relationship.key; - if (key === 'comments') { - return; - } else { - this._super.apply(this, arguments); - } - } - }); - ``` - - @method serializeHasMany - @param {DS.Model} record - @param {Object} json - @param {Object} relationship - */ - serializeHasMany: function(record, json, relationship) { - var key = relationship.key; - - if (this._canSerialize(key)) { - var payloadKey; - - // if provided, use the mapping provided by `attrs` in - // the serializer - payloadKey = this._getMappedKey(key); - if (payloadKey === key && this.keyForRelationship) { - payloadKey = this.keyForRelationship(key, "hasMany"); - } - - var relationshipType = record.constructor.determineRelationshipType(relationship); - - if (relationshipType === 'manyToNone' || relationshipType === 'manyToMany') { - json[payloadKey] = get(record, key).mapBy('id'); - // TODO support for polymorphic manyToNone and manyToMany relationships - } - } - }, - - /** - You can use this method to customize how polymorphic objects are - serialized. Objects are considered to be polymorphic if - `{polymorphic: true}` is pass as the second argument to the - `DS.belongsTo` function. - - Example - - ```javascript - App.CommentSerializer = DS.JSONSerializer.extend({ - serializePolymorphicType: function(record, json, relationship) { - var key = relationship.key, - belongsTo = get(record, key); - key = this.keyForAttribute ? this.keyForAttribute(key) : key; - - if (Ember.isNone(belongsTo)) { - json[key + "_type"] = null; - } else { - json[key + "_type"] = belongsTo.constructor.typeKey; - } - } - }); - ``` - - @method serializePolymorphicType - @param {DS.Model} record - @param {Object} json - @param {Object} relationship - */ - serializePolymorphicType: Ember.K, - - // EXTRACT - - /** - The `extract` method is used to deserialize payload data from the - server. By default the `JSONSerializer` does not push the records - into the store. However records that subclass `JSONSerializer` - such as the `RESTSerializer` may push records into the store as - part of the extract call. - - This method delegates to a more specific extract method based on - the `requestType`. - - Example - - ```javascript - var get = Ember.get; - socket.on('message', function(message) { - var modelName = message.model; - var data = message.data; - var type = store.modelFor(modelName); - var serializer = store.serializerFor(type.typeKey); - var record = serializer.extract(store, type, data, get(data, 'id'), 'single'); - store.push(modelName, record); - }); - ``` - - @method extract - @param {DS.Store} store - @param {subclass of DS.Model} type - @param {Object} payload - @param {String or Number} id - @param {String} requestType - @return {Object} json The deserialized payload - */ - extract: function(store, type, payload, id, requestType) { - this.extractMeta(store, type, payload); - - var specificExtract = "extract" + requestType.charAt(0).toUpperCase() + requestType.substr(1); - return this[specificExtract](store, type, payload, id, requestType); - }, - - /** - `extractFindAll` is a hook into the extract method used when a - call is made to `DS.Store#findAll`. By default this method is an - alias for [extractArray](#method_extractArray). - - @method extractFindAll - @param {DS.Store} store - @param {subclass of DS.Model} type - @param {Object} payload - @param {String or Number} id - @param {String} requestType - @return {Array} array An array of deserialized objects - */ - extractFindAll: function(store, type, payload, id, requestType){ - return this.extractArray(store, type, payload, id, requestType); - }, - /** - `extractFindQuery` is a hook into the extract method used when a - call is made to `DS.Store#findQuery`. By default this method is an - alias for [extractArray](#method_extractArray). - - @method extractFindQuery - @param {DS.Store} store - @param {subclass of DS.Model} type - @param {Object} payload - @param {String or Number} id - @param {String} requestType - @return {Array} array An array of deserialized objects - */ - extractFindQuery: function(store, type, payload, id, requestType){ - return this.extractArray(store, type, payload, id, requestType); - }, - /** - `extractFindMany` is a hook into the extract method used when a - call is made to `DS.Store#findMany`. By default this method is - alias for [extractArray](#method_extractArray). - - @method extractFindMany - @param {DS.Store} store - @param {subclass of DS.Model} type - @param {Object} payload - @param {String or Number} id - @param {String} requestType - @return {Array} array An array of deserialized objects - */ - extractFindMany: function(store, type, payload, id, requestType){ - return this.extractArray(store, type, payload, id, requestType); - }, - /** - `extractFindHasMany` is a hook into the extract method used when a - call is made to `DS.Store#findHasMany`. By default this method is - alias for [extractArray](#method_extractArray). - - @method extractFindHasMany - @param {DS.Store} store - @param {subclass of DS.Model} type - @param {Object} payload - @param {String or Number} id - @param {String} requestType - @return {Array} array An array of deserialized objects - */ - extractFindHasMany: function(store, type, payload, id, requestType){ - return this.extractArray(store, type, payload, id, requestType); - }, - - /** - `extractCreateRecord` is a hook into the extract method used when a - call is made to `DS.Store#createRecord`. By default this method is - alias for [extractSave](#method_extractSave). - - @method extractCreateRecord - @param {DS.Store} store - @param {subclass of DS.Model} type - @param {Object} payload - @param {String or Number} id - @param {String} requestType - @return {Object} json The deserialized payload - */ - extractCreateRecord: function(store, type, payload, id, requestType) { - return this.extractSave(store, type, payload, id, requestType); - }, - /** - `extractUpdateRecord` is a hook into the extract method used when - a call is made to `DS.Store#update`. By default this method is alias - for [extractSave](#method_extractSave). - - @method extractUpdateRecord - @param {DS.Store} store - @param {subclass of DS.Model} type - @param {Object} payload - @param {String or Number} id - @param {String} requestType - @return {Object} json The deserialized payload - */ - extractUpdateRecord: function(store, type, payload, id, requestType) { - return this.extractSave(store, type, payload, id, requestType); - }, - /** - `extractDeleteRecord` is a hook into the extract method used when - a call is made to `DS.Store#deleteRecord`. By default this method is - alias for [extractSave](#method_extractSave). - - @method extractDeleteRecord - @param {DS.Store} store - @param {subclass of DS.Model} type - @param {Object} payload - @param {String or Number} id - @param {String} requestType - @return {Object} json The deserialized payload - */ - extractDeleteRecord: function(store, type, payload, id, requestType) { - return this.extractSave(store, type, payload, id, requestType); - }, - - /** - `extractFind` is a hook into the extract method used when - a call is made to `DS.Store#find`. By default this method is - alias for [extractSingle](#method_extractSingle). - - @method extractFind - @param {DS.Store} store - @param {subclass of DS.Model} type - @param {Object} payload - @param {String or Number} id - @param {String} requestType - @return {Object} json The deserialized payload - */ - extractFind: function(store, type, payload, id, requestType) { - return this.extractSingle(store, type, payload, id, requestType); - }, - /** - `extractFindBelongsTo` is a hook into the extract method used when - a call is made to `DS.Store#findBelongsTo`. By default this method is - alias for [extractSingle](#method_extractSingle). - - @method extractFindBelongsTo - @param {DS.Store} store - @param {subclass of DS.Model} type - @param {Object} payload - @param {String or Number} id - @param {String} requestType - @return {Object} json The deserialized payload - */ - extractFindBelongsTo: function(store, type, payload, id, requestType) { - return this.extractSingle(store, type, payload, id, requestType); - }, - /** - `extractSave` is a hook into the extract method used when a call - is made to `DS.Model#save`. By default this method is alias - for [extractSingle](#method_extractSingle). - - @method extractSave - @param {DS.Store} store - @param {subclass of DS.Model} type - @param {Object} payload - @param {String or Number} id - @param {String} requestType - @return {Object} json The deserialized payload - */ - extractSave: function(store, type, payload, id, requestType) { - return this.extractSingle(store, type, payload, id, requestType); - }, - - /** - `extractSingle` is used to deserialize a single record returned - from the adapter. - - Example - - ```javascript - App.PostSerializer = DS.JSONSerializer.extend({ - extractSingle: function(store, type, payload) { - payload.comments = payload._embedded.comment; - delete payload._embedded; - - return this._super(store, type, payload); - }, - }); - ``` - - @method extractSingle - @param {DS.Store} store - @param {subclass of DS.Model} type - @param {Object} payload - @param {String or Number} id - @param {String} requestType - @return {Object} json The deserialized payload - */ - extractSingle: function(store, type, payload, id, requestType) { - payload = this.normalizePayload(payload); - return this.normalize(type, payload); - }, - - /** - `extractArray` is used to deserialize an array of records - returned from the adapter. - - Example - - ```javascript - App.PostSerializer = DS.JSONSerializer.extend({ - extractArray: function(store, type, payload) { - return payload.map(function(json) { - return this.extractSingle(store, type, json); - }, this); - } - }); - ``` - - @method extractArray - @param {DS.Store} store - @param {subclass of DS.Model} type - @param {Object} payload - @param {String or Number} id - @param {String} requestType - @return {Array} array An array of deserialized objects - */ - extractArray: function(store, type, arrayPayload, id, requestType) { - var normalizedPayload = this.normalizePayload(arrayPayload); - var serializer = this; - - return map.call(normalizedPayload, function(singlePayload) { - return serializer.normalize(type, singlePayload); - }); - }, - - /** - `extractMeta` is used to deserialize any meta information in the - adapter payload. By default Ember Data expects meta information to - be located on the `meta` property of the payload object. - - Example - - ```javascript - App.PostSerializer = DS.JSONSerializer.extend({ - extractMeta: function(store, type, payload) { - if (payload && payload._pagination) { - store.metaForType(type, payload._pagination); - delete payload._pagination; - } - } - }); - ``` - - @method extractMeta - @param {DS.Store} store - @param {subclass of DS.Model} type - @param {Object} payload - */ - extractMeta: function(store, type, payload) { - if (payload && payload.meta) { - store.metaForType(type, payload.meta); - delete payload.meta; - } - }, - - /** - `keyForAttribute` can be used to define rules for how to convert an - attribute name in your model to a key in your JSON. - - Example - - ```javascript - App.ApplicationSerializer = DS.RESTSerializer.extend({ - keyForAttribute: function(attr) { - return Ember.String.underscore(attr).toUpperCase(); - } - }); - ``` - - @method keyForAttribute - @param {String} key - @return {String} normalized key - */ - keyForAttribute: function(key){ - return key; - }, - - /** - `keyForRelationship` can be used to define a custom key when - serializing relationship properties. By default `JSONSerializer` - does not provide an implementation of this method. - - Example - - ```javascript - App.PostSerializer = DS.JSONSerializer.extend({ - keyForRelationship: function(key, relationship) { - return 'rel_' + Ember.String.underscore(key); - } - }); - ``` - - @method keyForRelationship - @param {String} key - @param {String} relationship type - @return {String} normalized key - */ - - keyForRelationship: function(key, type){ - return key; - }, - - // HELPERS - - /** - @method transformFor - @private - @param {String} attributeType - @param {Boolean} skipAssertion - @return {DS.Transform} transform - */ - transformFor: function(attributeType, skipAssertion) { - var transform = this.container.lookup('transform:' + attributeType); - Ember.assert("Unable to find transform for '" + attributeType + "'", skipAssertion || !!transform); - return transform; - } - }); - }); -define("ember-data/serializers/rest_serializer", - ["ember-data/serializers/json_serializer","ember-inflector/system/string","exports"], - function(__dependency1__, __dependency2__, __exports__) { - "use strict"; - /** - @module ember-data - */ - - var JSONSerializer = __dependency1__["default"]; - var get = Ember.get; - var forEach = Ember.ArrayPolyfills.forEach; - var map = Ember.ArrayPolyfills.map; - var camelize = Ember.String.camelize; - - var singularize = __dependency2__.singularize; - - function coerceId(id) { - return id == null ? null : id + ''; - } - - /** - Normally, applications will use the `RESTSerializer` by implementing - the `normalize` method and individual normalizations under - `normalizeHash`. - - This allows you to do whatever kind of munging you need, and is - especially useful if your server is inconsistent and you need to - do munging differently for many different kinds of responses. - - See the `normalize` documentation for more information. - - ## Across the Board Normalization - - There are also a number of hooks that you might find useful to define - across-the-board rules for your payload. These rules will be useful - if your server is consistent, or if you're building an adapter for - an infrastructure service, like Parse, and want to encode service - conventions. - - For example, if all of your keys are underscored and all-caps, but - otherwise consistent with the names you use in your models, you - can implement across-the-board rules for how to convert an attribute - name in your model to a key in your JSON. - - ```js - App.ApplicationSerializer = DS.RESTSerializer.extend({ - keyForAttribute: function(attr) { - return Ember.String.underscore(attr).toUpperCase(); - } - }); - ``` - - You can also implement `keyForRelationship`, which takes the name - of the relationship as the first parameter, and the kind of - relationship (`hasMany` or `belongsTo`) as the second parameter. - - @class RESTSerializer - @namespace DS - @extends DS.JSONSerializer - */ - var RESTSerializer = JSONSerializer.extend({ - /** - If you want to do normalizations specific to some part of the payload, you - can specify those under `normalizeHash`. - - For example, given the following json where the the `IDs` under - `"comments"` are provided as `_id` instead of `id`. - - ```javascript - { - "post": { - "id": 1, - "title": "Rails is omakase", - "comments": [ 1, 2 ] - }, - "comments": [{ - "_id": 1, - "body": "FIRST" - }, { - "_id": 2, - "body": "Rails is unagi" - }] - } - ``` - - You use `normalizeHash` to normalize just the comments: - - ```javascript - App.PostSerializer = DS.RESTSerializer.extend({ - normalizeHash: { - comments: function(hash) { - hash.id = hash._id; - delete hash._id; - return hash; - } - } - }); - ``` - - The key under `normalizeHash` is usually just the original key - that was in the original payload. However, key names will be - impacted by any modifications done in the `normalizePayload` - method. The `DS.RESTSerializer`'s default implementation makes no - changes to the payload keys. - - @property normalizeHash - @type {Object} - @default undefined - */ - - /** - Normalizes a part of the JSON payload returned by - the server. You should override this method, munge the hash - and call super if you have generic normalization to do. - - It takes the type of the record that is being normalized - (as a DS.Model class), the property where the hash was - originally found, and the hash to normalize. - - For example, if you have a payload that looks like this: - - ```js - { - "post": { - "id": 1, - "title": "Rails is omakase", - "comments": [ 1, 2 ] - }, - "comments": [{ - "id": 1, - "body": "FIRST" - }, { - "id": 2, - "body": "Rails is unagi" - }] - } - ``` - - The `normalize` method will be called three times: - - * With `App.Post`, `"posts"` and `{ id: 1, title: "Rails is omakase", ... }` - * With `App.Comment`, `"comments"` and `{ id: 1, body: "FIRST" }` - * With `App.Comment`, `"comments"` and `{ id: 2, body: "Rails is unagi" }` - - You can use this method, for example, to normalize underscored keys to camelized - or other general-purpose normalizations. - - If you want to do normalizations specific to some part of the payload, you - can specify those under `normalizeHash`. - - For example, if the `IDs` under `"comments"` are provided as `_id` instead of - `id`, you can specify how to normalize just the comments: - - ```js - App.PostSerializer = DS.RESTSerializer.extend({ - normalizeHash: { - comments: function(hash) { - hash.id = hash._id; - delete hash._id; - return hash; - } - } - }); - ``` - - The key under `normalizeHash` is just the original key that was in the original - payload. - - @method normalize - @param {subclass of DS.Model} type - @param {Object} hash - @param {String} prop - @return {Object} - */ - normalize: function(type, hash, prop) { - this.normalizeId(hash); - this.normalizeAttributes(type, hash); - this.normalizeRelationships(type, hash); - - this.normalizeUsingDeclaredMapping(type, hash); - - if (this.normalizeHash && this.normalizeHash[prop]) { - this.normalizeHash[prop](hash); - } - - this.applyTransforms(type, hash); - return hash; - }, - - - /** - Called when the server has returned a payload representing - a single record, such as in response to a `find` or `save`. - - It is your opportunity to clean up the server's response into the normalized - form expected by Ember Data. - - If you want, you can just restructure the top-level of your payload, and - do more fine-grained normalization in the `normalize` method. - - For example, if you have a payload like this in response to a request for - post 1: - - ```js - { - "id": 1, - "title": "Rails is omakase", - - "_embedded": { - "comment": [{ - "_id": 1, - "comment_title": "FIRST" - }, { - "_id": 2, - "comment_title": "Rails is unagi" - }] - } - } - ``` - - You could implement a serializer that looks like this to get your payload - into shape: - - ```js - App.PostSerializer = DS.RESTSerializer.extend({ - // First, restructure the top-level so it's organized by type - extractSingle: function(store, type, payload, id) { - var comments = payload._embedded.comment; - delete payload._embedded; - - payload = { comments: comments, post: payload }; - return this._super(store, type, payload, id); - }, - - normalizeHash: { - // Next, normalize individual comments, which (after `extract`) - // are now located under `comments` - comments: function(hash) { - hash.id = hash._id; - hash.title = hash.comment_title; - delete hash._id; - delete hash.comment_title; - return hash; - } - } - }) - ``` - - When you call super from your own implementation of `extractSingle`, the - built-in implementation will find the primary record in your normalized - payload and push the remaining records into the store. - - The primary record is the single hash found under `post` or the first - element of the `posts` array. - - The primary record has special meaning when the record is being created - for the first time or updated (`createRecord` or `updateRecord`). In - particular, it will update the properties of the record that was saved. - - @method extractSingle - @param {DS.Store} store - @param {subclass of DS.Model} primaryType - @param {Object} payload - @param {String} recordId - @return {Object} the primary response to the original request - */ - extractSingle: function(store, primaryType, rawPayload, recordId) { - var payload = this.normalizePayload(rawPayload); - var primaryTypeName = primaryType.typeKey; - var primaryRecord; - - for (var prop in payload) { - var typeName = this.typeForRoot(prop); - if (!store.modelFactoryFor(typeName)){ - Ember.warn(this.warnMessageNoModelForKey(prop, typeName), false); - continue; - } - var type = store.modelFor(typeName); - var isPrimary = type.typeKey === primaryTypeName; - var value = payload[prop]; - - // legacy support for singular resources - if (isPrimary && Ember.typeOf(value) !== "array" ) { - primaryRecord = this.normalize(primaryType, value, prop); - continue; - } - - /*jshint loopfunc:true*/ - forEach.call(value, function(hash) { - var typeName = this.typeForRoot(prop); - var type = store.modelFor(typeName); - var typeSerializer = store.serializerFor(type); - - hash = typeSerializer.normalize(type, hash, prop); - - var isFirstCreatedRecord = isPrimary && !recordId && !primaryRecord; - var isUpdatedRecord = isPrimary && coerceId(hash.id) === recordId; - - // find the primary record. - // - // It's either: - // * the record with the same ID as the original request - // * in the case of a newly created record that didn't have an ID, the first - // record in the Array - if (isFirstCreatedRecord || isUpdatedRecord) { - primaryRecord = hash; - } else { - store.push(typeName, hash); - } - }, this); - } - - return primaryRecord; - }, - - /** - Called when the server has returned a payload representing - multiple records, such as in response to a `findAll` or `findQuery`. - - It is your opportunity to clean up the server's response into the normalized - form expected by Ember Data. - - If you want, you can just restructure the top-level of your payload, and - do more fine-grained normalization in the `normalize` method. - - For example, if you have a payload like this in response to a request for - all posts: - - ```js - { - "_embedded": { - "post": [{ - "id": 1, - "title": "Rails is omakase" - }, { - "id": 2, - "title": "The Parley Letter" - }], - "comment": [{ - "_id": 1, - "comment_title": "Rails is unagi" - "post_id": 1 - }, { - "_id": 2, - "comment_title": "Don't tread on me", - "post_id": 2 - }] - } - } - ``` - - You could implement a serializer that looks like this to get your payload - into shape: - - ```js - App.PostSerializer = DS.RESTSerializer.extend({ - // First, restructure the top-level so it's organized by type - // and the comments are listed under a post's `comments` key. - extractArray: function(store, type, payload) { - var posts = payload._embedded.post; - var comments = []; - var postCache = {}; - - posts.forEach(function(post) { - post.comments = []; - postCache[post.id] = post; - }); - - payload._embedded.comment.forEach(function(comment) { - comments.push(comment); - postCache[comment.post_id].comments.push(comment); - delete comment.post_id; - }); - - payload = { comments: comments, posts: payload }; - - return this._super(store, type, payload); - }, - - normalizeHash: { - // Next, normalize individual comments, which (after `extract`) - // are now located under `comments` - comments: function(hash) { - hash.id = hash._id; - hash.title = hash.comment_title; - delete hash._id; - delete hash.comment_title; - return hash; - } - } - }) - ``` - - When you call super from your own implementation of `extractArray`, the - built-in implementation will find the primary array in your normalized - payload and push the remaining records into the store. - - The primary array is the array found under `posts`. - - The primary record has special meaning when responding to `findQuery` - or `findHasMany`. In particular, the primary array will become the - list of records in the record array that kicked off the request. - - If your primary array contains secondary (embedded) records of the same type, - you cannot place these into the primary array `posts`. Instead, place the - secondary items into an underscore prefixed property `_posts`, which will - push these items into the store and will not affect the resulting query. - - @method extractArray - @param {DS.Store} store - @param {subclass of DS.Model} primaryType - @param {Object} payload - @return {Array} The primary array that was returned in response - to the original query. - */ - extractArray: function(store, primaryType, rawPayload) { - var payload = this.normalizePayload(rawPayload); - var primaryTypeName = primaryType.typeKey; - var primaryArray; - - for (var prop in payload) { - var typeKey = prop; - var forcedSecondary = false; - - if (prop.charAt(0) === '_') { - forcedSecondary = true; - typeKey = prop.substr(1); - } - - var typeName = this.typeForRoot(typeKey); - if (!store.modelFactoryFor(typeName)) { - Ember.warn(this.warnMessageNoModelForKey(prop, typeName), false); - continue; - } - var type = store.modelFor(typeName); - var typeSerializer = store.serializerFor(type); - var isPrimary = (!forcedSecondary && (type.typeKey === primaryTypeName)); - - /*jshint loopfunc:true*/ - var normalizedArray = map.call(payload[prop], function(hash) { - return typeSerializer.normalize(type, hash, prop); - }, this); - - if (isPrimary) { - primaryArray = normalizedArray; - } else { - store.pushMany(typeName, normalizedArray); - } - } - - return primaryArray; - }, - - /** - This method allows you to push a payload containing top-level - collections of records organized per type. - - ```js - { - "posts": [{ - "id": "1", - "title": "Rails is omakase", - "author", "1", - "comments": [ "1" ] - }], - "comments": [{ - "id": "1", - "body": "FIRST" - }], - "users": [{ - "id": "1", - "name": "@d2h" - }] - } - ``` - - It will first normalize the payload, so you can use this to push - in data streaming in from your server structured the same way - that fetches and saves are structured. - - @method pushPayload - @param {DS.Store} store - @param {Object} payload - */ - pushPayload: function(store, rawPayload) { - var payload = this.normalizePayload(rawPayload); - - for (var prop in payload) { - var typeName = this.typeForRoot(prop); - if (!store.modelFactoryFor(typeName, prop)){ - Ember.warn(this.warnMessageNoModelForKey(prop, typeName), false); - continue; - } - var type = store.modelFor(typeName); - var typeSerializer = store.serializerFor(type); - - /*jshint loopfunc:true*/ - var normalizedArray = map.call(Ember.makeArray(payload[prop]), function(hash) { - return typeSerializer.normalize(type, hash, prop); - }, this); - - store.pushMany(typeName, normalizedArray); - } - }, - - /** - This method is used to convert each JSON root key in the payload - into a typeKey that it can use to look up the appropriate model for - that part of the payload. By default the typeKey for a model is its - name in camelCase, so if your JSON root key is 'fast-car' you would - use typeForRoot to convert it to 'fastCar' so that Ember Data finds - the `FastCar` model. - - If you diverge from this norm you should also consider changes to - store._normalizeTypeKey as well. - - For example, your server may return prefixed root keys like so: - - ```js - { - "response-fast-car": { - "id": "1", - "name": "corvette" - } - } - ``` - - In order for Ember Data to know that the model corresponding to - the 'response-fast-car' hash is `FastCar` (typeKey: 'fastCar'), - you can override typeForRoot to convert 'response-fast-car' to - 'fastCar' like so: - - ```js - App.ApplicationSerializer = DS.RESTSerializer.extend({ - typeForRoot: function(root) { - // 'response-fast-car' should become 'fast-car' - var subRoot = root.substring(9); - - // _super normalizes 'fast-car' to 'fastCar' - return this._super(subRoot); - } - }); - ``` - - @method typeForRoot - @param {String} key - @return {String} the model's typeKey - */ - typeForRoot: function(key) { - return camelize(singularize(key)); - }, - - // SERIALIZE - - /** - Called when a record is saved in order to convert the - record into JSON. - - By default, it creates a JSON object with a key for - each attribute and belongsTo relationship. - - For example, consider this model: - - ```js - App.Comment = DS.Model.extend({ - title: DS.attr(), - body: DS.attr(), - - author: DS.belongsTo('user') - }); - ``` - - The default serialization would create a JSON object like: - - ```js - { - "title": "Rails is unagi", - "body": "Rails? Omakase? O_O", - "author": 12 - } - ``` - - By default, attributes are passed through as-is, unless - you specified an attribute type (`DS.attr('date')`). If - you specify a transform, the JavaScript value will be - serialized when inserted into the JSON hash. - - By default, belongs-to relationships are converted into - IDs when inserted into the JSON hash. - - ## IDs - - `serialize` takes an options hash with a single option: - `includeId`. If this option is `true`, `serialize` will, - by default include the ID in the JSON object it builds. - - The adapter passes in `includeId: true` when serializing - a record for `createRecord`, but not for `updateRecord`. - - ## Customization - - Your server may expect a different JSON format than the - built-in serialization format. - - In that case, you can implement `serialize` yourself and - return a JSON hash of your choosing. - - ```js - App.PostSerializer = DS.RESTSerializer.extend({ - serialize: function(post, options) { - var json = { - POST_TTL: post.get('title'), - POST_BDY: post.get('body'), - POST_CMS: post.get('comments').mapBy('id') - } - - if (options.includeId) { - json.POST_ID_ = post.get('id'); - } - - return json; - } - }); - ``` - - ## Customizing an App-Wide Serializer - - If you want to define a serializer for your entire - application, you'll probably want to use `eachAttribute` - and `eachRelationship` on the record. - - ```js - App.ApplicationSerializer = DS.RESTSerializer.extend({ - serialize: function(record, options) { - var json = {}; - - record.eachAttribute(function(name) { - json[serverAttributeName(name)] = record.get(name); - }) - - record.eachRelationship(function(name, relationship) { - if (relationship.kind === 'hasMany') { - json[serverHasManyName(name)] = record.get(name).mapBy('id'); - } - }); - - if (options.includeId) { - json.ID_ = record.get('id'); - } - - return json; - } - }); - - function serverAttributeName(attribute) { - return attribute.underscore().toUpperCase(); - } - - function serverHasManyName(name) { - return serverAttributeName(name.singularize()) + "_IDS"; - } - ``` - - This serializer will generate JSON that looks like this: - - ```js - { - "TITLE": "Rails is omakase", - "BODY": "Yep. Omakase.", - "COMMENT_IDS": [ 1, 2, 3 ] - } - ``` - - ## Tweaking the Default JSON - - If you just want to do some small tweaks on the default JSON, - you can call super first and make the tweaks on the returned - JSON. - - ```js - App.PostSerializer = DS.RESTSerializer.extend({ - serialize: function(record, options) { - var json = this._super(record, options); - - json.subject = json.title; - delete json.title; - - return json; - } - }); - ``` - - @method serialize - @param {subclass of DS.Model} record - @param {Object} options - @return {Object} json - */ - serialize: function(record, options) { - return this._super.apply(this, arguments); - }, - - /** - You can use this method to customize the root keys serialized into the JSON. - By default the REST Serializer sends the typeKey of a model, which is a camelized - version of the name. - - For example, your server may expect underscored root objects. - - ```js - App.ApplicationSerializer = DS.RESTSerializer.extend({ - serializeIntoHash: function(data, type, record, options) { - var root = Ember.String.decamelize(type.typeKey); - data[root] = this.serialize(record, options); - } - }); - ``` - - @method serializeIntoHash - @param {Object} hash - @param {subclass of DS.Model} type - @param {DS.Model} record - @param {Object} options - */ - serializeIntoHash: function(hash, type, record, options) { - hash[type.typeKey] = this.serialize(record, options); - }, - - /** - You can use this method to customize how polymorphic objects are serialized. - By default the JSON Serializer creates the key by appending `Type` to - the attribute and value from the model's camelcased model name. - - @method serializePolymorphicType - @param {DS.Model} record - @param {Object} json - @param {Object} relationship - */ - serializePolymorphicType: function(record, json, relationship) { - var key = relationship.key; - var belongsTo = get(record, key); - key = this.keyForAttribute ? this.keyForAttribute(key) : key; - if (Ember.isNone(belongsTo)) { - json[key + "Type"] = null; - } else { - json[key + "Type"] = Ember.String.camelize(belongsTo.constructor.typeKey); - } - } - }); - - Ember.runInDebug(function(){ - RESTSerializer.reopen({ - warnMessageNoModelForKey: function(prop, typeKey){ - return 'Encountered "' + prop + '" in payload, but no model was found for model name "' + typeKey + '" (resolved model name using ' + this.constructor.toString() + '.typeForRoot("' + prop + '"))'; - } - }); - }); - - __exports__["default"] = RESTSerializer; - }); -define("ember-data/setup-container", - ["ember-data/initializers/store","ember-data/initializers/transforms","ember-data/initializers/store_injections","ember-data/initializers/data_adapter","activemodel-adapter/setup-container","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __exports__) { - "use strict"; - var initializeStore = __dependency1__["default"]; - var initializeTransforms = __dependency2__["default"]; - var initializeStoreInjections = __dependency3__["default"]; - var initializeDataAdapter = __dependency4__["default"]; - var setupActiveModelContainer = __dependency5__["default"]; - - __exports__["default"] = function setupContainer(container, application){ - // application is not a required argument. This ensures - // testing setups can setup a container without booting an - // entire ember application. - - initializeDataAdapter(container, application); - initializeTransforms(container, application); - initializeStoreInjections(container, application); - initializeStore(container, application); - setupActiveModelContainer(container, application); - }; - }); -define("ember-data/system/adapter", - ["exports"], - function(__exports__) { - "use strict"; - /** - @module ember-data - */ - - var get = Ember.get; - - var errorProps = [ - 'description', - 'fileName', - 'lineNumber', - 'message', - 'name', - 'number', - 'stack' - ]; - - /** - A `DS.InvalidError` is used by an adapter to signal the external API - was unable to process a request because the content was not - semantically correct or meaningful per the API. Usually this means a - record failed some form of server side validation. When a promise - from an adapter is rejected with a `DS.InvalidError` the record will - transition to the `invalid` state and the errors will be set to the - `errors` property on the record. - - Example - - ```javascript - App.ApplicationAdapter = DS.RESTAdapter.extend({ - ajaxError: function(jqXHR) { - var error = this._super(jqXHR); - - if (jqXHR && jqXHR.status === 422) { - var jsonErrors = Ember.$.parseJSON(jqXHR.responseText)["errors"]; - return new DS.InvalidError(jsonErrors); - } else { - return error; - } - } - }); - ``` - - The `DS.InvalidError` must be constructed with a single object whose - keys are the invalid model properties, and whose values are the - corresponding error messages. For example: - - ```javascript - return new DS.InvalidError({ - length: 'Must be less than 15', - name: 'Must not be blank - }); - ``` - - @class InvalidError - @namespace DS - */ - function InvalidError(errors) { - var tmp = Error.prototype.constructor.call(this, "The backend rejected the commit because it was invalid: " + Ember.inspect(errors)); - this.errors = errors; - - for (var i=0, l=errorProps.length; i 0; i--) { - proxyPair = proxyPairs[i - 1]; - deprecated = proxyPair['deprecated']; - valid = proxyPair['valid']; - - this.registerDeprecation(deprecated, valid); - } - }; - - __exports__["default"] = ContainerProxy; - }); -define("ember-data/system/debug", - ["ember-data/system/debug/debug_info","ember-data/system/debug/debug_adapter","exports"], - function(__dependency1__, __dependency2__, __exports__) { - "use strict"; - /** - @module ember-data - */ - - var DebugAdapter = __dependency2__["default"]; - - __exports__["default"] = DebugAdapter; - }); -define("ember-data/system/debug/debug_adapter", - ["ember-data/system/model","exports"], - function(__dependency1__, __exports__) { - "use strict"; - /** - @module ember-data - */ - var Model = __dependency1__.Model; - var get = Ember.get; - var capitalize = Ember.String.capitalize; - var underscore = Ember.String.underscore; - - /** - Extend `Ember.DataAdapter` with ED specific code. - - @class DebugAdapter - @namespace DS - @extends Ember.DataAdapter - @private - */ - __exports__["default"] = Ember.DataAdapter.extend({ - getFilters: function() { - return [ - { name: 'isNew', desc: 'New' }, - { name: 'isModified', desc: 'Modified' }, - { name: 'isClean', desc: 'Clean' } - ]; - }, - - detect: function(klass) { - return klass !== Model && Model.detect(klass); - }, - - columnsForType: function(type) { - var columns = [{ - name: 'id', - desc: 'Id' - }]; - var count = 0; - var self = this; - get(type, 'attributes').forEach(function(meta, name) { - if (count++ > self.attributeLimit) { return false; } - var desc = capitalize(underscore(name).replace('_', ' ')); - columns.push({ name: name, desc: desc }); - }); - return columns; - }, - - getRecords: function(type) { - return this.get('store').all(type); - }, - - getRecordColumnValues: function(record) { - var self = this, count = 0; - var columnValues = { id: get(record, 'id') }; - - record.eachAttribute(function(key) { - if (count++ > self.attributeLimit) { - return false; - } - var value = get(record, key); - columnValues[key] = value; - }); - return columnValues; - }, - - getRecordKeywords: function(record) { - var keywords = []; - var keys = Ember.A(['id']); - record.eachAttribute(function(key) { - keys.push(key); - }); - keys.forEach(function(key) { - keywords.push(get(record, key)); - }); - return keywords; - }, - - getRecordFilterValues: function(record) { - return { - isNew: record.get('isNew'), - isModified: record.get('isDirty') && !record.get('isNew'), - isClean: !record.get('isDirty') - }; - }, - - getRecordColor: function(record) { - var color = 'black'; - if (record.get('isNew')) { - color = 'green'; - } else if (record.get('isDirty')) { - color = 'blue'; - } - return color; - }, - - observeRecord: function(record, recordUpdated) { - var releaseMethods = Ember.A(), self = this; - var keysToObserve = Ember.A(['id', 'isNew', 'isDirty']); - - record.eachAttribute(function(key) { - keysToObserve.push(key); - }); - - keysToObserve.forEach(function(key) { - var handler = function() { - recordUpdated(self.wrapRecord(record)); - }; - Ember.addObserver(record, key, handler); - releaseMethods.push(function() { - Ember.removeObserver(record, key, handler); - }); - }); - - var release = function() { - releaseMethods.forEach(function(fn) { fn(); } ); - }; - - return release; - } - - }); - }); -define("ember-data/system/debug/debug_info", - ["ember-data/system/model","exports"], - function(__dependency1__, __exports__) { - "use strict"; - var Model = __dependency1__.Model; - - Model.reopen({ - - /** - Provides info about the model for debugging purposes - by grouping the properties into more semantic groups. - - Meant to be used by debugging tools such as the Chrome Ember Extension. - - - Groups all attributes in "Attributes" group. - - Groups all belongsTo relationships in "Belongs To" group. - - Groups all hasMany relationships in "Has Many" group. - - Groups all flags in "Flags" group. - - Flags relationship CPs as expensive properties. - - @method _debugInfo - @for DS.Model - @private - */ - _debugInfo: function() { - var attributes = ['id'], - relationships = { belongsTo: [], hasMany: [] }, - expensiveProperties = []; - - this.eachAttribute(function(name, meta) { - attributes.push(name); - }, this); - - this.eachRelationship(function(name, relationship) { - relationships[relationship.kind].push(name); - expensiveProperties.push(name); - }); - - var groups = [ - { - name: 'Attributes', - properties: attributes, - expand: true - }, - { - name: 'Belongs To', - properties: relationships.belongsTo, - expand: true - }, - { - name: 'Has Many', - properties: relationships.hasMany, - expand: true - }, - { - name: 'Flags', - properties: ['isLoaded', 'isDirty', 'isSaving', 'isDeleted', 'isError', 'isNew', 'isValid'] - } - ]; - - return { - propertyInfo: { - // include all other mixins / properties (not just the grouped ones) - includeOtherProperties: true, - groups: groups, - // don't pre-calculate unless cached - expensiveProperties: expensiveProperties - } - }; - } - }); - - __exports__["default"] = Model; - }); -define("ember-data/system/map", - ["exports"], - function(__exports__) { - "use strict"; - /** - * Polyfill Ember.Map behavior for Ember <= 1.7 - * This can probably be removed before 1.0 final - */ - var mapForEach, deleteFn; - - function OrderedSet(){ - Ember.OrderedSet.apply(this, arguments); - } - - function Map() { - Ember.Map.apply(this, arguments); - } - - function MapWithDefault(){ - Ember.MapWithDefault.apply(this, arguments); - } - - var testMap = Ember.Map.create(); - testMap.set('key', 'value'); - - var usesOldBehavior = false; - - testMap.forEach(function(value, key){ - usesOldBehavior = value === 'key' && key === 'value'; - }); - - Map.prototype = Object.create(Ember.Map.prototype); - MapWithDefault.prototype = Object.create(Ember.MapWithDefault.prototype); - OrderedSet.prototype = Object.create(Ember.OrderedSet.prototype); - - OrderedSet.create = function(){ - return new OrderedSet(); - }; - - /** - * returns a function that calls the original - * callback function in the correct order. - * if we are in pre-Ember.1.8 land, Map/MapWithDefault - * forEach calls with key, value, in that order. - * >= 1.8 forEach is called with the order value, key as per - * the ES6 spec. - */ - function translate(valueKeyOrderedCallback){ - return function(key, value){ - valueKeyOrderedCallback.call(this, value, key); - }; - } - - // old, non ES6 compliant behavior - if (usesOldBehavior){ - mapForEach = function(callback, thisArg){ - this.__super$forEach(translate(callback), thisArg); - }; - - /* alias to remove */ - deleteFn = function(thing){ - this.remove(thing); - }; - - Map.prototype.__super$forEach = Ember.Map.prototype.forEach; - Map.prototype.forEach = mapForEach; - Map.prototype["delete"] = deleteFn; - - MapWithDefault.prototype.forEach = mapForEach; - MapWithDefault.prototype.__super$forEach = Ember.MapWithDefault.prototype.forEach; - MapWithDefault.prototype["delete"] = deleteFn; - - OrderedSet.prototype["delete"] = deleteFn; - } - - MapWithDefault.constructor = MapWithDefault; - Map.constructor = Map; - - MapWithDefault.create = function(options){ - if (options) { - return new MapWithDefault(options); - } else { - return new Map(); - } - }; - - Map.create = function(){ - return new this.constructor(); - }; - - __exports__["default"] = Map; - __exports__.Map = Map; - __exports__.MapWithDefault = MapWithDefault; - __exports__.OrderedSet = OrderedSet; - }); -define("ember-data/system/model", - ["ember-data/system/model/model","ember-data/system/model/attributes","ember-data/system/model/states","ember-data/system/model/errors","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __exports__) { - "use strict"; - /** - @module ember-data - */ - - var Model = __dependency1__["default"]; - var attr = __dependency2__["default"]; - var RootState = __dependency3__["default"]; - var Errors = __dependency4__["default"]; - - __exports__.Model = Model; - __exports__.RootState = RootState; - __exports__.attr = attr; - __exports__.Errors = Errors; - }); -define("ember-data/system/model/attributes", - ["ember-data/system/model/model","ember-data/system/map","exports"], - function(__dependency1__, __dependency2__, __exports__) { - "use strict"; - var Model = __dependency1__["default"]; - var Map = __dependency2__.Map; - - /** - @module ember-data - */ - - var get = Ember.get; - - /** - @class Model - @namespace DS - */ - Model.reopenClass({ - /** - A map whose keys are the attributes of the model (properties - described by DS.attr) and whose values are the meta object for the - property. - - Example - - ```javascript - - App.Person = DS.Model.extend({ - firstName: attr('string'), - lastName: attr('string'), - birthday: attr('date') - }); - - var attributes = Ember.get(App.Person, 'attributes') - - attributes.forEach(function(name, meta) { - console.log(name, meta); - }); - - // prints: - // firstName {type: "string", isAttribute: true, options: Object, parentType: function, name: "firstName"} - // lastName {type: "string", isAttribute: true, options: Object, parentType: function, name: "lastName"} - // birthday {type: "date", isAttribute: true, options: Object, parentType: function, name: "birthday"} - ``` - - @property attributes - @static - @type {Ember.Map} - @readOnly - */ - attributes: Ember.computed(function() { - var map = Map.create(); - - this.eachComputedProperty(function(name, meta) { - if (meta.isAttribute) { - Ember.assert("You may not set `id` as an attribute on your model. Please remove any lines that look like: `id: DS.attr('')` from " + this.toString(), name !== 'id'); - - meta.name = name; - map.set(name, meta); - } - }); - - return map; - }).readOnly(), - - /** - A map whose keys are the attributes of the model (properties - described by DS.attr) and whose values are type of transformation - applied to each attribute. This map does not include any - attributes that do not have an transformation type. - - Example - - ```javascript - App.Person = DS.Model.extend({ - firstName: attr(), - lastName: attr('string'), - birthday: attr('date') - }); - - var transformedAttributes = Ember.get(App.Person, 'transformedAttributes') - - transformedAttributes.forEach(function(field, type) { - console.log(field, type); - }); - - // prints: - // lastName string - // birthday date - ``` - - @property transformedAttributes - @static - @type {Ember.Map} - @readOnly - */ - transformedAttributes: Ember.computed(function() { - var map = Map.create(); - - this.eachAttribute(function(key, meta) { - if (meta.type) { - map.set(key, meta.type); - } - }); - - return map; - }).readOnly(), - - /** - Iterates through the attributes of the model, calling the passed function on each - attribute. - - The callback method you provide should have the following signature (all - parameters are optional): - - ```javascript - function(name, meta); - ``` - - - `name` the name of the current property in the iteration - - `meta` the meta object for the attribute property in the iteration - - Note that in addition to a callback, you can also pass an optional target - object that will be set as `this` on the context. - - Example - - ```javascript - App.Person = DS.Model.extend({ - firstName: attr('string'), - lastName: attr('string'), - birthday: attr('date') - }); - - App.Person.eachAttribute(function(name, meta) { - console.log(name, meta); - }); - - // prints: - // firstName {type: "string", isAttribute: true, options: Object, parentType: function, name: "firstName"} - // lastName {type: "string", isAttribute: true, options: Object, parentType: function, name: "lastName"} - // birthday {type: "date", isAttribute: true, options: Object, parentType: function, name: "birthday"} - ``` - - @method eachAttribute - @param {Function} callback The callback to execute - @param {Object} [target] The target object to use - @static - */ - eachAttribute: function(callback, binding) { - get(this, 'attributes').forEach(function(meta, name) { - callback.call(binding, name, meta); - }, binding); - }, - - /** - Iterates through the transformedAttributes of the model, calling - the passed function on each attribute. Note the callback will not be - called for any attributes that do not have an transformation type. - - The callback method you provide should have the following signature (all - parameters are optional): - - ```javascript - function(name, type); - ``` - - - `name` the name of the current property in the iteration - - `type` a string containing the name of the type of transformed - applied to the attribute - - Note that in addition to a callback, you can also pass an optional target - object that will be set as `this` on the context. - - Example - - ```javascript - App.Person = DS.Model.extend({ - firstName: attr(), - lastName: attr('string'), - birthday: attr('date') - }); - - App.Person.eachTransformedAttribute(function(name, type) { - console.log(name, type); - }); - - // prints: - // lastName string - // birthday date - ``` - - @method eachTransformedAttribute - @param {Function} callback The callback to execute - @param {Object} [target] The target object to use - @static - */ - eachTransformedAttribute: function(callback, binding) { - get(this, 'transformedAttributes').forEach(function(type, name) { - callback.call(binding, name, type); - }); - } - }); - - - Model.reopen({ - eachAttribute: function(callback, binding) { - this.constructor.eachAttribute(callback, binding); - } - }); - - function getDefaultValue(record, options, key) { - if (typeof options.defaultValue === "function") { - return options.defaultValue.apply(null, arguments); - } else { - return options.defaultValue; - } - } - - function hasValue(record, key) { - return record._attributes.hasOwnProperty(key) || - record._inFlightAttributes.hasOwnProperty(key) || - record._data.hasOwnProperty(key); - } - - function getValue(record, key) { - if (record._attributes.hasOwnProperty(key)) { - return record._attributes[key]; - } else if (record._inFlightAttributes.hasOwnProperty(key)) { - return record._inFlightAttributes[key]; - } else { - return record._data[key]; - } - } - - /** - `DS.attr` defines an attribute on a [DS.Model](/api/data/classes/DS.Model.html). - By default, attributes are passed through as-is, however you can specify an - optional type to have the value automatically transformed. - Ember Data ships with four basic transform types: `string`, `number`, - `boolean` and `date`. You can define your own transforms by subclassing - [DS.Transform](/api/data/classes/DS.Transform.html). - - Note that you cannot use `attr` to define an attribute of `id`. - - `DS.attr` takes an optional hash as a second parameter, currently - supported options are: - - - `defaultValue`: Pass a string or a function to be called to set the attribute - to a default value if none is supplied. - - Example - - ```javascript - var attr = DS.attr; - - App.User = DS.Model.extend({ - username: attr('string'), - email: attr('string'), - verified: attr('boolean', {defaultValue: false}) - }); - ``` - - @namespace - @method attr - @for DS - @param {String} type the attribute type - @param {Object} options a hash of options - @return {Attribute} - */ - - __exports__["default"] = function attr(type, options) { - options = options || {}; - - var meta = { - type: type, - isAttribute: true, - options: options - }; - - return Ember.computed('data', function(key, value) { - if (arguments.length > 1) { - Ember.assert("You may not set `id` as an attribute on your model. Please remove any lines that look like: `id: DS.attr('')` from " + this.constructor.toString(), key !== 'id'); - var oldValue = getValue(this, key); - - if (value !== oldValue) { - // Add the new value to the changed attributes hash; it will get deleted by - // the 'didSetProperty' handler if it is no different from the original value - this._attributes[key] = value; - - this.send('didSetProperty', { - name: key, - oldValue: oldValue, - originalValue: this._data[key], - value: value - }); - } - - return value; - } else if (hasValue(this, key)) { - return getValue(this, key); - } else { - return getDefaultValue(this, options, key); - } - - // `data` is never set directly. However, it may be - // invalidated from the state manager's setData - // event. - }).meta(meta); - }; - }); -define("ember-data/system/model/errors", - ["ember-data/system/map","exports"], - function(__dependency1__, __exports__) { - "use strict"; - var get = Ember.get; - var isEmpty = Ember.isEmpty; - var map = Ember.EnumerableUtils.map; - - var MapWithDefault = __dependency1__.MapWithDefault; - - /** - @module ember-data - */ - - /** - Holds validation errors for a given record organized by attribute names. - - Every DS.Model has an `errors` property that is an instance of - `DS.Errors`. This can be used to display validation error - messages returned from the server when a `record.save()` rejects. - This works automatically with `DS.ActiveModelAdapter`, but you - can implement [ajaxError](api/data/classes/DS.RESTAdapter.html#method_ajaxError) - in other adapters as well. - - For Example, if you had an `User` model that looked like this: - - ```javascript - App.User = DS.Model.extend({ - username: attr('string'), - email: attr('string') - }); - ``` - And you attempted to save a record that did not validate on the backend. - - ```javascript - var user = store.createRecord('user', { - username: 'tomster', - email: 'invalidEmail' - }); - user.save(); - ``` - - Your backend data store might return a response that looks like - this. This response will be used to populate the error object. - - ```javascript - { - "errors": { - "username": ["This username is already taken!"], - "email": ["Doesn't look like a valid email."] - } - } - ``` - - Errors can be displayed to the user by accessing their property name - or using the `messages` property to get an array of all errors. - - ```handlebars - {{#each errors.messages}} -
- {{message}} -
- {{/each}} - - - {{#each errors.username}} -
- {{message}} -
- {{/each}} - - - {{#each errors.email}} -
- {{message}} -
- {{/each}} - ``` - - @class Errors - @namespace DS - @extends Ember.Object - @uses Ember.Enumerable - @uses Ember.Evented - */ - __exports__["default"] = Ember.Object.extend(Ember.Enumerable, Ember.Evented, { - /** - Register with target handler - - @method registerHandlers - @param {Object} target - @param {Function} becameInvalid - @param {Function} becameValid - */ - registerHandlers: function(target, becameInvalid, becameValid) { - this.on('becameInvalid', target, becameInvalid); - this.on('becameValid', target, becameValid); - }, - - /** - @property errorsByAttributeName - @type {Ember.MapWithDefault} - @private - */ - errorsByAttributeName: Ember.reduceComputed("content", { - initialValue: function() { - return MapWithDefault.create({ - defaultValue: function() { - return Ember.A(); - } - }); - }, - - addedItem: function(errors, error) { - errors.get(error.attribute).pushObject(error); - - return errors; - }, - - removedItem: function(errors, error) { - errors.get(error.attribute).removeObject(error); - - return errors; - } - }), - - /** - Returns errors for a given attribute - - ```javascript - var user = store.createRecord('user', { - username: 'tomster', - email: 'invalidEmail' - }); - user.save().catch(function(){ - user.get('errors').errorsFor('email'); // ["Doesn't look like a valid email."] - }); - ``` - - @method errorsFor - @param {String} attribute - @return {Array} - */ - errorsFor: function(attribute) { - return get(this, 'errorsByAttributeName').get(attribute); - }, - - /** - An array containing all of the error messages for this - record. This is useful for displaying all errors to the user. - - ```handlebars - {{#each errors.messages}} -
- {{message}} -
- {{/each}} - ``` - - @property messages - @type {Array} - */ - messages: Ember.computed.mapBy('content', 'message'), - - /** - @property content - @type {Array} - @private - */ - content: Ember.computed(function() { - return Ember.A(); - }), - - /** - @method unknownProperty - @private - */ - unknownProperty: function(attribute) { - var errors = this.errorsFor(attribute); - if (isEmpty(errors)) { return null; } - return errors; - }, - - /** - @method nextObject - @private - */ - nextObject: function(index, previousObject, context) { - return get(this, 'content').objectAt(index); - }, - - /** - Total number of errors. - - @property length - @type {Number} - @readOnly - */ - length: Ember.computed.oneWay('content.length').readOnly(), - - /** - @property isEmpty - @type {Boolean} - @readOnly - */ - isEmpty: Ember.computed.not('length').readOnly(), - - /** - Adds error messages to a given attribute and sends - `becameInvalid` event to the record. - - Example: - - ```javascript - if (!user.get('username') { - user.get('errors').add('username', 'This field is required'); - } - ``` - - @method add - @param {String} attribute - @param {Array|String} messages - */ - add: function(attribute, messages) { - var wasEmpty = get(this, 'isEmpty'); - - messages = this._findOrCreateMessages(attribute, messages); - get(this, 'content').addObjects(messages); - - this.notifyPropertyChange(attribute); - this.enumerableContentDidChange(); - - if (wasEmpty && !get(this, 'isEmpty')) { - this.trigger('becameInvalid'); - } - }, - - /** - @method _findOrCreateMessages - @private - */ - _findOrCreateMessages: function(attribute, messages) { - var errors = this.errorsFor(attribute); - - return map(Ember.makeArray(messages), function(message) { - return errors.findBy('message', message) || { - attribute: attribute, - message: message - }; - }); - }, - - /** - Removes all error messages from the given attribute and sends - `becameValid` event to the record if there no more errors left. - - Example: - - ```javascript - App.User = DS.Model.extend({ - email: DS.attr('string'), - twoFactorAuth: DS.attr('boolean'), - phone: DS.attr('string') - }); - - App.UserEditRoute = Ember.Route.extend({ - actions: { - save: function(user) { - if (!user.get('twoFactorAuth')) { - user.get('errors').remove('phone'); - } - user.save(); - } - } - }); - ``` - - @method remove - @param {String} attribute - */ - remove: function(attribute) { - if (get(this, 'isEmpty')) { return; } - - var content = get(this, 'content').rejectBy('attribute', attribute); - get(this, 'content').setObjects(content); - - this.notifyPropertyChange(attribute); - this.enumerableContentDidChange(); - - if (get(this, 'isEmpty')) { - this.trigger('becameValid'); - } - }, - - /** - Removes all error messages and sends `becameValid` event - to the record. - - Example: - - ```javascript - App.UserEditRoute = Ember.Route.extend({ - actions: { - retrySave: function(user) { - user.get('errors').clear(); - user.save(); - } - } - }); - ``` - - @method clear - */ - clear: function() { - if (get(this, 'isEmpty')) { return; } - - get(this, 'content').clear(); - this.enumerableContentDidChange(); - - this.trigger('becameValid'); - }, - - /** - Checks if there is error messages for the given attribute. - - ```javascript - App.UserEditRoute = Ember.Route.extend({ - actions: { - save: function(user) { - if (user.get('errors').has('email')) { - return alert('Please update your email before attempting to save.'); - } - user.save(); - } - } - }); - ``` - - @method has - @param {String} attribute - @return {Boolean} true if there some errors on given attribute - */ - has: function(attribute) { - return !isEmpty(this.errorsFor(attribute)); - } - }); - }); -define("ember-data/system/model/model", - ["ember-data/system/model/states","ember-data/system/model/errors","ember-data/system/promise_proxies","ember-data/system/relationships/relationship","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __exports__) { - "use strict"; - var RootState = __dependency1__["default"]; - var Errors = __dependency2__["default"]; - var PromiseObject = __dependency3__.PromiseObject; - var createRelationshipFor = __dependency4__.createRelationshipFor; - - /** - @module ember-data - */ - - var get = Ember.get; - var set = Ember.set; - var merge = Ember.merge; - var Promise = Ember.RSVP.Promise; - var forEach = Ember.ArrayPolyfills.forEach; - var map = Ember.ArrayPolyfills.map; - - var JSONSerializer; - var retrieveFromCurrentState = Ember.computed('currentState', function(key, value) { - return get(get(this, 'currentState'), key); - }).readOnly(); - - var _extractPivotNameCache = Object.create(null); - var _splitOnDotCache = Object.create(null); - - function splitOnDot(name) { - return _splitOnDotCache[name] || ( - _splitOnDotCache[name] = name.split('.') - ); - } - - function extractPivotName(name) { - return _extractPivotNameCache[name] || ( - _extractPivotNameCache[name] = splitOnDot(name)[0] - ); - } - - /** - - The model class that all Ember Data records descend from. - - @class Model - @namespace DS - @extends Ember.Object - @uses Ember.Evented - */ - var Model = Ember.Object.extend(Ember.Evented, { - _recordArrays: undefined, - _relationships: undefined, - _loadingRecordArrays: undefined, - /** - If this property is `true` the record is in the `empty` - state. Empty is the first state all records enter after they have - been created. Most records created by the store will quickly - transition to the `loading` state if data needs to be fetched from - the server or the `created` state if the record is created on the - client. A record can also enter the empty state if the adapter is - unable to locate the record. - - @property isEmpty - @type {Boolean} - @readOnly - */ - isEmpty: retrieveFromCurrentState, - /** - If this property is `true` the record is in the `loading` state. A - record enters this state when the store asks the adapter for its - data. It remains in this state until the adapter provides the - requested data. - - @property isLoading - @type {Boolean} - @readOnly - */ - isLoading: retrieveFromCurrentState, - /** - If this property is `true` the record is in the `loaded` state. A - record enters this state when its data is populated. Most of a - record's lifecycle is spent inside substates of the `loaded` - state. - - Example - - ```javascript - var record = store.createRecord('model'); - record.get('isLoaded'); // true - - store.find('model', 1).then(function(model) { - model.get('isLoaded'); // true - }); - ``` - - @property isLoaded - @type {Boolean} - @readOnly - */ - isLoaded: retrieveFromCurrentState, - /** - If this property is `true` the record is in the `dirty` state. The - record has local changes that have not yet been saved by the - adapter. This includes records that have been created (but not yet - saved) or deleted. - - Example - - ```javascript - var record = store.createRecord('model'); - record.get('isDirty'); // true - - store.find('model', 1).then(function(model) { - model.get('isDirty'); // false - model.set('foo', 'some value'); - model.get('isDirty'); // true - }); - ``` - - @property isDirty - @type {Boolean} - @readOnly - */ - isDirty: retrieveFromCurrentState, - /** - If this property is `true` the record is in the `saving` state. A - record enters the saving state when `save` is called, but the - adapter has not yet acknowledged that the changes have been - persisted to the backend. - - Example - - ```javascript - var record = store.createRecord('model'); - record.get('isSaving'); // false - var promise = record.save(); - record.get('isSaving'); // true - promise.then(function() { - record.get('isSaving'); // false - }); - ``` - - @property isSaving - @type {Boolean} - @readOnly - */ - isSaving: retrieveFromCurrentState, - /** - If this property is `true` the record is in the `deleted` state - and has been marked for deletion. When `isDeleted` is true and - `isDirty` is true, the record is deleted locally but the deletion - was not yet persisted. When `isSaving` is true, the change is - in-flight. When both `isDirty` and `isSaving` are false, the - change has persisted. - - Example - - ```javascript - var record = store.createRecord('model'); - record.get('isDeleted'); // false - record.deleteRecord(); - - // Locally deleted - record.get('isDeleted'); // true - record.get('isDirty'); // true - record.get('isSaving'); // false - - // Persisting the deletion - var promise = record.save(); - record.get('isDeleted'); // true - record.get('isSaving'); // true - - // Deletion Persisted - promise.then(function() { - record.get('isDeleted'); // true - record.get('isSaving'); // false - record.get('isDirty'); // false - }); - ``` - - @property isDeleted - @type {Boolean} - @readOnly - */ - isDeleted: retrieveFromCurrentState, - /** - If this property is `true` the record is in the `new` state. A - record will be in the `new` state when it has been created on the - client and the adapter has not yet report that it was successfully - saved. - - Example - - ```javascript - var record = store.createRecord('model'); - record.get('isNew'); // true - - record.save().then(function(model) { - model.get('isNew'); // false - }); - ``` - - @property isNew - @type {Boolean} - @readOnly - */ - isNew: retrieveFromCurrentState, - /** - If this property is `true` the record is in the `valid` state. - - A record will be in the `valid` state when the adapter did not report any - server-side validation failures. - - @property isValid - @type {Boolean} - @readOnly - */ - isValid: retrieveFromCurrentState, - /** - If the record is in the dirty state this property will report what - kind of change has caused it to move into the dirty - state. Possible values are: - - - `created` The record has been created by the client and not yet saved to the adapter. - - `updated` The record has been updated by the client and not yet saved to the adapter. - - `deleted` The record has been deleted by the client and not yet saved to the adapter. - - Example - - ```javascript - var record = store.createRecord('model'); - record.get('dirtyType'); // 'created' - ``` - - @property dirtyType - @type {String} - @readOnly - */ - dirtyType: retrieveFromCurrentState, - - /** - If `true` the adapter reported that it was unable to save local - changes to the backend for any reason other than a server-side - validation error. - - Example - - ```javascript - record.get('isError'); // false - record.set('foo', 'valid value'); - record.save().then(null, function() { - record.get('isError'); // true - }); - ``` - - @property isError - @type {Boolean} - @readOnly - */ - isError: false, - /** - If `true` the store is attempting to reload the record form the adapter. - - Example - - ```javascript - record.get('isReloading'); // false - record.reload(); - record.get('isReloading'); // true - ``` - - @property isReloading - @type {Boolean} - @readOnly - */ - isReloading: false, - - /** - The `clientId` property is a transient numerical identifier - generated at runtime by the data store. It is important - primarily because newly created objects may not yet have an - externally generated id. - - @property clientId - @private - @type {Number|String} - */ - clientId: null, - /** - All ember models have an id property. This is an identifier - managed by an external source. These are always coerced to be - strings before being used internally. Note when declaring the - attributes for a model it is an error to declare an id - attribute. - - ```javascript - var record = store.createRecord('model'); - record.get('id'); // null - - store.find('model', 1).then(function(model) { - model.get('id'); // '1' - }); - ``` - - @property id - @type {String} - */ - id: null, - - /** - @property currentState - @private - @type {Object} - */ - currentState: RootState.empty, - - /** - When the record is in the `invalid` state this object will contain - any errors returned by the adapter. When present the errors hash - typically contains keys corresponding to the invalid property names - and values which are an array of error messages. - - ```javascript - record.get('errors.length'); // 0 - record.set('foo', 'invalid value'); - record.save().then(null, function() { - record.get('errors').get('foo'); // ['foo should be a number.'] - }); - ``` - - @property errors - @type {DS.Errors} - */ - errors: Ember.computed(function() { - var errors = Errors.create(); - - errors.registerHandlers(this, function() { - this.send('becameInvalid'); - }, function() { - this.send('becameValid'); - }); - - return errors; - }).readOnly(), - - /** - Create a JSON representation of the record, using the serialization - strategy of the store's adapter. - - `serialize` takes an optional hash as a parameter, currently - supported options are: - - - `includeId`: `true` if the record's ID should be included in the - JSON representation. - - @method serialize - @param {Object} options - @return {Object} an object whose values are primitive JSON values only - */ - serialize: function(options) { - var store = get(this, 'store'); - return store.serialize(this, options); - }, - - /** - Use [DS.JSONSerializer](DS.JSONSerializer.html) to - get the JSON representation of a record. - - `toJSON` takes an optional hash as a parameter, currently - supported options are: - - - `includeId`: `true` if the record's ID should be included in the - JSON representation. - - @method toJSON - @param {Object} options - @return {Object} A JSON representation of the object. - */ - toJSON: function(options) { - if (!JSONSerializer) { JSONSerializer = requireModule("ember-data/serializers/json_serializer")["default"]; } - // container is for lazy transform lookups - var serializer = JSONSerializer.create({ container: this.container }); - return serializer.serialize(this, options); - }, - - /** - Fired when the record is loaded from the server. - - @event didLoad - */ - didLoad: Ember.K, - - /** - Fired when the record is updated. - - @event didUpdate - */ - didUpdate: Ember.K, - - /** - Fired when the record is created. - - @event didCreate - */ - didCreate: Ember.K, - - /** - Fired when the record is deleted. - - @event didDelete - */ - didDelete: Ember.K, - - /** - Fired when the record becomes invalid. - - @event becameInvalid - */ - becameInvalid: Ember.K, - - /** - Fired when the record enters the error state. - - @event becameError - */ - becameError: Ember.K, - - /** - @property data - @private - @type {Object} - */ - data: Ember.computed(function() { - this._data = this._data || {}; - return this._data; - }).readOnly(), - - _data: null, - - init: function() { - this._super(); - this._setup(); - }, - - _setup: function() { - this._changesToSync = {}; - this._deferredTriggers = []; - this._data = {}; - this._attributes = {}; - this._inFlightAttributes = {}; - this._relationships = {}; - /* - implicit relationships are relationship which have not been declared but the inverse side exists on - another record somewhere - For example if there was - ``` - App.Comment = DS.Model.extend({ - name: DS.attr() - }) - ``` - but there is also - ``` - App.Post = DS.Model.extend({ - name: DS.attr(), - comments: DS.hasMany('comment') - }) - ``` - - would have a implicit post relationship in order to be do things like remove ourselves from the post - when we are deleted - */ - this._implicitRelationships = Object.create(null); - var model = this; - //TODO Move into a getter for better perf - this.constructor.eachRelationship(function(key, descriptor) { - model._relationships[key] = createRelationshipFor(model, descriptor, model.store); - }); - - }, - - /** - @method send - @private - @param {String} name - @param {Object} context - */ - send: function(name, context) { - var currentState = get(this, 'currentState'); - - if (!currentState[name]) { - this._unhandledEvent(currentState, name, context); - } - - return currentState[name](this, context); - }, - - /** - @method transitionTo - @private - @param {String} name - */ - transitionTo: function(name) { - // POSSIBLE TODO: Remove this code and replace with - // always having direct references to state objects - - var pivotName = extractPivotName(name); - var currentState = get(this, 'currentState'); - var state = currentState; - - do { - if (state.exit) { state.exit(this); } - state = state.parentState; - } while (!state.hasOwnProperty(pivotName)); - - var path = splitOnDot(name); - var setups = [], enters = [], i, l; - - for (i=0, l=path.length; i "root.created.uncommitted" - ``` - - The hierarchy of valid states that ship with ember data looks like - this: - - ```text - * root - * deleted - * saved - * uncommitted - * inFlight - * empty - * loaded - * created - * uncommitted - * inFlight - * saved - * updated - * uncommitted - * inFlight - * loading - ``` - - The `DS.Model` states are themselves stateless. What that means is - that, the hierarchical states that each of *those* points to is a - shared data structure. For performance reasons, instead of each - record getting its own copy of the hierarchy of states, each record - points to this global, immutable shared instance. How does a state - know which record it should be acting on? We pass the record - instance into the state's event handlers as the first argument. - - The record passed as the first parameter is where you should stash - state about the record if needed; you should never store data on the state - object itself. - - ### Events and Flags - - A state may implement zero or more events and flags. - - #### Events - - Events are named functions that are invoked when sent to a record. The - record will first look for a method with the given name on the - current state. If no method is found, it will search the current - state's parent, and then its grandparent, and so on until reaching - the top of the hierarchy. If the root is reached without an event - handler being found, an exception will be raised. This can be very - helpful when debugging new features. - - Here's an example implementation of a state with a `myEvent` event handler: - - ```javascript - aState: DS.State.create({ - myEvent: function(manager, param) { - console.log("Received myEvent with", param); - } - }) - ``` - - To trigger this event: - - ```javascript - record.send('myEvent', 'foo'); - //=> "Received myEvent with foo" - ``` - - Note that an optional parameter can be sent to a record's `send()` method, - which will be passed as the second parameter to the event handler. - - Events should transition to a different state if appropriate. This can be - done by calling the record's `transitionTo()` method with a path to the - desired state. The state manager will attempt to resolve the state path - relative to the current state. If no state is found at that path, it will - attempt to resolve it relative to the current state's parent, and then its - parent, and so on until the root is reached. For example, imagine a hierarchy - like this: - - * created - * uncommitted <-- currentState - * inFlight - * updated - * inFlight - - If we are currently in the `uncommitted` state, calling - `transitionTo('inFlight')` would transition to the `created.inFlight` state, - while calling `transitionTo('updated.inFlight')` would transition to - the `updated.inFlight` state. - - Remember that *only events* should ever cause a state transition. You should - never call `transitionTo()` from outside a state's event handler. If you are - tempted to do so, create a new event and send that to the state manager. - - #### Flags - - Flags are Boolean values that can be used to introspect a record's current - state in a more user-friendly way than examining its state path. For example, - instead of doing this: - - ```javascript - var statePath = record.get('stateManager.currentPath'); - if (statePath === 'created.inFlight') { - doSomething(); - } - ``` - - You can say: - - ```javascript - if (record.get('isNew') && record.get('isSaving')) { - doSomething(); - } - ``` - - If your state does not set a value for a given flag, the value will - be inherited from its parent (or the first place in the state hierarchy - where it is defined). - - The current set of flags are defined below. If you want to add a new flag, - in addition to the area below, you will also need to declare it in the - `DS.Model` class. - - - * [isEmpty](DS.Model.html#property_isEmpty) - * [isLoading](DS.Model.html#property_isLoading) - * [isLoaded](DS.Model.html#property_isLoaded) - * [isDirty](DS.Model.html#property_isDirty) - * [isSaving](DS.Model.html#property_isSaving) - * [isDeleted](DS.Model.html#property_isDeleted) - * [isNew](DS.Model.html#property_isNew) - * [isValid](DS.Model.html#property_isValid) - - @namespace DS - @class RootState - */ - - function didSetProperty(record, context) { - if (context.value === context.originalValue) { - delete record._attributes[context.name]; - record.send('propertyWasReset', context.name); - } else if (context.value !== context.oldValue) { - record.send('becomeDirty'); - } - - record.updateRecordArraysLater(); - } - - // Implementation notes: - // - // Each state has a boolean value for all of the following flags: - // - // * isLoaded: The record has a populated `data` property. When a - // record is loaded via `store.find`, `isLoaded` is false - // until the adapter sets it. When a record is created locally, - // its `isLoaded` property is always true. - // * isDirty: The record has local changes that have not yet been - // saved by the adapter. This includes records that have been - // created (but not yet saved) or deleted. - // * isSaving: The record has been committed, but - // the adapter has not yet acknowledged that the changes have - // been persisted to the backend. - // * isDeleted: The record was marked for deletion. When `isDeleted` - // is true and `isDirty` is true, the record is deleted locally - // but the deletion was not yet persisted. When `isSaving` is - // true, the change is in-flight. When both `isDirty` and - // `isSaving` are false, the change has persisted. - // * isError: The adapter reported that it was unable to save - // local changes to the backend. This may also result in the - // record having its `isValid` property become false if the - // adapter reported that server-side validations failed. - // * isNew: The record was created on the client and the adapter - // did not yet report that it was successfully saved. - // * isValid: The adapter did not report any server-side validation - // failures. - - // The dirty state is a abstract state whose functionality is - // shared between the `created` and `updated` states. - // - // The deleted state shares the `isDirty` flag with the - // subclasses of `DirtyState`, but with a very different - // implementation. - // - // Dirty states have three child states: - // - // `uncommitted`: the store has not yet handed off the record - // to be saved. - // `inFlight`: the store has handed off the record to be saved, - // but the adapter has not yet acknowledged success. - // `invalid`: the record has invalid information and cannot be - // send to the adapter yet. - var DirtyState = { - initialState: 'uncommitted', - - // FLAGS - isDirty: true, - - // SUBSTATES - - // When a record first becomes dirty, it is `uncommitted`. - // This means that there are local pending changes, but they - // have not yet begun to be saved, and are not invalid. - uncommitted: { - // EVENTS - didSetProperty: didSetProperty, - - //TODO(Igor) reloading now triggers a - //loadingData event, though it seems fine? - loadingData: Ember.K, - - propertyWasReset: function(record, name) { - var length = Ember.keys(record._attributes); - var stillDirty = length > 0; - - if (!stillDirty) { record.send('rolledBack'); } - }, - - pushedData: Ember.K, - - becomeDirty: Ember.K, - - willCommit: function(record) { - record.transitionTo('inFlight'); - }, - - reloadRecord: function(record, resolve) { - resolve(get(record, 'store').reloadRecord(record)); - }, - - rolledBack: function(record) { - record.transitionTo('loaded.saved'); - }, - - becameInvalid: function(record) { - record.transitionTo('invalid'); - }, - - rollback: function(record) { - record.rollback(); - } - }, - - // Once a record has been handed off to the adapter to be - // saved, it is in the 'in flight' state. Changes to the - // record cannot be made during this window. - inFlight: { - // FLAGS - isSaving: true, - - // EVENTS - didSetProperty: didSetProperty, - becomeDirty: Ember.K, - pushedData: Ember.K, - - unloadRecord: function(record) { - Ember.assert("You can only unload a record which is not inFlight. `" + Ember.inspect(record) + " `", false); - }, - - // TODO: More robust semantics around save-while-in-flight - willCommit: Ember.K, - - didCommit: function(record) { - var dirtyType = get(this, 'dirtyType'); - - record.transitionTo('saved'); - record.send('invokeLifecycleCallbacks', dirtyType); - }, - - becameInvalid: function(record) { - record.transitionTo('invalid'); - record.send('invokeLifecycleCallbacks'); - }, - - becameError: function(record) { - record.transitionTo('uncommitted'); - record.triggerLater('becameError', record); - } - }, - - // A record is in the `invalid` if the adapter has indicated - // the the record failed server-side invalidations. - invalid: { - // FLAGS - isValid: false, - - // EVENTS - deleteRecord: function(record) { - record.transitionTo('deleted.uncommitted'); - record.disconnectRelationships(); - }, - - didSetProperty: function(record, context) { - get(record, 'errors').remove(context.name); - - didSetProperty(record, context); - }, - - becomeDirty: Ember.K, - - willCommit: function(record) { - get(record, 'errors').clear(); - record.transitionTo('inFlight'); - }, - - rolledBack: function(record) { - get(record, 'errors').clear(); - }, - - becameValid: function(record) { - record.transitionTo('uncommitted'); - }, - - invokeLifecycleCallbacks: function(record) { - record.triggerLater('becameInvalid', record); - }, - - exit: function(record) { - record._inFlightAttributes = {}; - } - } - }; - - // The created and updated states are created outside the state - // chart so we can reopen their substates and add mixins as - // necessary. - - function deepClone(object) { - var clone = {}, value; - - for (var prop in object) { - value = object[prop]; - if (value && typeof value === 'object') { - clone[prop] = deepClone(value); - } else { - clone[prop] = value; - } - } - - return clone; - } - - function mixin(original, hash) { - for (var prop in hash) { - original[prop] = hash[prop]; - } - - return original; - } - - function dirtyState(options) { - var newState = deepClone(DirtyState); - return mixin(newState, options); - } - - var createdState = dirtyState({ - dirtyType: 'created', - // FLAGS - isNew: true - }); - - createdState.uncommitted.rolledBack = function(record) { - record.transitionTo('deleted.saved'); - }; - - var updatedState = dirtyState({ - dirtyType: 'updated' - }); - - createdState.uncommitted.deleteRecord = function(record) { - record.disconnectRelationships(); - record.transitionTo('deleted.saved'); - }; - - createdState.uncommitted.rollback = function(record) { - DirtyState.uncommitted.rollback.apply(this, arguments); - record.transitionTo('deleted.saved'); - }; - - createdState.uncommitted.propertyWasReset = Ember.K; - - function assertAgainstUnloadRecord(record) { - Ember.assert("You can only unload a record which is not inFlight. `" + Ember.inspect(record) + "`", false); - } - - updatedState.inFlight.unloadRecord = assertAgainstUnloadRecord; - - updatedState.uncommitted.deleteRecord = function(record) { - record.transitionTo('deleted.uncommitted'); - record.disconnectRelationships(); - }; - - var RootState = { - // FLAGS - isEmpty: false, - isLoading: false, - isLoaded: false, - isDirty: false, - isSaving: false, - isDeleted: false, - isNew: false, - isValid: true, - - // DEFAULT EVENTS - - // Trying to roll back if you're not in the dirty state - // doesn't change your state. For example, if you're in the - // in-flight state, rolling back the record doesn't move - // you out of the in-flight state. - rolledBack: Ember.K, - unloadRecord: function(record) { - // clear relationships before moving to deleted state - // otherwise it fails - record.clearRelationships(); - record.transitionTo('deleted.saved'); - }, - - - propertyWasReset: Ember.K, - - // SUBSTATES - - // A record begins its lifecycle in the `empty` state. - // If its data will come from the adapter, it will - // transition into the `loading` state. Otherwise, if - // the record is being created on the client, it will - // transition into the `created` state. - empty: { - isEmpty: true, - - // EVENTS - loadingData: function(record, promise) { - record._loadingPromise = promise; - record.transitionTo('loading'); - }, - - loadedData: function(record) { - record.transitionTo('loaded.created.uncommitted'); - record.notifyPropertyChange('data'); - }, - - pushedData: function(record) { - record.transitionTo('loaded.saved'); - record.triggerLater('didLoad'); - } - }, - - // A record enters this state when the store asks - // the adapter for its data. It remains in this state - // until the adapter provides the requested data. - // - // Usually, this process is asynchronous, using an - // XHR to retrieve the data. - loading: { - // FLAGS - isLoading: true, - - exit: function(record) { - record._loadingPromise = null; - }, - - // EVENTS - pushedData: function(record) { - record.transitionTo('loaded.saved'); - record.triggerLater('didLoad'); - set(record, 'isError', false); - }, - - becameError: function(record) { - record.triggerLater('becameError', record); - }, - - notFound: function(record) { - record.transitionTo('empty'); - } - }, - - // A record enters this state when its data is populated. - // Most of a record's lifecycle is spent inside substates - // of the `loaded` state. - loaded: { - initialState: 'saved', - - // FLAGS - isLoaded: true, - - //TODO(Igor) Reloading now triggers a loadingData event, - //but it should be ok? - loadingData: Ember.K, - - // SUBSTATES - - // If there are no local changes to a record, it remains - // in the `saved` state. - saved: { - setup: function(record) { - var attrs = record._attributes; - var isDirty = false; - - for (var prop in attrs) { - if (attrs.hasOwnProperty(prop)) { - isDirty = true; - break; - } - } - - if (isDirty) { - record.adapterDidDirty(); - } - }, - - // EVENTS - didSetProperty: didSetProperty, - - pushedData: Ember.K, - - becomeDirty: function(record) { - record.transitionTo('updated.uncommitted'); - }, - - willCommit: function(record) { - record.transitionTo('updated.inFlight'); - }, - - reloadRecord: function(record, resolve) { - resolve(get(record, 'store').reloadRecord(record)); - }, - - deleteRecord: function(record) { - record.transitionTo('deleted.uncommitted'); - record.disconnectRelationships(); - }, - - unloadRecord: function(record) { - // clear relationships before moving to deleted state - // otherwise it fails - record.clearRelationships(); - record.transitionTo('deleted.saved'); - }, - - didCommit: function(record) { - record.send('invokeLifecycleCallbacks', get(record, 'lastDirtyType')); - }, - - // loaded.saved.notFound would be triggered by a failed - // `reload()` on an unchanged record - notFound: Ember.K - - }, - - // A record is in this state after it has been locally - // created but before the adapter has indicated that - // it has been saved. - created: createdState, - - // A record is in this state if it has already been - // saved to the server, but there are new local changes - // that have not yet been saved. - updated: updatedState - }, - - // A record is in this state if it was deleted from the store. - deleted: { - initialState: 'uncommitted', - dirtyType: 'deleted', - - // FLAGS - isDeleted: true, - isLoaded: true, - isDirty: true, - - // TRANSITIONS - setup: function(record) { - record.updateRecordArrays(); - }, - - // SUBSTATES - - // When a record is deleted, it enters the `start` - // state. It will exit this state when the record - // starts to commit. - uncommitted: { - - // EVENTS - - willCommit: function(record) { - record.transitionTo('inFlight'); - }, - - rollback: function(record) { - record.rollback(); - }, - - becomeDirty: Ember.K, - deleteRecord: Ember.K, - - rolledBack: function(record) { - record.transitionTo('loaded.saved'); - } - }, - - // After a record starts committing, but - // before the adapter indicates that the deletion - // has saved to the server, a record is in the - // `inFlight` substate of `deleted`. - inFlight: { - // FLAGS - isSaving: true, - - // EVENTS - - unloadRecord: assertAgainstUnloadRecord, - - // TODO: More robust semantics around save-while-in-flight - willCommit: Ember.K, - didCommit: function(record) { - record.transitionTo('saved'); - - record.send('invokeLifecycleCallbacks'); - }, - - becameError: function(record) { - record.transitionTo('uncommitted'); - record.triggerLater('becameError', record); - } - }, - - // Once the adapter indicates that the deletion has - // been saved, the record enters the `saved` substate - // of `deleted`. - saved: { - // FLAGS - isDirty: false, - - setup: function(record) { - var store = get(record, 'store'); - store.dematerializeRecord(record); - }, - - invokeLifecycleCallbacks: function(record) { - record.triggerLater('didDelete', record); - record.triggerLater('didCommit', record); - }, - - willCommit: Ember.K, - - didCommit: Ember.K - } - }, - - invokeLifecycleCallbacks: function(record, dirtyType) { - if (dirtyType === 'created') { - record.triggerLater('didCreate', record); - } else { - record.triggerLater('didUpdate', record); - } - - record.triggerLater('didCommit', record); - } - }; - - function wireState(object, parent, name) { - /*jshint proto:true*/ - // TODO: Use Object.create and copy instead - object = mixin(parent ? Ember.create(parent) : {}, object); - object.parentState = parent; - object.stateName = name; - - for (var prop in object) { - if (!object.hasOwnProperty(prop) || prop === 'parentState' || prop === 'stateName') { continue; } - if (typeof object[prop] === 'object') { - object[prop] = wireState(object[prop], object, name + "." + prop); - } - } - - return object; - } - - RootState = wireState(RootState, null, "root"); - - __exports__["default"] = RootState; - }); -define("ember-data/system/promise_proxies", - ["exports"], - function(__exports__) { - "use strict"; - var Promise = Ember.RSVP.Promise; - var get = Ember.get; - - /** - A `PromiseArray` is an object that acts like both an `Ember.Array` - and a promise. When the promise is resolved the resulting value - will be set to the `PromiseArray`'s `content` property. This makes - it easy to create data bindings with the `PromiseArray` that will be - updated when the promise resolves. - - For more information see the [Ember.PromiseProxyMixin - documentation](/api/classes/Ember.PromiseProxyMixin.html). - - Example - - ```javascript - var promiseArray = DS.PromiseArray.create({ - promise: $.getJSON('/some/remote/data.json') - }); - - promiseArray.get('length'); // 0 - - promiseArray.then(function() { - promiseArray.get('length'); // 100 - }); - ``` - - @class PromiseArray - @namespace DS - @extends Ember.ArrayProxy - @uses Ember.PromiseProxyMixin - */ - var PromiseArray = Ember.ArrayProxy.extend(Ember.PromiseProxyMixin); - - /** - A `PromiseObject` is an object that acts like both an `Ember.Object` - and a promise. When the promise is resolved, then the resulting value - will be set to the `PromiseObject`'s `content` property. This makes - it easy to create data bindings with the `PromiseObject` that will - be updated when the promise resolves. - - For more information see the [Ember.PromiseProxyMixin - documentation](/api/classes/Ember.PromiseProxyMixin.html). - - Example - - ```javascript - var promiseObject = DS.PromiseObject.create({ - promise: $.getJSON('/some/remote/data.json') - }); - - promiseObject.get('name'); // null - - promiseObject.then(function() { - promiseObject.get('name'); // 'Tomster' - }); - ``` - - @class PromiseObject - @namespace DS - @extends Ember.ObjectProxy - @uses Ember.PromiseProxyMixin - */ - var PromiseObject = Ember.ObjectProxy.extend(Ember.PromiseProxyMixin); - - var promiseObject = function(promise, label) { - return PromiseObject.create({ - promise: Promise.resolve(promise, label) - }); - }; - - var promiseArray = function(promise, label) { - return PromiseArray.create({ - promise: Promise.resolve(promise, label) - }); - }; - - /** - A PromiseManyArray is a PromiseArray that also proxies certain method calls - to the underlying manyArray. - Right now we proxy: - `reload()` - */ - - var PromiseManyArray = PromiseArray.extend({ - reload: function() { - //I don't think this should ever happen right now, but worth guarding if we refactor the async relationships - Ember.assert('You are trying to reload an async manyArray before it has been created', get(this, 'content')); - return get(this, 'content').reload(); - } - }); - - var promiseManyArray = function(promise, label) { - return PromiseManyArray.create({ - promise: Promise.resolve(promise, label) - }); - }; - - - __exports__.PromiseArray = PromiseArray; - __exports__.PromiseObject = PromiseObject; - __exports__.PromiseManyArray = PromiseManyArray; - __exports__.promiseArray = promiseArray; - __exports__.promiseObject = promiseObject; - __exports__.promiseManyArray = promiseManyArray; - }); -define("ember-data/system/record_array_manager", - ["ember-data/system/record_arrays","ember-data/system/map","exports"], - function(__dependency1__, __dependency2__, __exports__) { - "use strict"; - /** - @module ember-data - */ - - var RecordArray = __dependency1__.RecordArray; - var FilteredRecordArray = __dependency1__.FilteredRecordArray; - var AdapterPopulatedRecordArray = __dependency1__.AdapterPopulatedRecordArray; - var ManyArray = __dependency1__.ManyArray; - var MapWithDefault = __dependency2__.MapWithDefault; - var OrderedSet = __dependency2__.OrderedSet; - var get = Ember.get; - var forEach = Ember.EnumerableUtils.forEach; - - /** - @class RecordArrayManager - @namespace DS - @private - @extends Ember.Object - */ - __exports__["default"] = Ember.Object.extend({ - init: function() { - this.filteredRecordArrays = MapWithDefault.create({ - defaultValue: function() { return []; } - }); - - this.changedRecords = []; - this._adapterPopulatedRecordArrays = []; - }, - - recordDidChange: function(record) { - if (this.changedRecords.push(record) !== 1) { return; } - - Ember.run.schedule('actions', this, this.updateRecordArrays); - }, - - recordArraysForRecord: function(record) { - record._recordArrays = record._recordArrays || OrderedSet.create(); - return record._recordArrays; - }, - - /** - This method is invoked whenever data is loaded into the store by the - adapter or updated by the adapter, or when a record has changed. - - It updates all record arrays that a record belongs to. - - To avoid thrashing, it only runs at most once per run loop. - - @method updateRecordArrays - @param {Class} type - @param {Number|String} clientId - */ - updateRecordArrays: function() { - forEach(this.changedRecords, function(record) { - if (get(record, 'isDeleted')) { - this._recordWasDeleted(record); - } else { - this._recordWasChanged(record); - } - }, this); - - this.changedRecords.length = 0; - }, - - _recordWasDeleted: function (record) { - var recordArrays = record._recordArrays; - - if (!recordArrays) { return; } - - recordArrays.forEach(function(array){ - array.removeRecord(record); - }); - - record._recordArrays = null; - }, - - _recordWasChanged: function (record) { - var type = record.constructor; - var recordArrays = this.filteredRecordArrays.get(type); - var filter; - - forEach(recordArrays, function(array) { - filter = get(array, 'filterFunction'); - this.updateRecordArray(array, filter, type, record); - }, this); - - // loop through all manyArrays containing an unloaded copy of this - // clientId and notify them that the record was loaded. - var manyArrays = record._loadingRecordArrays; - - if (manyArrays) { - for (var i=0, l=manyArrays.length; i 0){ - records = get(this, 'content').slice(idx, idx+amt); - this.get('relationship').removeRecords(records); - } - if (objects){ - this.get('relationship').addRecords(objects, idx); - } - }, - /** - @method reload - @public - */ - reload: function() { - return this.relationship.reload(); - }, - - /** - Create a child record within the owner - - @method createRecord - @private - @param {Object} hash - @return {DS.Model} record - */ - createRecord: function(hash) { - var store = get(this, 'store'); - var type = get(this, 'type'); - var record; - - Ember.assert("You cannot add '" + type.typeKey + "' records to this polymorphic relationship.", !get(this, 'isPolymorphic')); - - record = store.createRecord.call(store, type, hash); - this.pushObject(record); - - return record; - } - }); - }); -define("ember-data/system/record_arrays/record_array", - ["ember-data/system/promise_proxies","exports"], - function(__dependency1__, __exports__) { - "use strict"; - /** - @module ember-data - */ - - var PromiseArray = __dependency1__.PromiseArray; - var get = Ember.get; - - /** - A record array is an array that contains records of a certain type. The record - array materializes records as needed when they are retrieved for the first - time. You should not create record arrays yourself. Instead, an instance of - `DS.RecordArray` or its subclasses will be returned by your application's store - in response to queries. - - @class RecordArray - @namespace DS - @extends Ember.ArrayProxy - @uses Ember.Evented - */ - - __exports__["default"] = Ember.ArrayProxy.extend(Ember.Evented, { - /** - The model type contained by this record array. - - @property type - @type DS.Model - */ - type: null, - - /** - The array of client ids backing the record array. When a - record is requested from the record array, the record - for the client id at the same index is materialized, if - necessary, by the store. - - @property content - @private - @type Ember.Array - */ - content: null, - - /** - The flag to signal a `RecordArray` is currently loading data. - - Example - - ```javascript - var people = store.all('person'); - people.get('isLoaded'); // true - ``` - - @property isLoaded - @type Boolean - */ - isLoaded: false, - /** - The flag to signal a `RecordArray` is currently loading data. - - Example - - ```javascript - var people = store.all('person'); - people.get('isUpdating'); // false - people.update(); - people.get('isUpdating'); // true - ``` - - @property isUpdating - @type Boolean - */ - isUpdating: false, - - /** - The store that created this record array. - - @property store - @private - @type DS.Store - */ - store: null, - - /** - Retrieves an object from the content by index. - - @method objectAtContent - @private - @param {Number} index - @return {DS.Model} record - */ - objectAtContent: function(index) { - var content = get(this, 'content'); - - return content.objectAt(index); - }, - - /** - Used to get the latest version of all of the records in this array - from the adapter. - - Example - - ```javascript - var people = store.all('person'); - people.get('isUpdating'); // false - people.update(); - people.get('isUpdating'); // true - ``` - - @method update - */ - update: function() { - if (get(this, 'isUpdating')) { return; } - - var store = get(this, 'store'); - var type = get(this, 'type'); - - return store.fetchAll(type, this); - }, - - /** - Adds a record to the `RecordArray` without duplicates - - @method addRecord - @private - @param {DS.Model} record - @param {DS.Model} an optional index to insert at - */ - addRecord: function(record, idx) { - var content = get(this, 'content'); - if (idx === undefined) { - content.addObject(record); - } else { - if (!content.contains(record)) { - content.insertAt(idx, record); - } - } - }, - - /** - Adds a record to the `RecordArray`, but allows duplicates - - @method pushRecord - @private - @param {DS.Model} record - */ - pushRecord: function(record) { - get(this, 'content').pushObject(record); - }, - - - /** - Removes a record to the `RecordArray`. - - @method removeRecord - @private - @param {DS.Model} record - */ - removeRecord: function(record) { - get(this, 'content').removeObject(record); - }, - - /** - Saves all of the records in the `RecordArray`. - - Example - - ```javascript - var messages = store.all('message'); - messages.forEach(function(message) { - message.set('hasBeenSeen', true); - }); - messages.save(); - ``` - - @method save - @return {DS.PromiseArray} promise - */ - save: function() { - var promiseLabel = "DS: RecordArray#save " + get(this, 'type'); - var promise = Ember.RSVP.all(this.invoke("save"), promiseLabel).then(function(array) { - return Ember.A(array); - }, null, "DS: RecordArray#save apply Ember.NativeArray"); - - return PromiseArray.create({ promise: promise }); - }, - - _dissociateFromOwnRecords: function() { - var array = this; - - this.forEach(function(record){ - var recordArrays = record._recordArrays; - - if (recordArrays) { - recordArrays["delete"](array); - } - }); - }, - - willDestroy: function(){ - this._dissociateFromOwnRecords(); - this._super(); - } - }); - }); -define("ember-data/system/relationship-meta", - ["ember-inflector/system","exports"], - function(__dependency1__, __exports__) { - "use strict"; - var singularize = __dependency1__.singularize; - - function typeForRelationshipMeta(store, meta) { - var typeKey, type; - - typeKey = meta.type || meta.key; - if (typeof typeKey === 'string') { - if (meta.kind === 'hasMany') { - typeKey = singularize(typeKey); - } - type = store.modelFor(typeKey); - } else { - type = meta.type; - } - - return type; - } - - __exports__.typeForRelationshipMeta = typeForRelationshipMeta;function relationshipFromMeta(store, meta) { - return { - key: meta.key, - kind: meta.kind, - type: typeForRelationshipMeta(store, meta), - options: meta.options, - parentType: meta.parentType, - isRelationship: true - }; - } - - __exports__.relationshipFromMeta = relationshipFromMeta; - }); -define("ember-data/system/relationships", - ["./relationships/belongs_to","./relationships/has_many","ember-data/system/relationships/ext","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __exports__) { - "use strict"; - /** - @module ember-data - */ - - var belongsTo = __dependency1__["default"]; - var hasMany = __dependency2__["default"]; - - - __exports__.belongsTo = belongsTo; - __exports__.hasMany = hasMany; - }); -define("ember-data/system/relationships/belongs_to", - ["ember-data/system/model","exports"], - function(__dependency1__, __exports__) { - "use strict"; - var Model = __dependency1__.Model; - - - /** - `DS.belongsTo` is used to define One-To-One and One-To-Many - relationships on a [DS.Model](/api/data/classes/DS.Model.html). - - - `DS.belongsTo` takes an optional hash as a second parameter, currently - supported options are: - - - `async`: A boolean value used to explicitly declare this to be an async relationship. - - `inverse`: A string used to identify the inverse property on a - related model in a One-To-Many relationship. See [Explicit Inverses](#toc_explicit-inverses) - - #### One-To-One - To declare a one-to-one relationship between two models, use - `DS.belongsTo`: - - ```javascript - App.User = DS.Model.extend({ - profile: DS.belongsTo('profile') - }); - - App.Profile = DS.Model.extend({ - user: DS.belongsTo('user') - }); - ``` - - #### One-To-Many - To declare a one-to-many relationship between two models, use - `DS.belongsTo` in combination with `DS.hasMany`, like this: - - ```javascript - App.Post = DS.Model.extend({ - comments: DS.hasMany('comment') - }); - - App.Comment = DS.Model.extend({ - post: DS.belongsTo('post') - }); - ``` - - @namespace - @method belongsTo - @for DS - @param {String or DS.Model} type the model type of the relationship - @param {Object} options a hash of options - @return {Ember.computed} relationship - */ - function belongsTo(type, options) { - if (typeof type === 'object') { - options = type; - type = undefined; - } else { - Ember.assert("The first argument to DS.belongsTo must be a string representing a model type key, e.g. use DS.belongsTo('person') to define a relation to the App.Person model", !!type && (typeof type === 'string' || Model.detect(type))); - } - - options = options || {}; - - var meta = { - type: type, - isRelationship: true, - options: options, - kind: 'belongsTo', - key: null - }; - - return Ember.computed(function(key, value) { - if (arguments.length>1) { - if ( value === undefined ) { - value = null; - } - if (value && value.then) { - this._relationships[key].setRecordPromise(value); - } else { - this._relationships[key].setRecord(value); - } - } - - return this._relationships[key].getRecord(); - }).meta(meta); - } - - /** - These observers observe all `belongsTo` relationships on the record. See - `relationships/ext` to see how these observers get their dependencies. - - @class Model - @namespace DS - */ - Model.reopen({ - notifyBelongsToAdded: function(key, relationship) { - this.notifyPropertyChange(key); - }, - - notifyBelongsToRemoved: function(key) { - this.notifyPropertyChange(key); - } - }); - - __exports__["default"] = belongsTo; - }); -define("ember-data/system/relationships/ext", - ["ember-data/system/relationship-meta","ember-data/system/model","ember-data/system/map"], - function(__dependency1__, __dependency2__, __dependency3__) { - "use strict"; - var typeForRelationshipMeta = __dependency1__.typeForRelationshipMeta; - var relationshipFromMeta = __dependency1__.relationshipFromMeta; - var Model = __dependency2__.Model; - var Map = __dependency3__.Map; - var MapWithDefault = __dependency3__.MapWithDefault; - - var get = Ember.get; - var filter = Ember.ArrayPolyfills.filter; - - /** - @module ember-data - */ - - /* - This file defines several extensions to the base `DS.Model` class that - add support for one-to-many relationships. - */ - - /** - @class Model - @namespace DS - */ - Model.reopen({ - - /** - This Ember.js hook allows an object to be notified when a property - is defined. - - In this case, we use it to be notified when an Ember Data user defines a - belongs-to relationship. In that case, we need to set up observers for - each one, allowing us to track relationship changes and automatically - reflect changes in the inverse has-many array. - - This hook passes the class being set up, as well as the key and value - being defined. So, for example, when the user does this: - - ```javascript - DS.Model.extend({ - parent: DS.belongsTo('user') - }); - ``` - - This hook would be called with "parent" as the key and the computed - property returned by `DS.belongsTo` as the value. - - @method didDefineProperty - @param {Object} proto - @param {String} key - @param {Ember.ComputedProperty} value - */ - didDefineProperty: function(proto, key, value) { - // Check if the value being set is a computed property. - if (value instanceof Ember.ComputedProperty) { - - // If it is, get the metadata for the relationship. This is - // populated by the `DS.belongsTo` helper when it is creating - // the computed property. - var meta = value.meta(); - - meta.parentType = proto.constructor; - } - } - }); - - /* - These DS.Model extensions add class methods that provide relationship - introspection abilities about relationships. - - A note about the computed properties contained here: - - **These properties are effectively sealed once called for the first time.** - To avoid repeatedly doing expensive iteration over a model's fields, these - values are computed once and then cached for the remainder of the runtime of - your application. - - If your application needs to modify a class after its initial definition - (for example, using `reopen()` to add additional attributes), make sure you - do it before using your model with the store, which uses these properties - extensively. - */ - - Model.reopenClass({ - - /** - For a given relationship name, returns the model type of the relationship. - - For example, if you define a model like this: - - ```javascript - App.Post = DS.Model.extend({ - comments: DS.hasMany('comment') - }); - ``` - - Calling `App.Post.typeForRelationship('comments')` will return `App.Comment`. - - @method typeForRelationship - @static - @param {String} name the name of the relationship - @return {subclass of DS.Model} the type of the relationship, or undefined - */ - typeForRelationship: function(name) { - var relationship = get(this, 'relationshipsByName').get(name); - return relationship && relationship.type; - }, - - inverseMap: Ember.computed(function() { - return Object.create(null); - }), - - /* - Find the relationship which is the inverse of the one asked for. - - For example, if you define models like this: - - ```javascript - App.Post = DS.Model.extend({ - comments: DS.hasMany('message') - }); - - App.Message = DS.Model.extend({ - owner: DS.belongsTo('post') - }); - ``` - - App.Post.inverseFor('comments') -> {type: App.Message, name:'owner', kind:'belongsTo'} - App.Message.inverseFor('owner') -> {type: App.Post, name:'comments', kind:'hasMany'} - - @method inverseFor - @static - @param {String} name the name of the relationship - @return {Object} the inverse relationship, or null - */ - inverseFor: function(name) { - var inverseMap = get(this, 'inverseMap'); - if (inverseMap[name]) { - return inverseMap[name]; - } else { - var inverse = this._findInverseFor(name); - inverseMap[name] = inverse; - return inverse; - } - }, - - //Calculate the inverse, ignoring the cache - _findInverseFor: function(name) { - - var inverseType = this.typeForRelationship(name); - if (!inverseType) { - return null; - } - - //If inverse is manually specified to be null, like `comments: DS.hasMany('message', {inverse: null})` - var options = this.metaForProperty(name).options; - if (options.inverse === null) { return null; } - - var inverseName, inverseKind, inverse; - - //If inverse is specified manually, return the inverse - if (options.inverse) { - inverseName = options.inverse; - inverse = Ember.get(inverseType, 'relationshipsByName').get(inverseName); - - Ember.assert("We found no inverse relationships by the name of '" + inverseName + "' on the '" + inverseType.typeKey + - "' model. This is most likely due to a missing attribute on your model definition.", !Ember.isNone(inverse)); - - inverseKind = inverse.kind; - } else { - //No inverse was specified manually, we need to use a heuristic to guess one - var possibleRelationships = findPossibleInverses(this, inverseType); - - if (possibleRelationships.length === 0) { return null; } - - var filteredRelationships = filter.call(possibleRelationships, function(possibleRelationship) { - var optionsForRelationship = inverseType.metaForProperty(possibleRelationship.name).options; - return name === optionsForRelationship.inverse; - }); - - Ember.assert("You defined the '" + name + "' relationship on " + this + ", but you defined the inverse relationships of type " + - inverseType.toString() + " multiple times. Look at http://emberjs.com/guides/models/defining-models/#toc_explicit-inverses for how to explicitly specify inverses", - filteredRelationships.length < 2); - - if (filteredRelationships.length === 1 ) { - possibleRelationships = filteredRelationships; - } - - Ember.assert("You defined the '" + name + "' relationship on " + this + ", but multiple possible inverse relationships of type " + - this + " were found on " + inverseType + ". Look at http://emberjs.com/guides/models/defining-models/#toc_explicit-inverses for how to explicitly specify inverses", - possibleRelationships.length === 1); - - inverseName = possibleRelationships[0].name; - inverseKind = possibleRelationships[0].kind; - } - - function findPossibleInverses(type, inverseType, relationshipsSoFar) { - var possibleRelationships = relationshipsSoFar || []; - - var relationshipMap = get(inverseType, 'relationships'); - if (!relationshipMap) { return; } - - var relationships = relationshipMap.get(type); - - relationships = filter.call(relationships, function(relationship) { - var optionsForRelationship = inverseType.metaForProperty(relationship.name).options; - - if (!optionsForRelationship.inverse){ - return true; - } - - return name === optionsForRelationship.inverse; - }); - - if (relationships) { - possibleRelationships.push.apply(possibleRelationships, relationships); - } - - //Recurse to support polymorphism - if (type.superclass) { - findPossibleInverses(type.superclass, inverseType, possibleRelationships); - } - - return possibleRelationships; - } - - return { - type: inverseType, - name: inverseName, - kind: inverseKind - }; - }, - - /** - The model's relationships as a map, keyed on the type of the - relationship. The value of each entry is an array containing a descriptor - for each relationship with that type, describing the name of the relationship - as well as the type. - - For example, given the following model definition: - - ```javascript - App.Blog = DS.Model.extend({ - users: DS.hasMany('user'), - owner: DS.belongsTo('user'), - posts: DS.hasMany('post') - }); - ``` - - This computed property would return a map describing these - relationships, like this: - - ```javascript - var relationships = Ember.get(App.Blog, 'relationships'); - relationships.get(App.User); - //=> [ { name: 'users', kind: 'hasMany' }, - // { name: 'owner', kind: 'belongsTo' } ] - relationships.get(App.Post); - //=> [ { name: 'posts', kind: 'hasMany' } ] - ``` - - @property relationships - @static - @type Ember.Map - @readOnly - */ - relationships: Ember.computed(function() { - var map = new MapWithDefault({ - defaultValue: function() { return []; } - }); - - // Loop through each computed property on the class - this.eachComputedProperty(function(name, meta) { - // If the computed property is a relationship, add - // it to the map. - if (meta.isRelationship) { - meta.key = name; - var relationshipsForType = map.get(typeForRelationshipMeta(this.store, meta)); - - relationshipsForType.push({ - name: name, - kind: meta.kind - }); - } - }); - - return map; - }).cacheable(false).readOnly(), - - /** - A hash containing lists of the model's relationships, grouped - by the relationship kind. For example, given a model with this - definition: - - ```javascript - App.Blog = DS.Model.extend({ - users: DS.hasMany('user'), - owner: DS.belongsTo('user'), - - posts: DS.hasMany('post') - }); - ``` - - This property would contain the following: - - ```javascript - var relationshipNames = Ember.get(App.Blog, 'relationshipNames'); - relationshipNames.hasMany; - //=> ['users', 'posts'] - relationshipNames.belongsTo; - //=> ['owner'] - ``` - - @property relationshipNames - @static - @type Object - @readOnly - */ - relationshipNames: Ember.computed(function() { - var names = { - hasMany: [], - belongsTo: [] - }; - - this.eachComputedProperty(function(name, meta) { - if (meta.isRelationship) { - names[meta.kind].push(name); - } - }); - - return names; - }), - - /** - An array of types directly related to a model. Each type will be - included once, regardless of the number of relationships it has with - the model. - - For example, given a model with this definition: - - ```javascript - App.Blog = DS.Model.extend({ - users: DS.hasMany('user'), - owner: DS.belongsTo('user'), - - posts: DS.hasMany('post') - }); - ``` - - This property would contain the following: - - ```javascript - var relatedTypes = Ember.get(App.Blog, 'relatedTypes'); - //=> [ App.User, App.Post ] - ``` - - @property relatedTypes - @static - @type Ember.Array - @readOnly - */ - relatedTypes: Ember.computed(function() { - var type; - var types = Ember.A(); - - // Loop through each computed property on the class, - // and create an array of the unique types involved - // in relationships - this.eachComputedProperty(function(name, meta) { - if (meta.isRelationship) { - meta.key = name; - type = typeForRelationshipMeta(this.store, meta); - - Ember.assert("You specified a hasMany (" + meta.type + ") on " + meta.parentType + " but " + meta.type + " was not found.", type); - - if (!types.contains(type)) { - Ember.assert("Trying to sideload " + name + " on " + this.toString() + " but the type doesn't exist.", !!type); - types.push(type); - } - } - }); - - return types; - }).cacheable(false).readOnly(), - - /** - A map whose keys are the relationships of a model and whose values are - relationship descriptors. - - For example, given a model with this - definition: - - ```javascript - App.Blog = DS.Model.extend({ - users: DS.hasMany('user'), - owner: DS.belongsTo('user'), - - posts: DS.hasMany('post') - }); - ``` - - This property would contain the following: - - ```javascript - var relationshipsByName = Ember.get(App.Blog, 'relationshipsByName'); - relationshipsByName.get('users'); - //=> { key: 'users', kind: 'hasMany', type: App.User } - relationshipsByName.get('owner'); - //=> { key: 'owner', kind: 'belongsTo', type: App.User } - ``` - - @property relationshipsByName - @static - @type Ember.Map - @readOnly - */ - relationshipsByName: Ember.computed(function() { - var map = Map.create(); - - this.eachComputedProperty(function(name, meta) { - if (meta.isRelationship) { - meta.key = name; - var relationship = relationshipFromMeta(this.store, meta); - relationship.type = typeForRelationshipMeta(this.store, meta); - map.set(name, relationship); - } - }); - - return map; - }).cacheable(false).readOnly(), - - /** - A map whose keys are the fields of the model and whose values are strings - describing the kind of the field. A model's fields are the union of all of its - attributes and relationships. - - For example: - - ```javascript - - App.Blog = DS.Model.extend({ - users: DS.hasMany('user'), - owner: DS.belongsTo('user'), - - posts: DS.hasMany('post'), - - title: DS.attr('string') - }); - - var fields = Ember.get(App.Blog, 'fields'); - fields.forEach(function(field, kind) { - console.log(field, kind); - }); - - // prints: - // users, hasMany - // owner, belongsTo - // posts, hasMany - // title, attribute - ``` - - @property fields - @static - @type Ember.Map - @readOnly - */ - fields: Ember.computed(function() { - var map = Map.create(); - - this.eachComputedProperty(function(name, meta) { - if (meta.isRelationship) { - map.set(name, meta.kind); - } else if (meta.isAttribute) { - map.set(name, 'attribute'); - } - }); - - return map; - }).readOnly(), - - /** - Given a callback, iterates over each of the relationships in the model, - invoking the callback with the name of each relationship and its relationship - descriptor. - - @method eachRelationship - @static - @param {Function} callback the callback to invoke - @param {any} binding the value to which the callback's `this` should be bound - */ - eachRelationship: function(callback, binding) { - get(this, 'relationshipsByName').forEach(function(relationship, name) { - callback.call(binding, name, relationship); - }); - }, - - /** - Given a callback, iterates over each of the types related to a model, - invoking the callback with the related type's class. Each type will be - returned just once, regardless of how many different relationships it has - with a model. - - @method eachRelatedType - @static - @param {Function} callback the callback to invoke - @param {any} binding the value to which the callback's `this` should be bound - */ - eachRelatedType: function(callback, binding) { - get(this, 'relatedTypes').forEach(function(type) { - callback.call(binding, type); - }); - }, - - determineRelationshipType: function(knownSide) { - var knownKey = knownSide.key; - var knownKind = knownSide.kind; - var inverse = this.inverseFor(knownKey); - var key, otherKind; - - if (!inverse) { - return knownKind === 'belongsTo' ? 'oneToNone' : 'manyToNone'; - } - - key = inverse.name; - otherKind = inverse.kind; - - if (otherKind === 'belongsTo') { - return knownKind === 'belongsTo' ? 'oneToOne' : 'manyToOne'; - } else { - return knownKind === 'belongsTo' ? 'oneToMany' : 'manyToMany'; - } - } - - }); - - Model.reopen({ - /** - Given a callback, iterates over each of the relationships in the model, - invoking the callback with the name of each relationship and its relationship - descriptor. - - @method eachRelationship - @param {Function} callback the callback to invoke - @param {any} binding the value to which the callback's `this` should be bound - */ - eachRelationship: function(callback, binding) { - this.constructor.eachRelationship(callback, binding); - }, - - relationshipFor: function(name) { - return get(this.constructor, 'relationshipsByName').get(name); - }, - - inverseFor: function(key) { - return this.constructor.inverseFor(key); - } - - }); - }); -define("ember-data/system/relationships/has_many", - ["ember-data/system/model","exports"], - function(__dependency1__, __exports__) { - "use strict"; - /** - @module ember-data - */ - - var Model = __dependency1__.Model; - - /** - `DS.hasMany` is used to define One-To-Many and Many-To-Many - relationships on a [DS.Model](/api/data/classes/DS.Model.html). - - `DS.hasMany` takes an optional hash as a second parameter, currently - supported options are: - - - `async`: A boolean value used to explicitly declare this to be an async relationship. - - `inverse`: A string used to identify the inverse property on a related model. - - #### One-To-Many - To declare a one-to-many relationship between two models, use - `DS.belongsTo` in combination with `DS.hasMany`, like this: - - ```javascript - App.Post = DS.Model.extend({ - comments: DS.hasMany('comment') - }); - - App.Comment = DS.Model.extend({ - post: DS.belongsTo('post') - }); - ``` - - #### Many-To-Many - To declare a many-to-many relationship between two models, use - `DS.hasMany`: - - ```javascript - App.Post = DS.Model.extend({ - tags: DS.hasMany('tag') - }); - - App.Tag = DS.Model.extend({ - posts: DS.hasMany('post') - }); - ``` - - #### Explicit Inverses - - Ember Data will do its best to discover which relationships map to - one another. In the one-to-many code above, for example, Ember Data - can figure out that changing the `comments` relationship should update - the `post` relationship on the inverse because post is the only - relationship to that model. - - However, sometimes you may have multiple `belongsTo`/`hasManys` for the - same type. You can specify which property on the related model is - the inverse using `DS.hasMany`'s `inverse` option: - - ```javascript - var belongsTo = DS.belongsTo, - hasMany = DS.hasMany; - - App.Comment = DS.Model.extend({ - onePost: belongsTo('post'), - twoPost: belongsTo('post'), - redPost: belongsTo('post'), - bluePost: belongsTo('post') - }); - - App.Post = DS.Model.extend({ - comments: hasMany('comment', { - inverse: 'redPost' - }) - }); - ``` - - You can also specify an inverse on a `belongsTo`, which works how - you'd expect. - - @namespace - @method hasMany - @for DS - @param {String or DS.Model} type the model type of the relationship - @param {Object} options a hash of options - @return {Ember.computed} relationship - */ - function hasMany(type, options) { - if (typeof type === 'object') { - options = type; - type = undefined; - } - - options = options || {}; - - // Metadata about relationships is stored on the meta of - // the relationship. This is used for introspection and - // serialization. Note that `key` is populated lazily - // the first time the CP is called. - var meta = { - type: type, - isRelationship: true, - options: options, - kind: 'hasMany', - key: null - }; - - return Ember.computed(function(key) { - var relationship = this._relationships[key]; - return relationship.getRecords(); - }).meta(meta).readOnly(); - } - - Model.reopen({ - notifyHasManyAdded: function(key, record, idx) { - var relationship = this._relationships[key]; - var manyArray = relationship.manyArray; - manyArray.addRecord(record, idx); - //We need to notifyPropertyChange in the adding case because we need to make sure - //we fetch the newly added record in case it is unloaded - //TODO(Igor): Consider whether we could do this only if the record state is unloaded - this.notifyPropertyChange(key); - }, - - notifyHasManyRemoved: function(key, record) { - var relationship = this._relationships[key]; - var manyArray = relationship.manyArray; - manyArray.removeRecord(record); - } - }); - - - __exports__["default"] = hasMany; - }); -define("ember-data/system/relationships/relationship", - ["ember-data/system/promise_proxies","ember-data/system/map","exports"], - function(__dependency1__, __dependency2__, __exports__) { - "use strict"; - var PromiseManyArray = __dependency1__.PromiseManyArray; - var PromiseObject = __dependency1__.PromiseObject; - var OrderedSet = __dependency2__.OrderedSet; - - var Relationship = function(store, record, inverseKey, relationshipMeta) { - this.members = new OrderedSet(); - this.store = store; - this.key = relationshipMeta.key; - this.inverseKey = inverseKey; - this.record = record; - this.key = relationshipMeta.key; - this.isAsync = relationshipMeta.options.async; - this.relationshipMeta = relationshipMeta; - //This probably breaks for polymorphic relationship in complex scenarios, due to - //multiple possible typeKeys - this.inverseKeyForImplicit = this.store.modelFor(this.record.constructor).typeKey + this.key; - //Cached promise when fetching the relationship from a link - this.linkPromise = null; - }; - - Relationship.prototype = { - constructor: Relationship, - - destroy: Ember.K, - - clear: function() { - this.members.forEach(function(member) { - this.removeRecord(member); - }, this); - }, - - disconnect: function(){ - this.members.forEach(function(member) { - this.removeRecordFromInverse(member); - }, this); - }, - - reconnect: function(){ - this.members.forEach(function(member) { - this.addRecordToInverse(member); - }, this); - }, - - removeRecords: function(records){ - var that = this; - records.forEach(function(record){ - that.removeRecord(record); - }); - }, - - addRecords: function(records, idx){ - var that = this; - records.forEach(function(record){ - that.addRecord(record, idx); - if (idx !== undefined) { - idx++; - } - }); - }, - - addRecord: function(record, idx) { - if (!this.members.has(record)) { - this.members.add(record); - this.notifyRecordRelationshipAdded(record, idx); - if (this.inverseKey) { - record._relationships[this.inverseKey].addRecord(this.record); - } else { - if (!record._implicitRelationships[this.inverseKeyForImplicit]) { - record._implicitRelationships[this.inverseKeyForImplicit] = new Relationship(this.store, record, this.key, {options:{}}); - } - record._implicitRelationships[this.inverseKeyForImplicit].addRecord(this.record); - } - this.record.updateRecordArrays(); - } - }, - - removeRecord: function(record) { - if (this.members.has(record)) { - this.removeRecordFromOwn(record); - if (this.inverseKey) { - this.removeRecordFromInverse(record); - } else { - if (record._implicitRelationships[this.inverseKeyForImplicit]) { - record._implicitRelationships[this.inverseKeyForImplicit].removeRecord(this.record); - } - } - } - }, - - addRecordToInverse: function(record) { - if (this.inverseKey) { - record._relationships[this.inverseKey].addRecord(this.record); - } - }, - - removeRecordFromInverse: function(record) { - var inverseRelationship = record._relationships[this.inverseKey]; - //Need to check for existence, as the record might unloading at the moment - if (inverseRelationship) { - inverseRelationship.removeRecordFromOwn(this.record); - } - }, - - removeRecordFromOwn: function(record) { - this.members["delete"](record); - this.notifyRecordRelationshipRemoved(record); - this.record.updateRecordArrays(); - }, - - updateLink: function(link) { - if (link !== this.link) { - this.link = link; - this.linkPromise = null; - this.record.notifyPropertyChange(this.key); - } - }, - - findLink: function() { - if (this.linkPromise) { - return this.linkPromise; - } else { - var promise = this.fetchLink(); - this.linkPromise = promise; - return promise.then(function(result) { - return result; - }); - } - }, - - updateRecordsFromAdapter: function(records) { - //TODO Once we have adapter support, we need to handle updated and canonical changes - this.computeChanges(records); - }, - - notifyRecordRelationshipAdded: Ember.K, - notifyRecordRelationshipRemoved: Ember.K - }; - - var ManyRelationship = function(store, record, inverseKey, relationshipMeta) { - this._super$constructor(store, record, inverseKey, relationshipMeta); - this.belongsToType = relationshipMeta.type; - this.manyArray = store.recordArrayManager.createManyArray(this.belongsToType, Ember.A()); - this.manyArray.relationship = this; - this.isPolymorphic = relationshipMeta.options.polymorphic; - this.manyArray.isPolymorphic = this.isPolymorphic; - }; - - ManyRelationship.prototype = Object.create(Relationship.prototype); - ManyRelationship.prototype.constructor = ManyRelationship; - ManyRelationship.prototype._super$constructor = Relationship; - - ManyRelationship.prototype.destroy = function() { - this.manyArray.destroy(); - }; - - ManyRelationship.prototype.notifyRecordRelationshipAdded = function(record, idx) { - Ember.assert("You cannot add '" + record.constructor.typeKey + "' records to this relationship (only '" + this.belongsToType.typeKey + "' allowed)", !this.belongsToType || record instanceof this.belongsToType); - this.record.notifyHasManyAdded(this.key, record, idx); - }; - - ManyRelationship.prototype.notifyRecordRelationshipRemoved = function(record) { - this.record.notifyHasManyRemoved(this.key, record); - }; - - ManyRelationship.prototype.reload = function() { - var self = this; - if (this.link) { - return this.fetchLink(); - } else { - return this.store.scheduleFetchMany(this.manyArray.toArray()).then(function() { - //Goes away after the manyArray refactor - self.manyArray.set('isLoaded', true); - return self.manyArray; - }); - } - }; - - ManyRelationship.prototype.computeChanges = function(records) { - var members = this.members; - var recordsToRemove = []; - var length; - var record; - var i; - - records = setForArray(records); - - members.forEach(function(member) { - if (records.has(member)) return; - - recordsToRemove.push(member); - }); - this.removeRecords(recordsToRemove); - - var hasManyArray = this.manyArray; - - // Using records.toArray() since currently using - // removeRecord can modify length, messing stuff up - // forEach since it directly looks at "length" each - // iteration - records = records.toArray(); - length = records.length; - for (i = 0; i < length; i++){ - record = records[i]; - //Need to preserve the order of incoming records - if (hasManyArray.objectAt(i) === record ) { - continue; - } - this.removeRecord(record); - this.addRecord(record, i); - } - }; - - ManyRelationship.prototype.fetchLink = function() { - var self = this; - return this.store.findHasMany(this.record, this.link, this.relationshipMeta).then(function(records){ - self.updateRecordsFromAdapter(records); - return self.manyArray; - }); - }; - - ManyRelationship.prototype.findRecords = function() { - var manyArray = this.manyArray; - return this.store.findMany(manyArray.toArray()).then(function(){ - //Goes away after the manyArray refactor - manyArray.set('isLoaded', true); - return manyArray; - }); - }; - - ManyRelationship.prototype.getRecords = function() { - if (this.isAsync) { - var self = this; - var promise; - if (this.link) { - promise = this.findLink().then(function() { - return self.findRecords(); - }); - } else { - promise = this.findRecords(); - } - return PromiseManyArray.create({ - content: this.manyArray, - promise: promise - }); - } else { - Ember.assert("You looked up the '" + this.key + "' relationship on a '" + this.record.constructor.typeKey + "' with id " + this.record.get('id') + " but some of the associated records were not loaded. Either make sure they are all loaded together with the parent record, or specify that the relationship is async (`DS.hasMany({ async: true })`)", this.manyArray.isEvery('isEmpty', false)); - - this.manyArray.set('isLoaded', true); - return this.manyArray; - } - }; - - var BelongsToRelationship = function(store, record, inverseKey, relationshipMeta) { - this._super$constructor(store, record, inverseKey, relationshipMeta); - this.record = record; - this.key = relationshipMeta.key; - this.inverseRecord = null; - }; - - BelongsToRelationship.prototype = Object.create(Relationship.prototype); - BelongsToRelationship.prototype.constructor = BelongsToRelationship; - BelongsToRelationship.prototype._super$constructor = Relationship; - - BelongsToRelationship.prototype.setRecord = function(newRecord) { - if (newRecord) { - this.addRecord(newRecord); - } else if (this.inverseRecord) { - this.removeRecord(this.inverseRecord); - } - }; - - BelongsToRelationship.prototype._super$addRecord = Relationship.prototype.addRecord; - BelongsToRelationship.prototype.addRecord = function(newRecord) { - if (this.members.has(newRecord)){ return;} - var type = this.relationshipMeta.type; - Ember.assert("You can only add a '" + type.typeKey + "' record to this relationship", newRecord instanceof type); - - if (this.inverseRecord) { - this.removeRecord(this.inverseRecord); - } - - this.inverseRecord = newRecord; - this._super$addRecord(newRecord); - }; - - BelongsToRelationship.prototype.setRecordPromise = function(newPromise) { - var content = newPromise.get && newPromise.get('content'); - Ember.assert("You passed in a promise that did not originate from an EmberData relationship. You can only pass promises that come from a belongsTo or hasMany relationship to the get call.", content !== undefined); - this.setRecord(content); - }; - - BelongsToRelationship.prototype.notifyRecordRelationshipAdded = function(newRecord) { - this.record.notifyBelongsToAdded(this.key, this); - }; - - BelongsToRelationship.prototype.notifyRecordRelationshipRemoved = function(record) { - this.record.notifyBelongsToRemoved(this.key, this); - }; - - BelongsToRelationship.prototype._super$removeRecordFromOwn = Relationship.prototype.removeRecordFromOwn; - BelongsToRelationship.prototype.removeRecordFromOwn = function(record) { - if (!this.members.has(record)){ return;} - this._super$removeRecordFromOwn(record); - this.inverseRecord = null; - }; - - BelongsToRelationship.prototype.findRecord = function() { - if (this.inverseRecord) { - return this.store._findByRecord(this.inverseRecord); - } else { - return Ember.RSVP.Promise.resolve(null); - } - }; - - BelongsToRelationship.prototype.fetchLink = function() { - var self = this; - return this.store.findBelongsTo(this.record, this.link, this.relationshipMeta).then(function(record){ - self.addRecord(record); - return record; - }); - }; - - BelongsToRelationship.prototype.getRecord = function() { - if (this.isAsync) { - var promise; - if (this.link){ - var self = this; - promise = this.findLink().then(function() { - return self.findRecord(); - }); - } else { - promise = this.findRecord(); - } - - return PromiseObject.create({ - promise: promise, - content: this.inverseRecord - }); - } else { - Ember.assert("You looked up the '" + this.key + "' relationship on a '" + this.record.constructor.typeKey + "' with id " + this.record.get('id') + " but some of the associated records were not loaded. Either make sure they are all loaded together with the parent record, or specify that the relationship is async (`DS.belongsTo({ async: true })`)", this.inverseRecord === null || !this.inverseRecord.get('isEmpty')); - return this.inverseRecord; - } - }; - - function setForArray(array) { - var set = new OrderedSet(); - - if (array) { - for (var i=0, l=array.length; i= 1); - Ember.assert("You may not pass `" + id + "` as id to the store's find method", arguments.length === 1 || !Ember.isNone(id)); - - if (arguments.length === 1) { - return this.findAll(type); - } - - // We are passed a query instead of an id. - if (Ember.typeOf(id) === 'object') { - return this.findQuery(type, id); - } - - return this.findById(type, coerceId(id), preload); - }, - - /** - This method returns a record for a given type and id combination. - - @method findById - @private - @param {String or subclass of DS.Model} type - @param {String|Integer} id - @param {Object} preload - optional set of attributes and relationships passed in either as IDs or as actual models - @return {Promise} promise - */ - findById: function(typeName, id, preload) { - - var type = this.modelFor(typeName); - var record = this.recordForId(type, id); - - return this._findByRecord(record, preload); - }, - - _findByRecord: function(record, preload) { - var fetchedRecord; - - if (preload) { - record._preloadData(preload); - } - - if (get(record, 'isEmpty')) { - fetchedRecord = this.scheduleFetch(record); - //TODO double check about reloading - } else if (get(record, 'isLoading')){ - fetchedRecord = record._loadingPromise; - } - - return promiseObject(fetchedRecord || record, "DS: Store#findByRecord " + record.typeKey + " with id: " + get(record, 'id')); - }, - - /** - This method makes a series of requests to the adapter's `find` method - and returns a promise that resolves once they are all loaded. - - @private - @method findByIds - @param {String} type - @param {Array} ids - @return {Promise} promise - */ - findByIds: function(type, ids) { - var store = this; - - return promiseArray(Ember.RSVP.all(map(ids, function(id) { - return store.findById(type, id); - })).then(Ember.A, null, "DS: Store#findByIds of " + type + " complete")); - }, - - /** - This method is called by `findById` if it discovers that a particular - type/id pair hasn't been loaded yet to kick off a request to the - adapter. - - @method fetchRecord - @private - @param {DS.Model} record - @return {Promise} promise - */ - fetchRecord: function(record) { - var type = record.constructor; - var id = get(record, 'id'); - var adapter = this.adapterFor(type); - - Ember.assert("You tried to find a record but you have no adapter (for " + type + ")", adapter); - Ember.assert("You tried to find a record but your adapter (for " + type + ") does not implement 'find'", adapter.find); - - var promise = _find(adapter, this, type, id, record); - return promise; - }, - - scheduleFetchMany: function(records) { - return Ember.RSVP.all(map(records, this.scheduleFetch, this)); - }, - - scheduleFetch: function(record) { - var type = record.constructor; - if (isNone(record)) { return null; } - if (record._loadingPromise) { return record._loadingPromise; } - - var resolver = Ember.RSVP.defer('Fetching ' + type + 'with id: ' + record.get('id')); - var recordResolverPair = { - record: record, - resolver: resolver - }; - var promise = resolver.promise; - - record.loadingData(promise); - - if (!this._pendingFetch.get(type)){ - this._pendingFetch.set(type, [recordResolverPair]); - } else { - this._pendingFetch.get(type).push(recordResolverPair); - } - Ember.run.scheduleOnce('afterRender', this, this.flushAllPendingFetches); - - return promise; - }, - - flushAllPendingFetches: function(){ - if (this.isDestroyed || this.isDestroying) { - return; - } - - this._pendingFetch.forEach(this._flushPendingFetchForType, this); - this._pendingFetch = Map.create(); - }, - - _flushPendingFetchForType: function (recordResolverPairs, type) { - var store = this; - var adapter = store.adapterFor(type); - var shouldCoalesce = !!adapter.findMany && adapter.coalesceFindRequests; - var records = Ember.A(recordResolverPairs).mapBy('record'); - - function _fetchRecord(recordResolverPair) { - recordResolverPair.resolver.resolve(store.fetchRecord(recordResolverPair.record)); - } - - function resolveFoundRecords(records) { - forEach(records, function(record){ - var pair = Ember.A(recordResolverPairs).findBy('record', record); - if (pair){ - var resolver = pair.resolver; - resolver.resolve(record); - } - }); - } - - function makeMissingRecordsRejector(requestedRecords) { - return function rejectMissingRecords(resolvedRecords) { - var missingRecords = requestedRecords.without(resolvedRecords); - rejectRecords(missingRecords); - }; - } - - function makeRecordsRejector(records) { - return function (error) { - rejectRecords(records, error); - }; - } - - function rejectRecords(records, error) { - forEach(records, function(record){ - var pair = Ember.A(recordResolverPairs).findBy('record', record); - if (pair){ - var resolver = pair.resolver; - resolver.reject(error); - } - }); - } - - if (recordResolverPairs.length === 1) { - _fetchRecord(recordResolverPairs[0]); - } else if (shouldCoalesce) { - var groups = adapter.groupRecordsForFindMany(this, records); - forEach(groups, function (groupOfRecords) { - var requestedRecords = Ember.A(groupOfRecords); - var ids = requestedRecords.mapBy('id'); - if (ids.length > 1) { - _findMany(adapter, store, type, ids, requestedRecords). - then(resolveFoundRecords). - then(makeMissingRecordsRejector(requestedRecords)). - then(null, makeRecordsRejector(requestedRecords)); - } else if (ids.length === 1) { - var pair = Ember.A(recordResolverPairs).findBy('record', groupOfRecords[0]); - _fetchRecord(pair); - } else { - Ember.assert("You cannot return an empty array from adapter's method groupRecordsForFindMany", false); - } - }); - } else { - forEach(recordResolverPairs, _fetchRecord); - } - }, - - /** - Get a record by a given type and ID without triggering a fetch. - - This method will synchronously return the record if it is available in the store, - otherwise it will return `null`. A record is available if it has been fetched earlier, or - pushed manually into the store. - - _Note: This is an synchronous method and does not return a promise._ - - ```js - var post = store.getById('post', 1); - - post.get('id'); // 1 - ``` - - @method getById - @param {String or subclass of DS.Model} type - @param {String|Integer} id - @return {DS.Model|null} record - */ - getById: function(type, id) { - if (this.hasRecordForId(type, id)) { - return this.recordForId(type, id); - } else { - return null; - } - }, - - /** - This method is called by the record's `reload` method. - - This method calls the adapter's `find` method, which returns a promise. When - **that** promise resolves, `reloadRecord` will resolve the promise returned - by the record's `reload`. - - @method reloadRecord - @private - @param {DS.Model} record - @return {Promise} promise - */ - reloadRecord: function(record) { - var type = record.constructor; - var adapter = this.adapterFor(type); - var id = get(record, 'id'); - - Ember.assert("You cannot reload a record without an ID", id); - Ember.assert("You tried to reload a record but you have no adapter (for " + type + ")", adapter); - Ember.assert("You tried to reload a record but your adapter does not implement `find`", adapter.find); - - return this.scheduleFetch(record); - }, - - /** - Returns true if a record for a given type and ID is already loaded. - - @method hasRecordForId - @param {String or subclass of DS.Model} type - @param {String|Integer} id - @return {Boolean} - */ - hasRecordForId: function(typeName, inputId) { - var type = this.modelFor(typeName); - var id = coerceId(inputId); - return !!this.typeMapFor(type).idToRecord[id]; - }, - - /** - Returns id record for a given type and ID. If one isn't already loaded, - it builds a new record and leaves it in the `empty` state. - - @method recordForId - @private - @param {String or subclass of DS.Model} type - @param {String|Integer} id - @return {DS.Model} record - */ - recordForId: function(typeName, inputId) { - var type = this.modelFor(typeName); - var id = coerceId(inputId); - var idToRecord = this.typeMapFor(type).idToRecord; - var record = idToRecord[id]; - - if (!record || !idToRecord[id]) { - record = this.buildRecord(type, id); - } - - return record; - }, - - /** - @method findMany - @private - @param {DS.Model} owner - @param {Array} records - @param {String or subclass of DS.Model} type - @param {Resolver} resolver - @return {DS.ManyArray} records - */ - findMany: function(records) { - var store = this; - return Promise.all( map(records, function(record) { - return store._findByRecord(record); - })); - }, - - - /** - If a relationship was originally populated by the adapter as a link - (as opposed to a list of IDs), this method is called when the - relationship is fetched. - - The link (which is usually a URL) is passed through unchanged, so the - adapter can make whatever request it wants. - - The usual use-case is for the server to register a URL as a link, and - then use that URL in the future to make a request for the relationship. - - @method findHasMany - @private - @param {DS.Model} owner - @param {any} link - @param {String or subclass of DS.Model} type - @return {Promise} promise - */ - findHasMany: function(owner, link, type) { - var adapter = this.adapterFor(owner.constructor); - - Ember.assert("You tried to load a hasMany relationship but you have no adapter (for " + owner.constructor + ")", adapter); - Ember.assert("You tried to load a hasMany relationship from a specified `link` in the original payload but your adapter does not implement `findHasMany`", adapter.findHasMany); - - return _findHasMany(adapter, this, owner, link, type); - }, - - /** - @method findBelongsTo - @private - @param {DS.Model} owner - @param {any} link - @param {Relationship} relationship - @return {Promise} promise - */ - findBelongsTo: function(owner, link, relationship) { - var adapter = this.adapterFor(owner.constructor); - - Ember.assert("You tried to load a belongsTo relationship but you have no adapter (for " + owner.constructor + ")", adapter); - Ember.assert("You tried to load a belongsTo relationship from a specified `link` in the original payload but your adapter does not implement `findBelongsTo`", adapter.findBelongsTo); - - return _findBelongsTo(adapter, this, owner, link, relationship); - }, - - /** - This method delegates a query to the adapter. This is the one place where - adapter-level semantics are exposed to the application. - - Exposing queries this way seems preferable to creating an abstract query - language for all server-side queries, and then require all adapters to - implement them. - - This method returns a promise, which is resolved with a `RecordArray` - once the server returns. - - @method findQuery - @private - @param {String or subclass of DS.Model} type - @param {any} query an opaque query to be used by the adapter - @return {Promise} promise - */ - findQuery: function(typeName, query) { - var type = this.modelFor(typeName); - var array = this.recordArrayManager - .createAdapterPopulatedRecordArray(type, query); - - var adapter = this.adapterFor(type); - - Ember.assert("You tried to load a query but you have no adapter (for " + type + ")", adapter); - Ember.assert("You tried to load a query but your adapter does not implement `findQuery`", adapter.findQuery); - - return promiseArray(_findQuery(adapter, this, type, query, array)); - }, - - /** - This method returns an array of all records adapter can find. - It triggers the adapter's `findAll` method to give it an opportunity to populate - the array with records of that type. - - @method findAll - @private - @param {String or subclass of DS.Model} type - @return {DS.AdapterPopulatedRecordArray} - */ - findAll: function(typeName) { - var type = this.modelFor(typeName); - - return this.fetchAll(type, this.all(type)); - }, - - /** - @method fetchAll - @private - @param {DS.Model} type - @param {DS.RecordArray} array - @return {Promise} promise - */ - fetchAll: function(type, array) { - var adapter = this.adapterFor(type); - var sinceToken = this.typeMapFor(type).metadata.since; - - set(array, 'isUpdating', true); - - Ember.assert("You tried to load all records but you have no adapter (for " + type + ")", adapter); - Ember.assert("You tried to load all records but your adapter does not implement `findAll`", adapter.findAll); - - return promiseArray(_findAll(adapter, this, type, sinceToken)); - }, - - /** - @method didUpdateAll - @param {DS.Model} type - */ - didUpdateAll: function(type) { - var findAllCache = this.typeMapFor(type).findAllCache; - set(findAllCache, 'isUpdating', false); - }, - - /** - This method returns a filtered array that contains all of the known records - for a given type. - - Note that because it's just a filter, it will have any locally - created records of the type. - - Also note that multiple calls to `all` for a given type will always - return the same RecordArray. - - Example - - ```javascript - var localPosts = store.all('post'); - ``` - - @method all - @param {String or subclass of DS.Model} type - @return {DS.RecordArray} - */ - all: function(typeName) { - var type = this.modelFor(typeName); - var typeMap = this.typeMapFor(type); - var findAllCache = typeMap.findAllCache; - - if (findAllCache) { return findAllCache; } - - var array = this.recordArrayManager.createRecordArray(type); - - typeMap.findAllCache = array; - return array; - }, - - - /** - This method unloads all of the known records for a given type. - - ```javascript - store.unloadAll('post'); - ``` - - @method unloadAll - @param {String or subclass of DS.Model} type - */ - unloadAll: function(type) { - var modelType = this.modelFor(type); - var typeMap = this.typeMapFor(modelType); - var records = typeMap.records.slice(); - var record; - - for (var i = 0; i < records.length; i++) { - record = records[i]; - record.unloadRecord(); - record.destroy(); // maybe within unloadRecord - } - - typeMap.findAllCache = null; - }, - - /** - Takes a type and filter function, and returns a live RecordArray that - remains up to date as new records are loaded into the store or created - locally. - - The callback function takes a materialized record, and returns true - if the record should be included in the filter and false if it should - not. - - The filter function is called once on all records for the type when - it is created, and then once on each newly loaded or created record. - - If any of a record's properties change, or if it changes state, the - filter function will be invoked again to determine whether it should - still be in the array. - - Optionally you can pass a query which will be triggered at first. The - results returned by the server could then appear in the filter if they - match the filter function. - - Example - - ```javascript - store.filter('post', {unread: true}, function(post) { - return post.get('unread'); - }).then(function(unreadPosts) { - unreadPosts.get('length'); // 5 - var unreadPost = unreadPosts.objectAt(0); - unreadPost.set('unread', false); - unreadPosts.get('length'); // 4 - }); - ``` - - @method filter - @param {String or subclass of DS.Model} type - @param {Object} query optional query - @param {Function} filter - @return {DS.PromiseArray} - */ - filter: function(type, query, filter) { - var promise; - var length = arguments.length; - var array; - var hasQuery = length === 3; - - // allow an optional server query - if (hasQuery) { - promise = this.findQuery(type, query); - } else if (arguments.length === 2) { - filter = query; - } - - type = this.modelFor(type); - - if (hasQuery) { - array = this.recordArrayManager.createFilteredRecordArray(type, filter, query); - } else { - array = this.recordArrayManager.createFilteredRecordArray(type, filter); - } - - promise = promise || Promise.cast(array); - - - return promiseArray(promise.then(function() { - return array; - }, null, "DS: Store#filter of " + type)); - }, - - /** - This method returns if a certain record is already loaded - in the store. Use this function to know beforehand if a find() - will result in a request or that it will be a cache hit. - - Example - - ```javascript - store.recordIsLoaded('post', 1); // false - store.find('post', 1).then(function() { - store.recordIsLoaded('post', 1); // true - }); - ``` - - @method recordIsLoaded - @param {String or subclass of DS.Model} type - @param {string} id - @return {boolean} - */ - recordIsLoaded: function(type, id) { - if (!this.hasRecordForId(type, id)) { return false; } - return !get(this.recordForId(type, id), 'isEmpty'); - }, - - /** - This method returns the metadata for a specific type. - - @method metadataFor - @param {String or subclass of DS.Model} type - @return {object} - */ - metadataFor: function(type) { - type = this.modelFor(type); - return this.typeMapFor(type).metadata; - }, - - // ............ - // . UPDATING . - // ............ - - /** - If the adapter updates attributes or acknowledges creation - or deletion, the record will notify the store to update its - membership in any filters. - To avoid thrashing, this method is invoked only once per - - run loop per record. - - @method dataWasUpdated - @private - @param {Class} type - @param {DS.Model} record - */ - dataWasUpdated: function(type, record) { - this.recordArrayManager.recordDidChange(record); - }, - - // .............. - // . PERSISTING . - // .............. - - /** - This method is called by `record.save`, and gets passed a - resolver for the promise that `record.save` returns. - - It schedules saving to happen at the end of the run loop. - - @method scheduleSave - @private - @param {DS.Model} record - @param {Resolver} resolver - */ - scheduleSave: function(record, resolver) { - record.adapterWillCommit(); - this._pendingSave.push([record, resolver]); - once(this, 'flushPendingSave'); - }, - - /** - This method is called at the end of the run loop, and - flushes any records passed into `scheduleSave` - - @method flushPendingSave - @private - */ - flushPendingSave: function() { - var pending = this._pendingSave.slice(); - this._pendingSave = []; - - forEach(pending, function(tuple) { - var record = tuple[0], resolver = tuple[1]; - var adapter = this.adapterFor(record.constructor); - var operation; - - if (get(record, 'currentState.stateName') === 'root.deleted.saved') { - return resolver.resolve(record); - } else if (get(record, 'isNew')) { - operation = 'createRecord'; - } else if (get(record, 'isDeleted')) { - operation = 'deleteRecord'; - } else { - operation = 'updateRecord'; - } - - resolver.resolve(_commit(adapter, this, operation, record)); - }, this); - }, - - /** - This method is called once the promise returned by an - adapter's `createRecord`, `updateRecord` or `deleteRecord` - is resolved. - - If the data provides a server-generated ID, it will - update the record and the store's indexes. - - @method didSaveRecord - @private - @param {DS.Model} record the in-flight record - @param {Object} data optional data (see above) - */ - didSaveRecord: function(record, data) { - if (data) { - // normalize relationship IDs into records - data = normalizeRelationships(this, record.constructor, data, record); - setupRelationships(this, record, data); - - this.updateId(record, data); - } - - record.adapterDidCommit(data); - }, - - /** - This method is called once the promise returned by an - adapter's `createRecord`, `updateRecord` or `deleteRecord` - is rejected with a `DS.InvalidError`. - - @method recordWasInvalid - @private - @param {DS.Model} record - @param {Object} errors - */ - recordWasInvalid: function(record, errors) { - record.adapterDidInvalidate(errors); - }, - - /** - This method is called once the promise returned by an - adapter's `createRecord`, `updateRecord` or `deleteRecord` - is rejected (with anything other than a `DS.InvalidError`). - - @method recordWasError - @private - @param {DS.Model} record - */ - recordWasError: function(record) { - record.adapterDidError(); - }, - - /** - When an adapter's `createRecord`, `updateRecord` or `deleteRecord` - resolves with data, this method extracts the ID from the supplied - data. - - @method updateId - @private - @param {DS.Model} record - @param {Object} data - */ - updateId: function(record, data) { - var oldId = get(record, 'id'); - var id = coerceId(data.id); - - Ember.assert("An adapter cannot assign a new id to a record that already has an id. " + record + " had id: " + oldId + " and you tried to update it with " + id + ". This likely happened because your server returned data in response to a find or update that had a different id than the one you sent.", oldId === null || id === oldId); - - this.typeMapFor(record.constructor).idToRecord[id] = record; - - set(record, 'id', id); - }, - - /** - Returns a map of IDs to client IDs for a given type. - - @method typeMapFor - @private - @param {subclass of DS.Model} type - @return {Object} typeMap - */ - typeMapFor: function(type) { - var typeMaps = get(this, 'typeMaps'); - var guid = Ember.guidFor(type); - var typeMap; - - typeMap = typeMaps[guid]; - - if (typeMap) { return typeMap; } - - typeMap = { - idToRecord: Object.create(null), - records: [], - metadata: Object.create(null), - type: type - }; - - typeMaps[guid] = typeMap; - - return typeMap; - }, - - // ................ - // . LOADING DATA . - // ................ - - /** - This internal method is used by `push`. - - @method _load - @private - @param {String or subclass of DS.Model} type - @param {Object} data - @param {Boolean} partial the data should be merged into - the existing data, not replace it. - */ - _load: function(type, data, partial) { - var id = coerceId(data.id); - var record = this.recordForId(type, id); - - record.setupData(data, partial); - this.recordArrayManager.recordDidChange(record); - - return record; - }, - - /** - Returns a model class for a particular key. Used by - methods that take a type key (like `find`, `createRecord`, - etc.) - - @method modelFor - @param {String or subclass of DS.Model} key - @return {subclass of DS.Model} - */ - modelFor: function(key) { - var factory; - - if (typeof key === 'string') { - factory = this.modelFactoryFor(key); - if (!factory) { - throw new Ember.Error("No model was found for '" + key + "'"); - } - factory.typeKey = factory.typeKey || this._normalizeTypeKey(key); - } else { - // A factory already supplied. Ensure it has a normalized key. - factory = key; - if (factory.typeKey) { - factory.typeKey = this._normalizeTypeKey(factory.typeKey); - } - } - - factory.store = this; - return factory; - }, - - modelFactoryFor: function(key){ - return this.container.lookupFactory('model:' + key); - }, - - /** - Push some data for a given type into the store. - - This method expects normalized data: - - * The ID is a key named `id` (an ID is mandatory) - * The names of attributes are the ones you used in - your model's `DS.attr`s. - * Your relationships must be: - * represented as IDs or Arrays of IDs - * represented as model instances - * represented as URLs, under the `links` key - - For this model: - - ```js - App.Person = DS.Model.extend({ - firstName: DS.attr(), - lastName: DS.attr(), - - children: DS.hasMany('person') - }); - ``` - - To represent the children as IDs: - - ```js - { - id: 1, - firstName: "Tom", - lastName: "Dale", - children: [1, 2, 3] - } - ``` - - To represent the children relationship as a URL: - - ```js - { - id: 1, - firstName: "Tom", - lastName: "Dale", - links: { - children: "/people/1/children" - } - } - ``` - - If you're streaming data or implementing an adapter, - make sure that you have converted the incoming data - into this form. - - This method can be used both to push in brand new - records, as well as to update existing records. - - @method push - @param {String or subclass of DS.Model} type - @param {Object} data - @return {DS.Model} the record that was created or - updated. - */ - push: function(typeName, data, _partial) { - // _partial is an internal param used by `update`. - // If passed, it means that the data should be - // merged into the existing data, not replace it. - Ember.assert("Expected an object as `data` in a call to push for " + typeName + " , but was " + data, Ember.typeOf(data) === 'object'); - Ember.assert("You must include an `id` for " + typeName + " in an object passed to `push`", data.id != null); - - var type = this.modelFor(typeName); - - // If the payload contains relationships that are specified as - // IDs, normalizeRelationships will convert them into DS.Model instances - // (possibly unloaded) before we push the payload into the - // store. - - data = normalizeRelationships(this, type, data); - - // Actually load the record into the store. - - this._load(type, data, _partial); - - var record = this.recordForId(type, data.id); - - // Now that the pushed record as well as any related records - // are in the store, create the data structures used to track - // relationships. - setupRelationships(this, record, data); - - return record; - }, - - /** - Push some raw data into the store. - - This method can be used both to push in brand new - records, as well as to update existing records. You - can push in more than one type of object at once. - All objects should be in the format expected by the - serializer. - - ```js - App.ApplicationSerializer = DS.ActiveModelSerializer; - - var pushData = { - posts: [ - {id: 1, post_title: "Great post", comment_ids: [2]} - ], - comments: [ - {id: 2, comment_body: "Insightful comment"} - ] - } - - store.pushPayload(pushData); - ``` - - By default, the data will be deserialized using a default - serializer (the application serializer if it exists). - - Alternatively, `pushPayload` will accept a model type which - will determine which serializer will process the payload. - However, the serializer itself (processing this data via - `normalizePayload`) will not know which model it is - deserializing. - - ```js - App.ApplicationSerializer = DS.ActiveModelSerializer; - App.PostSerializer = DS.JSONSerializer; - store.pushPayload('comment', pushData); // Will use the ApplicationSerializer - store.pushPayload('post', pushData); // Will use the PostSerializer - ``` - - @method pushPayload - @param {String} type Optionally, a model used to determine which serializer will be used - @param {Object} payload - */ - pushPayload: function (type, inputPayload) { - var serializer; - var payload; - if (!inputPayload) { - payload = type; - serializer = defaultSerializer(this.container); - Ember.assert("You cannot use `store#pushPayload` without a type unless your default serializer defines `pushPayload`", serializer.pushPayload); - } else { - payload = inputPayload; - serializer = this.serializerFor(type); - } - serializer.pushPayload(this, payload); - }, - - /** - `normalize` converts a json payload into the normalized form that - [push](#method_push) expects. - - Example - - ```js - socket.on('message', function(message) { - var modelName = message.model; - var data = message.data; - store.push(modelName, store.normalize(modelName, data)); - }); - ``` - - @method normalize - @param {String} type The name of the model type for this payload - @param {Object} payload - @return {Object} The normalized payload - */ - normalize: function (type, payload) { - var serializer = this.serializerFor(type); - var model = this.modelFor(type); - return serializer.normalize(model, payload); - }, - - /** - Update existing records in the store. Unlike [push](#method_push), - update will merge the new data properties with the existing - properties. This makes it safe to use with a subset of record - attributes. This method expects normalized data. - - `update` is useful if your app broadcasts partial updates to - records. - - ```js - App.Person = DS.Model.extend({ - firstName: DS.attr('string'), - lastName: DS.attr('string') - }); - - store.get('person', 1).then(function(tom) { - tom.get('firstName'); // Tom - tom.get('lastName'); // Dale - - var updateEvent = {id: 1, firstName: "TomHuda"}; - store.update('person', updateEvent); - - tom.get('firstName'); // TomHuda - tom.get('lastName'); // Dale - }); - ``` - - @method update - @param {String} type - @param {Object} data - @return {DS.Model} the record that was updated. - */ - update: function(type, data) { - Ember.assert("You must include an `id` for " + type + " in a hash passed to `update`", data.id != null); - - return this.push(type, data, true); - }, - - /** - If you have an Array of normalized data to push, - you can call `pushMany` with the Array, and it will - call `push` repeatedly for you. - - @method pushMany - @param {String or subclass of DS.Model} type - @param {Array} datas - @return {Array} - */ - pushMany: function(type, datas) { - var length = datas.length; - var result = new Array(length); - - for (var i = 0; i < length; i++) { - result[i] = this.push(type, datas[i]); - } - - return result; - }, - - /** - If you have some metadata to set for a type - you can call `metaForType`. - - @method metaForType - @param {String or subclass of DS.Model} type - @param {Object} metadata - */ - metaForType: function(typeName, metadata) { - var type = this.modelFor(typeName); - - Ember.merge(this.typeMapFor(type).metadata, metadata); - }, - - /** - Build a brand new record for a given type, ID, and - initial data. - - @method buildRecord - @private - @param {subclass of DS.Model} type - @param {String} id - @param {Object} data - @return {DS.Model} record - */ - buildRecord: function(type, id, data) { - var typeMap = this.typeMapFor(type); - var idToRecord = typeMap.idToRecord; - - Ember.assert('The id ' + id + ' has already been used with another record of type ' + type.toString() + '.', !id || !idToRecord[id]); - Ember.assert("`" + Ember.inspect(type)+ "` does not appear to be an ember-data model", (typeof type._create === 'function') ); - - // lookupFactory should really return an object that creates - // instances with the injections applied - var record = type._create({ - id: id, - store: this, - container: this.container - }); - - if (data) { - record.setupData(data); - } - - // if we're creating an item, this process will be done - // later, once the object has been persisted. - if (id) { - idToRecord[id] = record; - } - - typeMap.records.push(record); - - return record; - }, - - // ............... - // . DESTRUCTION . - // ............... - - /** - When a record is destroyed, this un-indexes it and - removes it from any record arrays so it can be GCed. - - @method dematerializeRecord - @private - @param {DS.Model} record - */ - dematerializeRecord: function(record) { - var type = record.constructor; - var typeMap = this.typeMapFor(type); - var id = get(record, 'id'); - - record.updateRecordArrays(); - - if (id) { - delete typeMap.idToRecord[id]; - } - - var loc = indexOf(typeMap.records, record); - typeMap.records.splice(loc, 1); - }, - - // ...................... - // . PER-TYPE ADAPTERS - // ...................... - - /** - Returns the adapter for a given type. - - @method adapterFor - @private - @param {subclass of DS.Model} type - @return DS.Adapter - */ - adapterFor: function(type) { - var container = this.container, adapter; - - if (container) { - adapter = container.lookup('adapter:' + type.typeKey) || container.lookup('adapter:application'); - } - - return adapter || get(this, 'defaultAdapter'); - }, - - // .............................. - // . RECORD CHANGE NOTIFICATION . - // .............................. - - /** - Returns an instance of the serializer for a given type. For - example, `serializerFor('person')` will return an instance of - `App.PersonSerializer`. - - If no `App.PersonSerializer` is found, this method will look - for an `App.ApplicationSerializer` (the default serializer for - your entire application). - - If no `App.ApplicationSerializer` is found, it will fall back - to an instance of `DS.JSONSerializer`. - - @method serializerFor - @private - @param {String} type the record to serialize - @return {DS.Serializer} - */ - serializerFor: function(type) { - type = this.modelFor(type); - var adapter = this.adapterFor(type); - - return serializerFor(this.container, type.typeKey, adapter && adapter.defaultSerializer); - }, - - willDestroy: function() { - var typeMaps = this.typeMaps; - var keys = Ember.keys(typeMaps); - - var types = map(keys, byType); - - this.recordArrayManager.destroy(); - - forEach(types, this.unloadAll, this); - - function byType(entry) { - return typeMaps[entry]['type']; - } - - }, - - /** - All typeKeys are camelCase internally. Changing this function may - require changes to other normalization hooks (such as typeForRoot). - - @method _normalizeTypeKey - @private - @param {String} type - @return {String} if the adapter can generate one, an ID - */ - _normalizeTypeKey: function(key) { - return camelize(singularize(key)); - } - }); - - - function normalizeRelationships(store, type, data, record) { - type.eachRelationship(function(key, relationship) { - var kind = relationship.kind; - var value = data[key]; - if (kind === 'belongsTo') { - deserializeRecordId(store, data, key, relationship, value); - } else if (kind === 'hasMany') { - deserializeRecordIds(store, data, key, relationship, value); - } - }); - - return data; - } - - function deserializeRecordId(store, data, key, relationship, id) { - if (!Model) { Model = requireModule("ember-data/system/model")["Model"]; } - if (isNone(id) || id instanceof Model) { - return; - } - - var type; - - if (typeof id === 'number' || typeof id === 'string') { - type = typeFor(relationship, key, data); - data[key] = store.recordForId(type, id); - } else if (typeof id === 'object') { - // polymorphic - data[key] = store.recordForId(id.type, id.id); - } - } - - function typeFor(relationship, key, data) { - if (relationship.options.polymorphic) { - return data[key + "Type"]; - } else { - return relationship.type; - } - } - - function deserializeRecordIds(store, data, key, relationship, ids) { - if (!Ember.isArray(ids)) { - return; - } - for (var i=0, l=ids.length; i 'kine' - inflector.singularize('kine'); //=> 'cow' - ``` - - Creating an inflector and adding rules later. - - ```javascript - var inflector = Ember.Inflector.inflector; - - inflector.pluralize('advice'); // => 'advices' - inflector.uncountable('advice'); - inflector.pluralize('advice'); // => 'advice' - - inflector.pluralize('formula'); // => 'formulas' - inflector.irregular('formula', 'formulae'); - inflector.pluralize('formula'); // => 'formulae' - - // you would not need to add these as they are the default rules - inflector.plural(/$/, 's'); - inflector.singular(/s$/i, ''); - ``` - - Creating an inflector with a nondefault ruleset. - - ```javascript - var rules = { - plurals: [ /$/, 's' ], - singular: [ /\s$/, '' ], - irregularPairs: [ - [ 'cow', 'kine' ] - ], - uncountable: [ 'fish' ] - }; - - var inflector = new Ember.Inflector(rules); - ``` - - @class Inflector - @namespace Ember - */ - function Inflector(ruleSet) { - ruleSet = ruleSet || {}; - ruleSet.uncountable = ruleSet.uncountable || makeDictionary(); - ruleSet.irregularPairs = ruleSet.irregularPairs || makeDictionary(); - - var rules = this.rules = { - plurals: ruleSet.plurals || [], - singular: ruleSet.singular || [], - irregular: makeDictionary(), - irregularInverse: makeDictionary(), - uncountable: makeDictionary() - }; - - loadUncountable(rules, ruleSet.uncountable); - loadIrregular(rules, ruleSet.irregularPairs); - - this.enableCache(); - } - - if (!Object.create && !Object.create(null).hasOwnProperty) { - throw new Error("This browser does not support Object.create(null), please polyfil with es5-sham: http://git.io/yBU2rg"); - } - - function makeDictionary() { - var cache = Object.create(null); - cache['_dict'] = null; - delete cache['_dict']; - return cache; - } - - Inflector.prototype = { - /** - @public - - As inflections can be costly, and commonly the same subset of words are repeatedly - inflected an optional cache is provided. - - @method enableCache - */ - enableCache: function() { - this.purgeCache(); - - this.singularize = function(word) { - this._cacheUsed = true; - return this._sCache[word] || (this._sCache[word] = this._singularize(word)); - }; - - this.pluralize = function(word) { - this._cacheUsed = true; - return this._pCache[word] || (this._pCache[word] = this._pluralize(word)); - }; - }, - - /** - @public - - @method purgedCache - */ - purgeCache: function() { - this._cacheUsed = false; - this._sCache = makeDictionary(); - this._pCache = makeDictionary(); - }, - - /** - @public - disable caching - - @method disableCache; - */ - disableCache: function() { - this._sCache = null; - this._pCache = null; - this.singularize = function(word) { - return this._singularize(word); - }; - - this.pluralize = function(word) { - return this._pluralize(word); - }; - }, - - /** - @method plural - @param {RegExp} regex - @param {String} string - */ - plural: function(regex, string) { - if (this._cacheUsed) { this.purgeCache(); } - this.rules.plurals.push([regex, string.toLowerCase()]); - }, - - /** - @method singular - @param {RegExp} regex - @param {String} string - */ - singular: function(regex, string) { - if (this._cacheUsed) { this.purgeCache(); } - this.rules.singular.push([regex, string.toLowerCase()]); - }, - - /** - @method uncountable - @param {String} regex - */ - uncountable: function(string) { - if (this._cacheUsed) { this.purgeCache(); } - loadUncountable(this.rules, [string.toLowerCase()]); - }, - - /** - @method irregular - @param {String} singular - @param {String} plural - */ - irregular: function (singular, plural) { - if (this._cacheUsed) { this.purgeCache(); } - loadIrregular(this.rules, [[singular, plural]]); - }, - - /** - @method pluralize - @param {String} word - */ - pluralize: function(word) { - return this._pluralize(word); - }, - - _pluralize: function(word) { - return this.inflect(word, this.rules.plurals, this.rules.irregular); - }, - /** - @method singularize - @param {String} word - */ - singularize: function(word) { - return this._singularize(word); - }, - - _singularize: function(word) { - return this.inflect(word, this.rules.singular, this.rules.irregularInverse); - }, - - /** - @protected - - @method inflect - @param {String} word - @param {Object} typeRules - @param {Object} irregular - */ - inflect: function(word, typeRules, irregular) { - var inflection, substitution, result, lowercase, wordSplit, - firstPhrase, lastWord, isBlank, isCamelized, isUncountable, - isIrregular, isIrregularInverse, rule; - - isBlank = BLANK_REGEX.test(word); - isCamelized = CAMELIZED_REGEX.test(word); - firstPhrase = ""; - - if (isBlank) { - return word; - } - - lowercase = word.toLowerCase(); - wordSplit = LAST_WORD_DASHED_REGEX.exec(word) || LAST_WORD_CAMELIZED_REGEX.exec(word); - if (wordSplit){ - firstPhrase = wordSplit[1]; - lastWord = wordSplit[2].toLowerCase(); - } - - isUncountable = this.rules.uncountable[lowercase] || this.rules.uncountable[lastWord]; - - if (isUncountable) { - return word; - } - - isIrregular = irregular && (irregular[lowercase] || irregular[lastWord]); - - if (isIrregular) { - if (irregular[lowercase]){ - return isIrregular; - } - else { - isIrregular = (isCamelized) ? isIrregular.capitalize() : isIrregular; - return firstPhrase + isIrregular; - } - } - - for (var i = typeRules.length, min = 0; i > min; i--) { - inflection = typeRules[i-1]; - rule = inflection[0]; - - if (rule.test(word)) { - break; - } - } - - inflection = inflection || []; - - rule = inflection[0]; - substitution = inflection[1]; - - result = word.replace(rule, substitution); - - return result; - } - }; - - __exports__["default"] = Inflector; - }); -define("ember-inflector/system/string", - ["./inflector","exports"], - function(__dependency1__, __exports__) { - "use strict"; - var Inflector = __dependency1__["default"]; - - function pluralize(word) { - return Inflector.inflector.pluralize(word); - } - - function singularize(word) { - return Inflector.inflector.singularize(word); - } - - __exports__.pluralize = pluralize; - __exports__.singularize = singularize; - }); - global.DS = requireModule('ember-data')['default']; - })(this); diff --git a/vendor/assets/ember/development/ember.js b/vendor/assets/ember/development/ember.js deleted file mode 100644 index 1be59aa8..00000000 --- a/vendor/assets/ember/development/ember.js +++ /dev/null @@ -1,49742 +0,0 @@ -// Fetched from channel: release, with url http://builds.emberjs.com/release/ember.js -// Fetched on: 2014-11-24T13:02:00Z -/*! - * @overview Ember - JavaScript Application Framework - * @copyright Copyright 2011-2014 Tilde Inc. and contributors - * Portions Copyright 2006-2011 Strobe Inc. - * Portions Copyright 2008-2011 Apple Inc. All rights reserved. - * @license Licensed under MIT license - * See https://raw.github.com/emberjs/ember.js/master/LICENSE - * @version 1.8.1 - */ - -(function() { -var enifed, requireModule, eriuqer, requirejs, Ember; - -(function() { - Ember = this.Ember = this.Ember || {}; - if (typeof Ember === 'undefined') { Ember = {}; }; - - if (typeof Ember.__loader === 'undefined') { - var registry = {}, seen = {}; - - enifed = function(name, deps, callback) { - registry[name] = { deps: deps, callback: callback }; - }; - - requirejs = eriuqer = requireModule = function(name) { - if (seen.hasOwnProperty(name)) { return seen[name]; } - seen[name] = {}; - - if (!registry[name]) { - throw new Error("Could not find module " + name); - } - - var mod = registry[name]; - var deps = mod.deps; - var callback = mod.callback; - var reified = []; - var exports; - - for (var i=0, l=deps.length; i 3) { - args = new Array(length - 3); - for (var i = 3; i < length; i++) { - args[i-3] = arguments[i]; - } - } else { - args = undefined; - } - - if (!this.currentInstance) { createAutorun(this); } - return this.currentInstance.schedule(queueName, target, method, args, false, stack); - }, - - deferOnce: function(queueName, target, method /* , args */) { - if (!method) { - method = target; - target = null; - } - - if (isString(method)) { - method = target[method]; - } - - var stack = this.DEBUG ? new Error() : undefined; - var length = arguments.length; - var args; - - if (length > 3) { - args = new Array(length - 3); - for (var i = 3; i < length; i++) { - args[i-3] = arguments[i]; - } - } else { - args = undefined; - } - - if (!this.currentInstance) { - createAutorun(this); - } - return this.currentInstance.schedule(queueName, target, method, args, true, stack); - }, - - setTimeout: function() { - var l = arguments.length; - var args = new Array(l); - - for (var x = 0; x < l; x++) { - args[x] = arguments[x]; - } - - var length = args.length, - method, wait, target, - methodOrTarget, methodOrWait, methodOrArgs; - - if (length === 0) { - return; - } else if (length === 1) { - method = args.shift(); - wait = 0; - } else if (length === 2) { - methodOrTarget = args[0]; - methodOrWait = args[1]; - - if (isFunction(methodOrWait) || isFunction(methodOrTarget[methodOrWait])) { - target = args.shift(); - method = args.shift(); - wait = 0; - } else if (isCoercableNumber(methodOrWait)) { - method = args.shift(); - wait = args.shift(); - } else { - method = args.shift(); - wait = 0; - } - } else { - var last = args[args.length - 1]; - - if (isCoercableNumber(last)) { - wait = args.pop(); - } else { - wait = 0; - } - - methodOrTarget = args[0]; - methodOrArgs = args[1]; - - if (isFunction(methodOrArgs) || (isString(methodOrArgs) && - methodOrTarget !== null && - methodOrArgs in methodOrTarget)) { - target = args.shift(); - method = args.shift(); - } else { - method = args.shift(); - } - } - - var executeAt = now() + parseInt(wait, 10); - - if (isString(method)) { - method = target[method]; - } - - var onError = getOnError(this.options); - - function fn() { - if (onError) { - try { - method.apply(target, args); - } catch (e) { - onError(e); - } - } else { - method.apply(target, args); - } - } - - // find position to insert - var i = searchTimer(executeAt, this._timers); - - this._timers.splice(i, 0, executeAt, fn); - - updateLaterTimer(this, executeAt, wait); - - return fn; - }, - - throttle: function(target, method /* , args, wait, [immediate] */) { - var backburner = this; - var args = arguments; - var immediate = pop.call(args); - var wait, throttler, index, timer; - - if (isNumber(immediate) || isString(immediate)) { - wait = immediate; - immediate = true; - } else { - wait = pop.call(args); - } - - wait = parseInt(wait, 10); - - index = findThrottler(target, method, this._throttlers); - if (index > -1) { return this._throttlers[index]; } // throttled - - timer = global.setTimeout(function() { - if (!immediate) { - backburner.run.apply(backburner, args); - } - var index = findThrottler(target, method, backburner._throttlers); - if (index > -1) { - backburner._throttlers.splice(index, 1); - } - }, wait); - - if (immediate) { - this.run.apply(this, args); - } - - throttler = [target, method, timer]; - - this._throttlers.push(throttler); - - return throttler; - }, - - debounce: function(target, method /* , args, wait, [immediate] */) { - var backburner = this; - var args = arguments; - var immediate = pop.call(args); - var wait, index, debouncee, timer; - - if (isNumber(immediate) || isString(immediate)) { - wait = immediate; - immediate = false; - } else { - wait = pop.call(args); - } - - wait = parseInt(wait, 10); - // Remove debouncee - index = findDebouncee(target, method, this._debouncees); - - if (index > -1) { - debouncee = this._debouncees[index]; - this._debouncees.splice(index, 1); - clearTimeout(debouncee[2]); - } - - timer = global.setTimeout(function() { - if (!immediate) { - backburner.run.apply(backburner, args); - } - var index = findDebouncee(target, method, backburner._debouncees); - if (index > -1) { - backburner._debouncees.splice(index, 1); - } - }, wait); - - if (immediate && index === -1) { - backburner.run.apply(backburner, args); - } - - debouncee = [ - target, - method, - timer - ]; - - backburner._debouncees.push(debouncee); - - return debouncee; - }, - - cancelTimers: function() { - var clearItems = function(item) { - clearTimeout(item[2]); - }; - - each(this._throttlers, clearItems); - this._throttlers = []; - - each(this._debouncees, clearItems); - this._debouncees = []; - - if (this._laterTimer) { - clearTimeout(this._laterTimer); - this._laterTimer = null; - } - this._timers = []; - - if (this._autorun) { - clearTimeout(this._autorun); - this._autorun = null; - } - }, - - hasTimers: function() { - return !!this._timers.length || !!this._debouncees.length || !!this._throttlers.length || this._autorun; - }, - - cancel: function(timer) { - var timerType = typeof timer; - - if (timer && timerType === 'object' && timer.queue && timer.method) { // we're cancelling a deferOnce - return timer.queue.cancel(timer); - } else if (timerType === 'function') { // we're cancelling a setTimeout - for (var i = 0, l = this._timers.length; i < l; i += 2) { - if (this._timers[i + 1] === timer) { - this._timers.splice(i, 2); // remove the two elements - if (i === 0) { - if (this._laterTimer) { // Active timer? Then clear timer and reset for future timer - clearTimeout(this._laterTimer); - this._laterTimer = null; - } - if (this._timers.length > 0) { // Update to next available timer when available - updateLaterTimer(this, this._timers[0], this._timers[0] - now()); - } - } - return true; - } - } - } else if (Object.prototype.toString.call(timer) === "[object Array]"){ // we're cancelling a throttle or debounce - return this._cancelItem(findThrottler, this._throttlers, timer) || - this._cancelItem(findDebouncee, this._debouncees, timer); - } else { - return; // timer was null or not a timer - } - }, - - _cancelItem: function(findMethod, array, timer){ - var item, index; - - if (timer.length < 3) { return false; } - - index = findMethod(timer[0], timer[1], array); - - if (index > -1) { - - item = array[index]; - - if (item[2] === timer[2]) { - array.splice(index, 1); - clearTimeout(timer[2]); - return true; - } - } - - return false; - } - }; - - Backburner.prototype.schedule = Backburner.prototype.defer; - Backburner.prototype.scheduleOnce = Backburner.prototype.deferOnce; - Backburner.prototype.later = Backburner.prototype.setTimeout; - - if (needsIETryCatchFix) { - var originalRun = Backburner.prototype.run; - Backburner.prototype.run = wrapInTryCatch(originalRun); - - var originalEnd = Backburner.prototype.end; - Backburner.prototype.end = wrapInTryCatch(originalEnd); - } - - function getOnError(options) { - return options.onError || (options.onErrorTarget && options.onErrorTarget[options.onErrorMethod]); - } - - function createAutorun(backburner) { - backburner.begin(); - backburner._autorun = global.setTimeout(function() { - backburner._autorun = null; - backburner.end(); - }); - } - - function updateLaterTimer(backburner, executeAt, wait) { - var n = now(); - if (!backburner._laterTimer || executeAt < backburner._laterTimerExpiresAt || backburner._laterTimerExpiresAt < n) { - - if (backburner._laterTimer) { - // Clear when: - // - Already expired - // - New timer is earlier - clearTimeout(backburner._laterTimer); - - if (backburner._laterTimerExpiresAt < n) { // If timer was never triggered - // Calculate the left-over wait-time - wait = Math.max(0, executeAt - n); - } - } - - backburner._laterTimer = global.setTimeout(function() { - backburner._laterTimer = null; - backburner._laterTimerExpiresAt = null; - executeTimers(backburner); - }, wait); - - backburner._laterTimerExpiresAt = n + wait; - } - } - - function executeTimers(backburner) { - var n = now(); - var fns, i, l; - - backburner.run(function() { - i = searchTimer(n, backburner._timers); - - fns = backburner._timers.splice(0, i); - - for (i = 1, l = fns.length; i < l; i += 2) { - backburner.schedule(backburner.options.defaultQueue, null, fns[i]); - } - }); - - if (backburner._timers.length) { - updateLaterTimer(backburner, backburner._timers[0], backburner._timers[0] - n); - } - } - - function findDebouncee(target, method, debouncees) { - return findItem(target, method, debouncees); - } - - function findThrottler(target, method, throttlers) { - return findItem(target, method, throttlers); - } - - function findItem(target, method, collection) { - var item; - var index = -1; - - for (var i = 0, l = collection.length; i < l; i++) { - item = collection[i]; - if (item[0] === target && item[1] === method) { - index = i; - break; - } - } - - return index; - } - - __exports__["default"] = Backburner; - }); -enifed("backburner.umd", - ["./backburner"], - function(__dependency1__) { - "use strict"; - var Backburner = __dependency1__["default"]; - - /* global define:true module:true window: true */ - if (typeof enifed === 'function' && enifed.amd) { - enifed(function() { return Backburner; }); - } else if (typeof module !== 'undefined' && module.exports) { - module.exports = Backburner; - } else if (typeof this !== 'undefined') { - this['Backburner'] = Backburner; - } - }); -enifed("backburner/binary-search", - ["exports"], - function(__exports__) { - "use strict"; - __exports__["default"] = function binarySearch(time, timers) { - var start = 0; - var end = timers.length - 2; - var middle, l; - - while (start < end) { - // since timers is an array of pairs 'l' will always - // be an integer - l = (end - start) / 2; - - // compensate for the index in case even number - // of pairs inside timers - middle = start + l - (l % 2); - - if (time >= timers[middle]) { - start = middle + 2; - } else { - end = middle; - } - } - - return (time >= timers[start]) ? start + 2 : start; - } - }); -enifed("backburner/deferred-action-queues", - ["./utils","./queue","exports"], - function(__dependency1__, __dependency2__, __exports__) { - "use strict"; - var each = __dependency1__.each; - var isString = __dependency1__.isString; - var Queue = __dependency2__["default"]; - - function DeferredActionQueues(queueNames, options) { - var queues = this.queues = {}; - this.queueNames = queueNames = queueNames || []; - - this.options = options; - - each(queueNames, function(queueName) { - queues[queueName] = new Queue(queueName, options[queueName], options); - }); - } - - function noSuchQueue(name) { - throw new Error("You attempted to schedule an action in a queue (" + name + ") that doesn't exist"); - } - - DeferredActionQueues.prototype = { - schedule: function(name, target, method, args, onceFlag, stack) { - var queues = this.queues; - var queue = queues[name]; - - if (!queue) { noSuchQueue(name); } - - if (onceFlag) { - return queue.pushUnique(target, method, args, stack); - } else { - return queue.push(target, method, args, stack); - } - }, - - invoke: function(target, method, args, _, _errorRecordedForStack) { - if (args && args.length > 0) { - method.apply(target, args); - } else { - method.call(target); - } - }, - - invokeWithOnError: function(target, method, args, onError, errorRecordedForStack) { - try { - if (args && args.length > 0) { - method.apply(target, args); - } else { - method.call(target); - } - } catch(error) { - onError(error, errorRecordedForStack); - } - }, - - flush: function() { - var queues = this.queues; - var queueNames = this.queueNames; - var queueName, queue, queueItems, priorQueueNameIndex; - var queueNameIndex = 0; - var numberOfQueues = queueNames.length; - var options = this.options; - var onError = options.onError || (options.onErrorTarget && options.onErrorTarget[options.onErrorMethod]); - var invoke = onError ? this.invokeWithOnError : this.invoke; - - while (queueNameIndex < numberOfQueues) { - queueName = queueNames[queueNameIndex]; - queue = queues[queueName]; - queueItems = queue._queueBeingFlushed = queue._queue.slice(); - queue._queue = []; - queue.targetQueues = Object.create(null); - - var queueOptions = queue.options; // TODO: write a test for this - var before = queueOptions && queueOptions.before; - var after = queueOptions && queueOptions.after; - var target, method, args, errorRecordedForStack; - var queueIndex = 0; - var numberOfQueueItems = queueItems.length; - - if (numberOfQueueItems && before) { - before(); - } - - while (queueIndex < numberOfQueueItems) { - target = queueItems[queueIndex]; - method = queueItems[queueIndex+1]; - args = queueItems[queueIndex+2]; - errorRecordedForStack = queueItems[queueIndex+3]; // Debugging assistance - - // - - if (isString(method)) { - method = target[method]; - } - - // method could have been nullified / canceled during flush - if (method) { - // - // ** Attention intrepid developer ** - // - // To find out the stack of this task when it was scheduled onto - // the run loop, add the following to your app.js: - // - // Ember.run.backburner.DEBUG = true; // NOTE: This slows your app, don't leave it on in production. - // - // Once that is in place, when you are at a breakpoint and navigate - // here in the stack explorer, you can look at `errorRecordedForStack.stack`, - // which will be the captured stack when this job was scheduled. - // - invoke(target, method, args, onError, errorRecordedForStack); - } - - queueIndex += 4; - } - - queue._queueBeingFlushed = null; - if (numberOfQueueItems && after) { - after(); - } - - if ((priorQueueNameIndex = indexOfPriorQueueWithActions(this, queueNameIndex)) !== -1) { - queueNameIndex = priorQueueNameIndex; - } else { - queueNameIndex++; - } - } - } - }; - - function indexOfPriorQueueWithActions(daq, currentQueueIndex) { - var queueName, queue; - - for (var i = 0, l = currentQueueIndex; i <= l; i++) { - queueName = daq.queueNames[i]; - queue = daq.queues[queueName]; - if (queue._queue.length) { return i; } - } - - return -1; - } - - __exports__["default"] = DeferredActionQueues; - }); -enifed("backburner/platform", - ["exports"], - function(__exports__) { - "use strict"; - // In IE 6-8, try/finally doesn't work without a catch. - // Unfortunately, this is impossible to test for since wrapping it in a parent try/catch doesn't trigger the bug. - // This tests for another broken try/catch behavior that only exhibits in the same versions of IE. - var needsIETryCatchFix = (function(e,x){ - try{ x(); } - catch(e) { } // jshint ignore:line - return !!e; - })(); - __exports__.needsIETryCatchFix = needsIETryCatchFix; - }); -enifed("backburner/queue", - ["exports"], - function(__exports__) { - "use strict"; - function Queue(name, options, globalOptions) { - this.name = name; - this.globalOptions = globalOptions || {}; - this.options = options; - this._queue = []; - this.targetQueues = Object.create(null); - this._queueBeingFlushed = undefined; - } - - Queue.prototype = { - push: function(target, method, args, stack) { - var queue = this._queue; - queue.push(target, method, args, stack); - - return { - queue: this, - target: target, - method: method - }; - }, - - pushUniqueWithoutGuid: function(target, method, args, stack) { - var queue = this._queue; - - for (var i = 0, l = queue.length; i < l; i += 4) { - var currentTarget = queue[i]; - var currentMethod = queue[i+1]; - - if (currentTarget === target && currentMethod === method) { - queue[i+2] = args; // replace args - queue[i+3] = stack; // replace stack - return; - } - } - - queue.push(target, method, args, stack); - }, - - targetQueue: function(targetQueue, target, method, args, stack) { - var queue = this._queue; - - for (var i = 0, l = targetQueue.length; i < l; i += 4) { - var currentMethod = targetQueue[i]; - var currentIndex = targetQueue[i + 1]; - - if (currentMethod === method) { - queue[currentIndex + 2] = args; // replace args - queue[currentIndex + 3] = stack; // replace stack - return; - } - } - - targetQueue.push( - method, - queue.push(target, method, args, stack) - 4 - ); - }, - - pushUniqueWithGuid: function(guid, target, method, args, stack) { - var hasLocalQueue = this.targetQueues[guid]; - - if (hasLocalQueue) { - this.targetQueue(hasLocalQueue, target, method, args, stack); - } else { - this.targetQueues[guid] = [ - method, - this._queue.push(target, method, args, stack) - 4 - ]; - } - - return { - queue: this, - target: target, - method: method - }; - }, - - pushUnique: function(target, method, args, stack) { - var queue = this._queue, currentTarget, currentMethod, i, l; - var KEY = this.globalOptions.GUID_KEY; - - if (target && KEY) { - var guid = target[KEY]; - if (guid) { - return this.pushUniqueWithGuid(guid, target, method, args, stack); - } - } - - this.pushUniqueWithoutGuid(target, method, args, stack); - - return { - queue: this, - target: target, - method: method - }; - }, - - // TODO: remove me, only being used for Ember.run.sync - flush: function() { - var queue = this._queue; - var globalOptions = this.globalOptions; - var options = this.options; - var before = options && options.before; - var after = options && options.after; - var onError = globalOptions.onError || (globalOptions.onErrorTarget && globalOptions.onErrorTarget[globalOptions.onErrorMethod]); - var target, method, args, stack, i, l = queue.length; - - this.targetQueues = Object.create(null); - - if (l && before) { before(); } - for (i = 0; i < l; i += 4) { - target = queue[i]; - method = queue[i+1]; - args = queue[i+2]; - stack = queue[i+3]; // Debugging assistance - - // TODO: error handling - if (args && args.length > 0) { - if (onError) { - try { - method.apply(target, args); - } catch (e) { - onError(e); - } - } else { - method.apply(target, args); - } - } else { - if (onError) { - try { - method.call(target); - } catch(e) { - onError(e); - } - } else { - method.call(target); - } - } - } - if (l && after) { after(); } - - // check if new items have been added - if (queue.length > l) { - this._queue = queue.slice(l); - this.flush(); - } else { - this._queue.length = 0; - } - }, - - cancel: function(actionToCancel) { - var queue = this._queue, currentTarget, currentMethod, i, l; - var target = actionToCancel.target; - var method = actionToCancel.method; - var GUID_KEY = this.globalOptions.GUID_KEY; - - if (GUID_KEY && this.targetQueues && target) { - var targetQueue = this.targetQueues[target[GUID_KEY]]; - - if (targetQueue) { - for (i = 0, l = targetQueue.length; i < l; i++) { - if (targetQueue[i] === method) { - targetQueue.splice(i, 1); - } - } - } - } - - for (i = 0, l = queue.length; i < l; i += 4) { - currentTarget = queue[i]; - currentMethod = queue[i+1]; - - if (currentTarget === target && - currentMethod === method) { - queue.splice(i, 4); - return true; - } - } - - // if not found in current queue - // could be in the queue that is being flushed - queue = this._queueBeingFlushed; - if (!queue) { - return; - } - for (i = 0, l = queue.length; i < l; i += 4) { - currentTarget = queue[i]; - currentMethod = queue[i+1]; - - if (currentTarget === target && - currentMethod === method) { - // don't mess with array during flush - // just nullify the method - queue[i+1] = null; - return true; - } - } - } - }; - - __exports__["default"] = Queue; - }); -enifed("backburner/utils", - ["exports"], - function(__exports__) { - "use strict"; - var NUMBER = /\d+/; - - function each(collection, callback) { - for (var i = 0; i < collection.length; i++) { - callback(collection[i]); - } - } - - __exports__.each = each;// Date.now is not available in browsers < IE9 - // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/now#Compatibility - var now = Date.now || function() { return new Date().getTime(); }; - __exports__.now = now; - function isString(suspect) { - return typeof suspect === 'string'; - } - - __exports__.isString = isString;function isFunction(suspect) { - return typeof suspect === 'function'; - } - - __exports__.isFunction = isFunction;function isNumber(suspect) { - return typeof suspect === 'number'; - } - - __exports__.isNumber = isNumber;function isCoercableNumber(number) { - return isNumber(number) || NUMBER.test(number); - } - - __exports__.isCoercableNumber = isCoercableNumber;function wrapInTryCatch(func) { - return function () { - try { - return func.apply(this, arguments); - } catch (e) { - throw e; - } - }; - } - - __exports__.wrapInTryCatch = wrapInTryCatch; - }); -enifed("calculateVersion", - [], - function() { - "use strict"; - 'use strict'; - - var fs = eriuqer('fs'); - var path = eriuqer('path'); - - module.exports = function () { - var packageVersion = eriuqer('../package.json').version; - var output = [packageVersion]; - var gitPath = path.join(__dirname,'..','.git'); - var headFilePath = path.join(gitPath, 'HEAD'); - - if (packageVersion.indexOf('+') > -1) { - try { - if (fs.existsSync(headFilePath)) { - var headFile = fs.readFileSync(headFilePath, {encoding: 'utf8'}); - var branchName = headFile.split('/').slice(-1)[0].trim(); - var refPath = headFile.split(' ')[1]; - var branchSHA; - - if (refPath) { - var branchPath = path.join(gitPath, refPath.trim()); - branchSHA = fs.readFileSync(branchPath); - } else { - branchSHA = branchName; - } - - output.push(branchSHA.slice(0,10)); - } - } catch (err) { - console.error(err.stack); - } - return output.join('.'); - } else { - return packageVersion; - } - }; - }); -enifed("container", - ["container/container","exports"], - function(__dependency1__, __exports__) { - "use strict"; - /* - Public api for the container is still in flux. - The public api, specified on the application namespace should be considered the stable api. - // @module container - @private - */ - - /* - Flag to enable/disable model factory injections (disabled by default) - If model factory injections are enabled, models should not be - accessed globally (only through `container.lookupFactory('model:modelName'))`); - */ - Ember.MODEL_FACTORY_INJECTIONS = false; - - if (Ember.ENV && typeof Ember.ENV.MODEL_FACTORY_INJECTIONS !== 'undefined') { - Ember.MODEL_FACTORY_INJECTIONS = !!Ember.ENV.MODEL_FACTORY_INJECTIONS; - } - - - var Container = __dependency1__["default"]; - - __exports__["default"] = Container; - }); -enifed("container/container", - ["ember-metal/core","ember-metal/keys","ember-metal/dictionary","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __exports__) { - "use strict"; - var Ember = __dependency1__["default"]; - // Ember.assert - var emberKeys = __dependency2__["default"]; - var dictionary = __dependency3__["default"]; - - // A lightweight container that helps to assemble and decouple components. - // Public api for the container is still in flux. - // The public api, specified on the application namespace should be considered the stable api. - function Container(parent) { - this.parent = parent; - this.children = []; - - this.resolver = parent && parent.resolver || function() {}; - - this.registry = dictionary(parent ? parent.registry : null); - this.cache = dictionary(parent ? parent.cache : null); - this.factoryCache = dictionary(parent ? parent.factoryCache : null); - this.resolveCache = dictionary(parent ? parent.resolveCache : null); - this.typeInjections = dictionary(parent ? parent.typeInjections : null); - this.injections = dictionary(null); - this.normalizeCache = dictionary(null); - - this.factoryTypeInjections = dictionary(parent ? parent.factoryTypeInjections : null); - this.factoryInjections = dictionary(null); - - this._options = dictionary(parent ? parent._options : null); - this._typeOptions = dictionary(parent ? parent._typeOptions : null); - } - - Container.prototype = { - - /** - @property parent - @type Container - @default null - */ - parent: null, - - /** - @property children - @type Array - @default [] - */ - children: null, - - /** - @property resolver - @type function - */ - resolver: null, - - /** - @property registry - @type InheritingDict - */ - registry: null, - - /** - @property cache - @type InheritingDict - */ - cache: null, - - /** - @property typeInjections - @type InheritingDict - */ - typeInjections: null, - - /** - @property injections - @type Object - @default {} - */ - injections: null, - - /** - @private - - @property _options - @type InheritingDict - @default null - */ - _options: null, - - /** - @private - - @property _typeOptions - @type InheritingDict - */ - _typeOptions: null, - - /** - Returns a new child of the current container. These children are configured - to correctly inherit from the current container. - - @method child - @return {Container} - */ - child: function() { - var container = new Container(this); - this.children.push(container); - return container; - }, - - /** - Sets a key-value pair on the current container. If a parent container, - has the same key, once set on a child, the parent and child will diverge - as expected. - - @method set - @param {Object} object - @param {String} key - @param {any} value - */ - set: function(object, key, value) { - object[key] = value; - }, - - /** - Registers a factory for later injection. - - Example: - - ```javascript - var container = new Container(); - - container.register('model:user', Person, {singleton: false }); - container.register('fruit:favorite', Orange); - container.register('communication:main', Email, {singleton: false}); - ``` - - @method register - @param {String} fullName - @param {Function} factory - @param {Object} options - */ - register: function(fullName, factory, options) { - Ember.assert('fullName must be a proper full name', validateFullName(fullName)); - - if (factory === undefined) { - throw new TypeError('Attempting to register an unknown factory: `' + fullName + '`'); - } - - var normalizedName = this.normalize(fullName); - - if (normalizedName in this.cache) { - throw new Error('Cannot re-register: `' + fullName +'`, as it has already been looked up.'); - } - - this.registry[normalizedName] = factory; - this._options[normalizedName] = (options || {}); - }, - - /** - Unregister a fullName - - ```javascript - var container = new Container(); - container.register('model:user', User); - - container.lookup('model:user') instanceof User //=> true - - container.unregister('model:user') - container.lookup('model:user') === undefined //=> true - ``` - - @method unregister - @param {String} fullName - */ - unregister: function(fullName) { - Ember.assert('fullName must be a proper full name', validateFullName(fullName)); - - var normalizedName = this.normalize(fullName); - - delete this.registry[normalizedName]; - delete this.cache[normalizedName]; - delete this.factoryCache[normalizedName]; - delete this.resolveCache[normalizedName]; - delete this._options[normalizedName]; - }, - - /** - Given a fullName return the corresponding factory. - - By default `resolve` will retrieve the factory from - its container's registry. - - ```javascript - var container = new Container(); - container.register('api:twitter', Twitter); - - container.resolve('api:twitter') // => Twitter - ``` - - Optionally the container can be provided with a custom resolver. - If provided, `resolve` will first provide the custom resolver - the opportunity to resolve the fullName, otherwise it will fallback - to the registry. - - ```javascript - var container = new Container(); - container.resolver = function(fullName) { - // lookup via the module system of choice - }; - - // the twitter factory is added to the module system - container.resolve('api:twitter') // => Twitter - ``` - - @method resolve - @param {String} fullName - @return {Function} fullName's factory - */ - resolve: function(fullName) { - Ember.assert('fullName must be a proper full name', validateFullName(fullName)); - return resolve(this, this.normalize(fullName)); - }, - - /** - A hook that can be used to describe how the resolver will - attempt to find the factory. - - For example, the default Ember `.describe` returns the full - class name (including namespace) where Ember's resolver expects - to find the `fullName`. - - @method describe - @param {String} fullName - @return {string} described fullName - */ - describe: function(fullName) { - return fullName; - }, - - /** - A hook to enable custom fullName normalization behaviour - - @method normalizeFullName - @param {String} fullName - @return {string} normalized fullName - */ - normalizeFullName: function(fullName) { - return fullName; - }, - - /** - normalize a fullName based on the applications conventions - - @method normalize - @param {String} fullName - @return {string} normalized fullName - */ - normalize: function(fullName) { - return this.normalizeCache[fullName] || ( - this.normalizeCache[fullName] = this.normalizeFullName(fullName) - ); - }, - - /** - @method makeToString - - @param {any} factory - @param {string} fullName - @return {function} toString function - */ - makeToString: function(factory, fullName) { - return factory.toString(); - }, - - /** - Given a fullName return a corresponding instance. - - The default behaviour is for lookup to return a singleton instance. - The singleton is scoped to the container, allowing multiple containers - to all have their own locally scoped singletons. - - ```javascript - var container = new Container(); - container.register('api:twitter', Twitter); - - var twitter = container.lookup('api:twitter'); - - twitter instanceof Twitter; // => true - - // by default the container will return singletons - var twitter2 = container.lookup('api:twitter'); - twitter2 instanceof Twitter; // => true - - twitter === twitter2; //=> true - ``` - - If singletons are not wanted an optional flag can be provided at lookup. - - ```javascript - var container = new Container(); - container.register('api:twitter', Twitter); - - var twitter = container.lookup('api:twitter', { singleton: false }); - var twitter2 = container.lookup('api:twitter', { singleton: false }); - - twitter === twitter2; //=> false - ``` - - @method lookup - @param {String} fullName - @param {Object} options - @return {any} - */ - lookup: function(fullName, options) { - Ember.assert('fullName must be a proper full name', validateFullName(fullName)); - return lookup(this, this.normalize(fullName), options); - }, - - /** - Given a fullName return the corresponding factory. - - @method lookupFactory - @param {String} fullName - @return {any} - */ - lookupFactory: function(fullName) { - Ember.assert('fullName must be a proper full name', validateFullName(fullName)); - return factoryFor(this, this.normalize(fullName)); - }, - - /** - Given a fullName check if the container is aware of its factory - or singleton instance. - - @method has - @param {String} fullName - @return {Boolean} - */ - has: function(fullName) { - Ember.assert('fullName must be a proper full name', validateFullName(fullName)); - return has(this, this.normalize(fullName)); - }, - - /** - Allow registering options for all factories of a type. - - ```javascript - var container = new Container(); - - // if all of type `connection` must not be singletons - container.optionsForType('connection', { singleton: false }); - - container.register('connection:twitter', TwitterConnection); - container.register('connection:facebook', FacebookConnection); - - var twitter = container.lookup('connection:twitter'); - var twitter2 = container.lookup('connection:twitter'); - - twitter === twitter2; // => false - - var facebook = container.lookup('connection:facebook'); - var facebook2 = container.lookup('connection:facebook'); - - facebook === facebook2; // => false - ``` - - @method optionsForType - @param {String} type - @param {Object} options - */ - optionsForType: function(type, options) { - if (this.parent) { illegalChildOperation('optionsForType'); } - - this._typeOptions[type] = options; - }, - - /** - @method options - @param {String} type - @param {Object} options - */ - options: function(type, options) { - this.optionsForType(type, options); - }, - - /** - Used only via `injection`. - - Provides a specialized form of injection, specifically enabling - all objects of one type to be injected with a reference to another - object. - - For example, provided each object of type `controller` needed a `router`. - one would do the following: - - ```javascript - var container = new Container(); - - container.register('router:main', Router); - container.register('controller:user', UserController); - container.register('controller:post', PostController); - - container.typeInjection('controller', 'router', 'router:main'); - - var user = container.lookup('controller:user'); - var post = container.lookup('controller:post'); - - user.router instanceof Router; //=> true - post.router instanceof Router; //=> true - - // both controllers share the same router - user.router === post.router; //=> true - ``` - - @private - @method typeInjection - @param {String} type - @param {String} property - @param {String} fullName - */ - typeInjection: function(type, property, fullName) { - Ember.assert('fullName must be a proper full name', validateFullName(fullName)); - - if (this.parent) { illegalChildOperation('typeInjection'); } - - var fullNameType = fullName.split(':')[0]; - if (fullNameType === type) { - throw new Error('Cannot inject a `' + fullName + '` on other ' + type + '(s). Register the `' + fullName + '` as a different type and perform the typeInjection.'); - } - - addTypeInjection(this.typeInjections, type, property, fullName); - }, - - /** - Defines injection rules. - - These rules are used to inject dependencies onto objects when they - are instantiated. - - Two forms of injections are possible: - - * Injecting one fullName on another fullName - * Injecting one fullName on a type - - Example: - - ```javascript - var container = new Container(); - - container.register('source:main', Source); - container.register('model:user', User); - container.register('model:post', Post); - - // injecting one fullName on another fullName - // eg. each user model gets a post model - container.injection('model:user', 'post', 'model:post'); - - // injecting one fullName on another type - container.injection('model', 'source', 'source:main'); - - var user = container.lookup('model:user'); - var post = container.lookup('model:post'); - - user.source instanceof Source; //=> true - post.source instanceof Source; //=> true - - user.post instanceof Post; //=> true - - // and both models share the same source - user.source === post.source; //=> true - ``` - - @method injection - @param {String} factoryName - @param {String} property - @param {String} injectionName - */ - injection: function(fullName, property, injectionName) { - if (this.parent) { illegalChildOperation('injection'); } - - validateFullName(injectionName); - var normalizedInjectionName = this.normalize(injectionName); - - if (fullName.indexOf(':') === -1) { - return this.typeInjection(fullName, property, normalizedInjectionName); - } - - Ember.assert('fullName must be a proper full name', validateFullName(fullName)); - var normalizedName = this.normalize(fullName); - - if (this.cache[normalizedName]) { - throw new Error("Attempted to register an injection for a type that has already been looked up. ('" + normalizedName + "', '" + property + "', '" + injectionName + "')"); - } - addInjection(this.injections, normalizedName, property, normalizedInjectionName); - }, - - - /** - Used only via `factoryInjection`. - - Provides a specialized form of injection, specifically enabling - all factory of one type to be injected with a reference to another - object. - - For example, provided each factory of type `model` needed a `store`. - one would do the following: - - ```javascript - var container = new Container(); - - container.register('store:main', SomeStore); - - container.factoryTypeInjection('model', 'store', 'store:main'); - - var store = container.lookup('store:main'); - var UserFactory = container.lookupFactory('model:user'); - - UserFactory.store instanceof SomeStore; //=> true - ``` - - @private - @method factoryTypeInjection - @param {String} type - @param {String} property - @param {String} fullName - */ - factoryTypeInjection: function(type, property, fullName) { - if (this.parent) { illegalChildOperation('factoryTypeInjection'); } - - addTypeInjection(this.factoryTypeInjections, type, property, this.normalize(fullName)); - }, - - /** - Defines factory injection rules. - - Similar to regular injection rules, but are run against factories, via - `Container#lookupFactory`. - - These rules are used to inject objects onto factories when they - are looked up. - - Two forms of injections are possible: - - * Injecting one fullName on another fullName - * Injecting one fullName on a type - - Example: - - ```javascript - var container = new Container(); - - container.register('store:main', Store); - container.register('store:secondary', OtherStore); - container.register('model:user', User); - container.register('model:post', Post); - - // injecting one fullName on another type - container.factoryInjection('model', 'store', 'store:main'); - - // injecting one fullName on another fullName - container.factoryInjection('model:post', 'secondaryStore', 'store:secondary'); - - var UserFactory = container.lookupFactory('model:user'); - var PostFactory = container.lookupFactory('model:post'); - var store = container.lookup('store:main'); - - UserFactory.store instanceof Store; //=> true - UserFactory.secondaryStore instanceof OtherStore; //=> false - - PostFactory.store instanceof Store; //=> true - PostFactory.secondaryStore instanceof OtherStore; //=> true - - // and both models share the same source instance - UserFactory.store === PostFactory.store; //=> true - ``` - - @method factoryInjection - @param {String} factoryName - @param {String} property - @param {String} injectionName - */ - factoryInjection: function(fullName, property, injectionName) { - if (this.parent) { illegalChildOperation('injection'); } - - var normalizedName = this.normalize(fullName); - var normalizedInjectionName = this.normalize(injectionName); - - validateFullName(injectionName); - - if (fullName.indexOf(':') === -1) { - return this.factoryTypeInjection(normalizedName, property, normalizedInjectionName); - } - - Ember.assert('fullName must be a proper full name', validateFullName(fullName)); - - if (this.factoryCache[normalizedName]) { - throw new Error('Attempted to register a factoryInjection for a type that has already ' + - 'been looked up. (\'' + normalizedName + '\', \'' + property + '\', \'' + injectionName + '\')'); - } - - addInjection(this.factoryInjections, normalizedName, property, normalizedInjectionName); - }, - - /** - A depth first traversal, destroying the container, its descendant containers and all - their managed objects. - - @method destroy - */ - destroy: function() { - for (var i = 0, length = this.children.length; i < length; i++) { - this.children[i].destroy(); - } - - this.children = []; - - eachDestroyable(this, function(item) { - item.destroy(); - }); - - this.parent = undefined; - this.isDestroyed = true; - }, - - /** - @method reset - */ - reset: function() { - for (var i = 0, length = this.children.length; i < length; i++) { - resetCache(this.children[i]); - } - - resetCache(this); - } - }; - - function resolve(container, normalizedName) { - var cached = container.resolveCache[normalizedName]; - if (cached) { return cached; } - - var resolved = container.resolver(normalizedName) || container.registry[normalizedName]; - container.resolveCache[normalizedName] = resolved; - - return resolved; - } - - function has(container, fullName){ - if (container.cache[fullName]) { - return true; - } - - return !!container.resolve(fullName); - } - - function lookup(container, fullName, options) { - options = options || {}; - - if (container.cache[fullName] && options.singleton !== false) { - return container.cache[fullName]; - } - - var value = instantiate(container, fullName); - - if (value === undefined) { return; } - - if (isSingleton(container, fullName) && options.singleton !== false) { - container.cache[fullName] = value; - } - - return value; - } - - function illegalChildOperation(operation) { - throw new Error(operation + ' is not currently supported on child containers'); - } - - function isSingleton(container, fullName) { - var singleton = option(container, fullName, 'singleton'); - - return singleton !== false; - } - - function buildInjections(container, injections) { - var hash = {}; - - if (!injections) { return hash; } - - var injection, injectable; - - for (var i = 0, length = injections.length; i < length; i++) { - injection = injections[i]; - injectable = lookup(container, injection.fullName); - - if (injectable !== undefined) { - hash[injection.property] = injectable; - } else { - throw new Error('Attempting to inject an unknown injection: `' + injection.fullName + '`'); - } - } - - return hash; - } - - function option(container, fullName, optionName) { - var options = container._options[fullName]; - - if (options && options[optionName] !== undefined) { - return options[optionName]; - } - - var type = fullName.split(':')[0]; - options = container._typeOptions[type]; - - if (options) { - return options[optionName]; - } - } - - function factoryFor(container, fullName) { - var cache = container.factoryCache; - if (cache[fullName]) { - return cache[fullName]; - } - var factory = container.resolve(fullName); - if (factory === undefined) { return; } - - var type = fullName.split(':')[0]; - if (!factory || typeof factory.extend !== 'function' || (!Ember.MODEL_FACTORY_INJECTIONS && type === 'model')) { - // TODO: think about a 'safe' merge style extension - // for now just fallback to create time injection - cache[fullName] = factory; - return factory; - } else { - var injections = injectionsFor(container, fullName); - var factoryInjections = factoryInjectionsFor(container, fullName); - - factoryInjections._toString = container.makeToString(factory, fullName); - - var injectedFactory = factory.extend(injections); - injectedFactory.reopenClass(factoryInjections); - - cache[fullName] = injectedFactory; - - return injectedFactory; - } - } - - function injectionsFor(container, fullName) { - var splitName = fullName.split(':'); - var type = splitName[0]; - var injections = []; - - injections = injections.concat(container.typeInjections[type] || []); - injections = injections.concat(container.injections[fullName] || []); - - injections = buildInjections(container, injections); - injections._debugContainerKey = fullName; - injections.container = container; - - return injections; - } - - function factoryInjectionsFor(container, fullName) { - var splitName = fullName.split(':'); - var type = splitName[0]; - var factoryInjections = []; - - factoryInjections = factoryInjections.concat(container.factoryTypeInjections[type] || []); - factoryInjections = factoryInjections.concat(container.factoryInjections[fullName] || []); - - factoryInjections = buildInjections(container, factoryInjections); - factoryInjections._debugContainerKey = fullName; - - return factoryInjections; - } - - function instantiate(container, fullName) { - var factory = factoryFor(container, fullName); - - if (option(container, fullName, 'instantiate') === false) { - return factory; - } - - if (factory) { - if (typeof factory.create !== 'function') { - throw new Error('Failed to create an instance of \'' + fullName + '\'. ' + - 'Most likely an improperly defined class or an invalid module export.'); - } - - if (typeof factory.extend === 'function') { - // assume the factory was extendable and is already injected - return factory.create(); - } else { - // assume the factory was extendable - // to create time injections - // TODO: support new'ing for instantiation and merge injections for pure JS Functions - return factory.create(injectionsFor(container, fullName)); - } - } - } - - function eachDestroyable(container, callback) { - var cache = container.cache; - var keys = emberKeys(cache); - var key, value; - - for (var i = 0, l = keys.length; i < l; i++) { - key = keys[i]; - value = cache[key]; - - if (option(container, key, 'instantiate') !== false) { - callback(value); - } - } - } - - function resetCache(container) { - eachDestroyable(container, function(value) { - value.destroy(); - }); - - container.cache.dict = dictionary(null); - } - - function addTypeInjection(rules, type, property, fullName) { - var injections = rules[type]; - - if (!injections) { - injections = []; - rules[type] = injections; - } - - injections.push({ - property: property, - fullName: fullName - }); - } - - var VALID_FULL_NAME_REGEXP = /^[^:]+.+:[^:]+$/; - function validateFullName(fullName) { - if (!VALID_FULL_NAME_REGEXP.test(fullName)) { - throw new TypeError('Invalid Fullname, expected: `type:name` got: ' + fullName); - } - return true; - } - - function addInjection(rules, factoryName, property, injectionName) { - var injections = rules[factoryName] = rules[factoryName] || []; - injections.push({ - property: property, - fullName: injectionName - }); - } - - __exports__["default"] = Container; - }); -enifed("ember-application", - ["ember-metal/core","ember-runtime/system/lazy_load","ember-application/system/dag","ember-application/system/resolver","ember-application/system/application","ember-application/ext/controller"], - function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__) { - "use strict"; - var Ember = __dependency1__["default"]; - var runLoadHooks = __dependency2__.runLoadHooks; - - /** - Ember Application - - @module ember - @submodule ember-application - @requires ember-views, ember-routing - */ - - var DAG = __dependency3__["default"]; - var Resolver = __dependency4__.Resolver; - var DefaultResolver = __dependency4__["default"]; - var Application = __dependency5__["default"]; - // side effect of extending ControllerMixin - - Ember.Application = Application; - Ember.DAG = DAG; - Ember.Resolver = Resolver; - Ember.DefaultResolver = DefaultResolver; - - runLoadHooks('Ember.Application', Application); - }); -enifed("ember-application/ext/controller", - ["ember-metal/core","ember-metal/property_get","ember-metal/property_set","ember-metal/error","ember-metal/utils","ember-metal/computed","ember-runtime/mixins/controller","ember-routing/system/controller_for","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __exports__) { - "use strict"; - /** - @module ember - @submodule ember-application - */ - - var Ember = __dependency1__["default"]; - // Ember.assert - var get = __dependency2__.get; - var set = __dependency3__.set; - var EmberError = __dependency4__["default"]; - var inspect = __dependency5__.inspect; - var computed = __dependency6__.computed; - var ControllerMixin = __dependency7__["default"]; - var meta = __dependency5__.meta; - var controllerFor = __dependency8__["default"]; - - function verifyNeedsDependencies(controller, container, needs) { - var dependency, i, l; - var missing = []; - - for (i=0, l=needs.length; i 1 ? 'they' : 'it') + " could not be found"); - } - } - - var defaultControllersComputedProperty = computed(function() { - var controller = this; - - return { - needs: get(controller, 'needs'), - container: get(controller, 'container'), - unknownProperty: function(controllerName) { - var needs = this.needs; - var dependency, i, l; - - for (i=0, l=needs.length; i 0) { - Ember.assert(' `' + inspect(this) + ' specifies `needs`, but does ' + - "not have a container. Please ensure this controller was " + - "instantiated with a container.", - this.container || meta(this, false).descs.controllers !== defaultControllersComputedProperty); - - if (this.container) { - verifyNeedsDependencies(this, this.container, needs); - } - - // if needs then initialize controllers proxy - get(this, 'controllers'); - } - - this._super.apply(this, arguments); - }, - - /** - @method controllerFor - @see {Ember.Route#controllerFor} - @deprecated Use `needs` instead - */ - controllerFor: function(controllerName) { - Ember.deprecate("Controller#controllerFor is deprecated, please use Controller#needs instead"); - return controllerFor(get(this, 'container'), controllerName); - }, - - /** - Stores the instances of other controllers available from within - this controller. Any controller listed by name in the `needs` - property will be accessible by name through this property. - - ```javascript - App.CommentsController = Ember.ArrayController.extend({ - needs: ['post'], - postTitle: function(){ - var currentPost = this.get('controllers.post'); // instance of App.PostController - return currentPost.get('title'); - }.property('controllers.post.title') - }); - ``` - - @see {Ember.ControllerMixin#needs} - @property {Object} controllers - @default null - */ - controllers: defaultControllersComputedProperty - }); - - __exports__["default"] = ControllerMixin; - }); -enifed("ember-application/system/application", - ["ember-metal","ember-metal/property_get","ember-metal/property_set","ember-runtime/system/lazy_load","ember-application/system/dag","ember-runtime/system/namespace","ember-runtime/mixins/deferred","ember-application/system/resolver","ember-metal/platform","ember-metal/run_loop","ember-metal/utils","container/container","ember-runtime/controllers/controller","ember-metal/enumerable_utils","ember-runtime/controllers/object_controller","ember-runtime/controllers/array_controller","ember-handlebars/controls/select","ember-views/system/event_dispatcher","ember-views/system/jquery","ember-routing/system/route","ember-routing/system/router","ember-routing/location/hash_location","ember-routing/location/history_location","ember-routing/location/auto_location","ember-routing/location/none_location","ember-routing/system/cache","ember-metal/core","ember-handlebars-compiler","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __dependency11__, __dependency12__, __dependency13__, __dependency14__, __dependency15__, __dependency16__, __dependency17__, __dependency18__, __dependency19__, __dependency20__, __dependency21__, __dependency22__, __dependency23__, __dependency24__, __dependency25__, __dependency26__, __dependency27__, __dependency28__, __exports__) { - "use strict"; - /** - @module ember - @submodule ember-application - */ - - var Ember = __dependency1__["default"]; - // Ember.FEATURES, Ember.deprecate, Ember.assert, Ember.libraries, LOG_VERSION, Namespace, BOOTED - var get = __dependency2__.get; - var set = __dependency3__.set; - var runLoadHooks = __dependency4__.runLoadHooks; - var DAG = __dependency5__["default"]; - var Namespace = __dependency6__["default"]; - var DeferredMixin = __dependency7__["default"]; - var DefaultResolver = __dependency8__["default"]; - var create = __dependency9__.create; - var run = __dependency10__["default"]; - var canInvoke = __dependency11__.canInvoke; - var Container = __dependency12__["default"]; - var Controller = __dependency13__["default"]; - var EnumerableUtils = __dependency14__["default"]; - var ObjectController = __dependency15__["default"]; - var ArrayController = __dependency16__["default"]; - var SelectView = __dependency17__["default"]; - var EventDispatcher = __dependency18__["default"]; - //import ContainerDebugAdapter from "ember-extension-support/container_debug_adapter"; - var jQuery = __dependency19__["default"]; - var Route = __dependency20__["default"]; - var Router = __dependency21__["default"]; - var HashLocation = __dependency22__["default"]; - var HistoryLocation = __dependency23__["default"]; - var AutoLocation = __dependency24__["default"]; - var NoneLocation = __dependency25__["default"]; - var BucketCache = __dependency26__["default"]; - - var K = __dependency27__.K; - var EmberHandlebars = __dependency28__["default"]; - - var ContainerDebugAdapter; - function props(obj) { - var properties = []; - - for (var key in obj) { - properties.push(key); - } - - return properties; - } - - /** - An instance of `Ember.Application` is the starting point for every Ember - application. It helps to instantiate, initialize and coordinate the many - objects that make up your app. - - Each Ember app has one and only one `Ember.Application` object. In fact, the - very first thing you should do in your application is create the instance: - - ```javascript - window.App = Ember.Application.create(); - ``` - - Typically, the application object is the only global variable. All other - classes in your app should be properties on the `Ember.Application` instance, - which highlights its first role: a global namespace. - - For example, if you define a view class, it might look like this: - - ```javascript - App.MyView = Ember.View.extend(); - ``` - - By default, calling `Ember.Application.create()` will automatically initialize - your application by calling the `Ember.Application.initialize()` method. If - you need to delay initialization, you can call your app's `deferReadiness()` - method. When you are ready for your app to be initialized, call its - `advanceReadiness()` method. - - You can define a `ready` method on the `Ember.Application` instance, which - will be run by Ember when the application is initialized. - - Because `Ember.Application` inherits from `Ember.Namespace`, any classes - you create will have useful string representations when calling `toString()`. - See the `Ember.Namespace` documentation for more information. - - While you can think of your `Ember.Application` as a container that holds the - other classes in your application, there are several other responsibilities - going on under-the-hood that you may want to understand. - - ### Event Delegation - - Ember uses a technique called _event delegation_. This allows the framework - to set up a global, shared event listener instead of requiring each view to - do it manually. For example, instead of each view registering its own - `mousedown` listener on its associated element, Ember sets up a `mousedown` - listener on the `body`. - - If a `mousedown` event occurs, Ember will look at the target of the event and - start walking up the DOM node tree, finding corresponding views and invoking - their `mouseDown` method as it goes. - - `Ember.Application` has a number of default events that it listens for, as - well as a mapping from lowercase events to camel-cased view method names. For - example, the `keypress` event causes the `keyPress` method on the view to be - called, the `dblclick` event causes `doubleClick` to be called, and so on. - - If there is a bubbling browser event that Ember does not listen for by - default, you can specify custom events and their corresponding view method - names by setting the application's `customEvents` property: - - ```javascript - App = Ember.Application.create({ - customEvents: { - // add support for the paste event - paste: "paste" - } - }); - ``` - - By default, the application sets up these event listeners on the document - body. However, in cases where you are embedding an Ember application inside - an existing page, you may want it to set up the listeners on an element - inside the body. - - For example, if only events inside a DOM element with the ID of `ember-app` - should be delegated, set your application's `rootElement` property: - - ```javascript - window.App = Ember.Application.create({ - rootElement: '#ember-app' - }); - ``` - - The `rootElement` can be either a DOM element or a jQuery-compatible selector - string. Note that *views appended to the DOM outside the root element will - not receive events.* If you specify a custom root element, make sure you only - append views inside it! - - To learn more about the advantages of event delegation and the Ember view - layer, and a list of the event listeners that are setup by default, visit the - [Ember View Layer guide](http://emberjs.com/guides/understanding-ember/the-view-layer/#toc_event-delegation). - - ### Initializers - - Libraries on top of Ember can add initializers, like so: - - ```javascript - Ember.Application.initializer({ - name: 'api-adapter', - - initialize: function(container, application) { - application.register('api-adapter:main', ApiAdapter); - } - }); - ``` - - Initializers provide an opportunity to access the container, which - organizes the different components of an Ember application. Additionally - they provide a chance to access the instantiated application. Beyond - being used for libraries, initializers are also a great way to organize - dependency injection or setup in your own application. - - ### Routing - - In addition to creating your application's router, `Ember.Application` is - also responsible for telling the router when to start routing. Transitions - between routes can be logged with the `LOG_TRANSITIONS` flag, and more - detailed intra-transition logging can be logged with - the `LOG_TRANSITIONS_INTERNAL` flag: - - ```javascript - window.App = Ember.Application.create({ - LOG_TRANSITIONS: true, // basic logging of successful transitions - LOG_TRANSITIONS_INTERNAL: true // detailed logging of all routing steps - }); - ``` - - By default, the router will begin trying to translate the current URL into - application state once the browser emits the `DOMContentReady` event. If you - need to defer routing, you can call the application's `deferReadiness()` - method. Once routing can begin, call the `advanceReadiness()` method. - - If there is any setup required before routing begins, you can implement a - `ready()` method on your app that will be invoked immediately before routing - begins. - ``` - - @class Application - @namespace Ember - @extends Ember.Namespace - */ - - var Application = Namespace.extend(DeferredMixin, { - _suppressDeferredDeprecation: true, - - /** - The root DOM element of the Application. This can be specified as an - element or a - [jQuery-compatible selector string](http://api.jquery.com/category/selectors/). - - This is the element that will be passed to the Application's, - `eventDispatcher`, which sets up the listeners for event delegation. Every - view in your application should be a child of the element you specify here. - - @property rootElement - @type DOMElement - @default 'body' - */ - rootElement: 'body', - - /** - The `Ember.EventDispatcher` responsible for delegating events to this - application's views. - - The event dispatcher is created by the application at initialization time - and sets up event listeners on the DOM element described by the - application's `rootElement` property. - - See the documentation for `Ember.EventDispatcher` for more information. - - @property eventDispatcher - @type Ember.EventDispatcher - @default null - */ - eventDispatcher: null, - - /** - The DOM events for which the event dispatcher should listen. - - By default, the application's `Ember.EventDispatcher` listens - for a set of standard DOM events, such as `mousedown` and - `keyup`, and delegates them to your application's `Ember.View` - instances. - - If you would like additional bubbling events to be delegated to your - views, set your `Ember.Application`'s `customEvents` property - to a hash containing the DOM event name as the key and the - corresponding view method name as the value. For example: - - ```javascript - App = Ember.Application.create({ - customEvents: { - // add support for the paste event - paste: "paste" - } - }); - ``` - - @property customEvents - @type Object - @default null - */ - customEvents: null, - - // Start off the number of deferrals at 1. This will be - // decremented by the Application's own `initialize` method. - _readinessDeferrals: 1, - - init: function() { - if (!this.$) { this.$ = jQuery; } - this.__container__ = this.buildContainer(); - - this.Router = this.defaultRouter(); - - this._super(); - - this.scheduleInitialize(); - - Ember.libraries.registerCoreLibrary('Handlebars' + (EmberHandlebars.compile ? '' : '-runtime'), EmberHandlebars.VERSION); - Ember.libraries.registerCoreLibrary('jQuery', jQuery().jquery); - - if ( Ember.LOG_VERSION ) { - Ember.LOG_VERSION = false; // we only need to see this once per Application#init - - var nameLengths = EnumerableUtils.map(Ember.libraries, function(item) { - return get(item, "name.length"); - }); - - var maxNameLength = Math.max.apply(this, nameLengths); - - Ember.debug('-------------------------------'); - Ember.libraries.each(function(name, version) { - var spaces = new Array(maxNameLength - name.length + 1).join(" "); - Ember.debug([name, spaces, ' : ', version].join("")); - }); - Ember.debug('-------------------------------'); - } - }, - - /** - Build the container for the current application. - - Also register a default application view in case the application - itself does not. - - @private - @method buildContainer - @return {Ember.Container} the configured container - */ - buildContainer: function() { - var container = this.__container__ = Application.buildContainer(this); - - return container; - }, - - /** - If the application has not opted out of routing and has not explicitly - defined a router, supply a default router for the application author - to configure. - - This allows application developers to do: - - ```javascript - var App = Ember.Application.create(); - - App.Router.map(function() { - this.resource('posts'); - }); - ``` - - @private - @method defaultRouter - @return {Ember.Router} the default router - */ - - defaultRouter: function() { - if (this.Router === false) { return; } - var container = this.__container__; - - if (this.Router) { - container.unregister('router:main'); - container.register('router:main', this.Router); - } - - return container.lookupFactory('router:main'); - }, - - /** - Automatically initialize the application once the DOM has - become ready. - - The initialization itself is scheduled on the actions queue - which ensures that application loading finishes before - booting. - - If you are asynchronously loading code, you should call - `deferReadiness()` to defer booting, and then call - `advanceReadiness()` once all of your code has finished - loading. - - @private - @method scheduleInitialize - */ - scheduleInitialize: function() { - var self = this; - - if (!this.$ || this.$.isReady) { - run.schedule('actions', self, '_initialize'); - } else { - this.$().ready(function runInitialize() { - run(self, '_initialize'); - }); - } - }, - - /** - Use this to defer readiness until some condition is true. - - Example: - - ```javascript - App = Ember.Application.create(); - App.deferReadiness(); - - jQuery.getJSON("/auth-token", function(token) { - App.token = token; - App.advanceReadiness(); - }); - ``` - - This allows you to perform asynchronous setup logic and defer - booting your application until the setup has finished. - - However, if the setup requires a loading UI, it might be better - to use the router for this purpose. - - @method deferReadiness - */ - deferReadiness: function() { - Ember.assert("You must call deferReadiness on an instance of Ember.Application", this instanceof Application); - Ember.assert("You cannot defer readiness since the `ready()` hook has already been called.", this._readinessDeferrals > 0); - this._readinessDeferrals++; - }, - - /** - Call `advanceReadiness` after any asynchronous setup logic has completed. - Each call to `deferReadiness` must be matched by a call to `advanceReadiness` - or the application will never become ready and routing will not begin. - - @method advanceReadiness - @see {Ember.Application#deferReadiness} - */ - advanceReadiness: function() { - Ember.assert("You must call advanceReadiness on an instance of Ember.Application", this instanceof Application); - this._readinessDeferrals--; - - if (this._readinessDeferrals === 0) { - run.once(this, this.didBecomeReady); - } - }, - - /** - Registers a factory that can be used for dependency injection (with - `App.inject`) or for service lookup. Each factory is registered with - a full name including two parts: `type:name`. - - A simple example: - - ```javascript - var App = Ember.Application.create(); - App.Orange = Ember.Object.extend(); - App.register('fruit:favorite', App.Orange); - ``` - - Ember will resolve factories from the `App` namespace automatically. - For example `App.CarsController` will be discovered and returned if - an application requests `controller:cars`. - - An example of registering a controller with a non-standard name: - - ```javascript - var App = Ember.Application.create(), - Session = Ember.Controller.extend(); - - App.register('controller:session', Session); - - // The Session controller can now be treated like a normal controller, - // despite its non-standard name. - App.ApplicationController = Ember.Controller.extend({ - needs: ['session'] - }); - ``` - - Registered factories are **instantiated** by having `create` - called on them. Additionally they are **singletons**, each time - they are looked up they return the same instance. - - Some examples modifying that default behavior: - - ```javascript - var App = Ember.Application.create(); - - App.Person = Ember.Object.extend(); - App.Orange = Ember.Object.extend(); - App.Email = Ember.Object.extend(); - App.session = Ember.Object.create(); - - App.register('model:user', App.Person, {singleton: false }); - App.register('fruit:favorite', App.Orange); - App.register('communication:main', App.Email, {singleton: false}); - App.register('session', App.session, {instantiate: false}); - ``` - - @method register - @param fullName {String} type:name (e.g., 'model:user') - @param factory {Function} (e.g., App.Person) - @param options {Object} (optional) disable instantiation or singleton usage - **/ - register: function() { - var container = this.__container__; - container.register.apply(container, arguments); - }, - - /** - Define a dependency injection onto a specific factory or all factories - of a type. - - When Ember instantiates a controller, view, or other framework component - it can attach a dependency to that component. This is often used to - provide services to a set of framework components. - - An example of providing a session object to all controllers: - - ```javascript - var App = Ember.Application.create(), - Session = Ember.Object.extend({ isAuthenticated: false }); - - // A factory must be registered before it can be injected - App.register('session:main', Session); - - // Inject 'session:main' onto all factories of the type 'controller' - // with the name 'session' - App.inject('controller', 'session', 'session:main'); - - App.IndexController = Ember.Controller.extend({ - isLoggedIn: Ember.computed.alias('session.isAuthenticated') - }); - ``` - - Injections can also be performed on specific factories. - - ```javascript - App.inject(, , ) - App.inject('route', 'source', 'source:main') - App.inject('route:application', 'email', 'model:email') - ``` - - It is important to note that injections can only be performed on - classes that are instantiated by Ember itself. Instantiating a class - directly (via `create` or `new`) bypasses the dependency injection - system. - - Ember-Data instantiates its models in a unique manner, and consequently - injections onto models (or all models) will not work as expected. Injections - on models can be enabled by setting `Ember.MODEL_FACTORY_INJECTIONS` - to `true`. - - @method inject - @param factoryNameOrType {String} - @param property {String} - @param injectionName {String} - **/ - inject: function() { - var container = this.__container__; - container.injection.apply(container, arguments); - }, - - /** - Calling initialize manually is not supported. - - Please see Ember.Application#advanceReadiness and - Ember.Application#deferReadiness. - - @private - @deprecated - @method initialize - **/ - initialize: function() { - Ember.deprecate('Calling initialize manually is not supported. Please see Ember.Application#advanceReadiness and Ember.Application#deferReadiness'); - }, - - /** - Initialize the application. This happens automatically. - - Run any initializers and run the application load hook. These hooks may - choose to defer readiness. For example, an authentication hook might want - to defer readiness until the auth token has been retrieved. - - @private - @method _initialize - */ - _initialize: function() { - if (this.isDestroyed) { return; } - - // At this point, the App.Router must already be assigned - if (this.Router) { - var container = this.__container__; - container.unregister('router:main'); - container.register('router:main', this.Router); - } - - this.runInitializers(); - runLoadHooks('application', this); - - // At this point, any initializers or load hooks that would have wanted - // to defer readiness have fired. In general, advancing readiness here - // will proceed to didBecomeReady. - this.advanceReadiness(); - - return this; - }, - - /** - Reset the application. This is typically used only in tests. It cleans up - the application in the following order: - - 1. Deactivate existing routes - 2. Destroy all objects in the container - 3. Create a new application container - 4. Re-route to the existing url - - Typical Example: - - ```javascript - - var App; - - run(function() { - App = Ember.Application.create(); - }); - - module("acceptance test", { - setup: function() { - App.reset(); - } - }); - - test("first test", function() { - // App is freshly reset - }); - - test("first test", function() { - // App is again freshly reset - }); - ``` - - Advanced Example: - - Occasionally you may want to prevent the app from initializing during - setup. This could enable extra configuration, or enable asserting prior - to the app becoming ready. - - ```javascript - - var App; - - run(function() { - App = Ember.Application.create(); - }); - - module("acceptance test", { - setup: function() { - run(function() { - App.reset(); - App.deferReadiness(); - }); - } - }); - - test("first test", function() { - ok(true, 'something before app is initialized'); - - run(function() { - App.advanceReadiness(); - }); - ok(true, 'something after app is initialized'); - }); - ``` - - @method reset - **/ - reset: function() { - this._readinessDeferrals = 1; - - function handleReset() { - var router = this.__container__.lookup('router:main'); - router.reset(); - - run(this.__container__, 'destroy'); - - this.buildContainer(); - - run.schedule('actions', this, function() { - this._initialize(); - }); - } - - run.join(this, handleReset); - }, - - /** - @private - @method runInitializers - */ - runInitializers: function() { - var initializersByName = get(this.constructor, 'initializers'); - var initializers = props(initializersByName); - var container = this.__container__; - var graph = new DAG(); - var namespace = this; - var name, initializer; - - for (var i = 0; i < initializers.length; i++) { - initializer = initializersByName[initializers[i]]; - graph.addEdges(initializer.name, initializer.initialize, initializer.before, initializer.after); - } - - graph.topsort(function (vertex) { - var initializer = vertex.value; - Ember.assert("No application initializer named '" + vertex.name + "'", initializer); - initializer(container, namespace); - }); - }, - - /** - @private - @method didBecomeReady - */ - didBecomeReady: function() { - this.setupEventDispatcher(); - this.ready(); // user hook - this.startRouting(); - - if (!Ember.testing) { - // Eagerly name all classes that are already loaded - Ember.Namespace.processAll(); - Ember.BOOTED = true; - } - - this.resolve(this); - }, - - /** - Setup up the event dispatcher to receive events on the - application's `rootElement` with any registered - `customEvents`. - - @private - @method setupEventDispatcher - */ - setupEventDispatcher: function() { - var customEvents = get(this, 'customEvents'); - var rootElement = get(this, 'rootElement'); - var dispatcher = this.__container__.lookup('event_dispatcher:main'); - - set(this, 'eventDispatcher', dispatcher); - dispatcher.setup(customEvents, rootElement); - }, - - /** - If the application has a router, use it to route to the current URL, and - trigger a new call to `route` whenever the URL changes. - - @private - @method startRouting - @property router {Ember.Router} - */ - startRouting: function() { - var router = this.__container__.lookup('router:main'); - if (!router) { return; } - - router.startRouting(); - }, - - handleURL: function(url) { - var router = this.__container__.lookup('router:main'); - - router.handleURL(url); - }, - - /** - Called when the Application has become ready. - The call will be delayed until the DOM has become ready. - - @event ready - */ - ready: K, - - /** - @deprecated Use 'Resolver' instead - Set this to provide an alternate class to `Ember.DefaultResolver` - - - @property resolver - */ - resolver: null, - - /** - Set this to provide an alternate class to `Ember.DefaultResolver` - - @property resolver - */ - Resolver: null, - - willDestroy: function() { - Ember.BOOTED = false; - // Ensure deactivation of routes before objects are destroyed - this.__container__.lookup('router:main').reset(); - - this.__container__.destroy(); - }, - - initializer: function(options) { - this.constructor.initializer(options); - }, - - /** - @method then - @private - @deprecated - */ - then: function() { - Ember.deprecate('Do not use `.then` on an instance of Ember.Application. Please use the `.ready` hook instead.'); - - this._super.apply(this, arguments); - } - }); - - Application.reopenClass({ - initializers: create(null), - - /** - Initializer receives an object which has the following attributes: - `name`, `before`, `after`, `initialize`. The only required attribute is - `initialize, all others are optional. - - * `name` allows you to specify under which name the initializer is registered. - This must be a unique name, as trying to register two initializers with the - same name will result in an error. - - ```javascript - Ember.Application.initializer({ - name: 'namedInitializer', - initialize: function(container, application) { - Ember.debug("Running namedInitializer!"); - } - }); - ``` - - * `before` and `after` are used to ensure that this initializer is ran prior - or after the one identified by the value. This value can be a single string - or an array of strings, referencing the `name` of other initializers. - - An example of ordering initializers, we create an initializer named `first`: - - ```javascript - Ember.Application.initializer({ - name: 'first', - initialize: function(container, application) { - Ember.debug("First initializer!"); - } - }); - - // DEBUG: First initializer! - ``` - - We add another initializer named `second`, specifying that it should run - after the initializer named `first`: - - ```javascript - Ember.Application.initializer({ - name: 'second', - after: 'first', - - initialize: function(container, application) { - Ember.debug("Second initializer!"); - } - }); - - // DEBUG: First initializer! - // DEBUG: Second initializer! - ``` - - Afterwards we add a further initializer named `pre`, this time specifying - that it should run before the initializer named `first`: - - ```javascript - Ember.Application.initializer({ - name: 'pre', - before: 'first', - - initialize: function(container, application) { - Ember.debug("Pre initializer!"); - } - }); - - // DEBUG: Pre initializer! - // DEBUG: First initializer! - // DEBUG: Second initializer! - ``` - - Finally we add an initializer named `post`, specifying it should run after - both the `first` and the `second` initializers: - - ```javascript - Ember.Application.initializer({ - name: 'post', - after: ['first', 'second'], - - initialize: function(container, application) { - Ember.debug("Post initializer!"); - } - }); - - // DEBUG: Pre initializer! - // DEBUG: First initializer! - // DEBUG: Second initializer! - // DEBUG: Post initializer! - ``` - - * `initialize` is a callback function that receives two arguments, `container` - and `application` on which you can operate. - - Example of using `container` to preload data into the store: - - ```javascript - Ember.Application.initializer({ - name: "preload-data", - - initialize: function(container, application) { - var store = container.lookup('store:main'); - store.pushPayload(preloadedData); - } - }); - ``` - - Example of using `application` to register an adapter: - - ```javascript - Ember.Application.initializer({ - name: 'api-adapter', - - initialize: function(container, application) { - application.register('api-adapter:main', ApiAdapter); - } - }); - ``` - - @method initializer - @param initializer {Object} - */ - initializer: function(initializer) { - // If this is the first initializer being added to a subclass, we are going to reopen the class - // to make sure we have a new `initializers` object, which extends from the parent class' using - // prototypal inheritance. Without this, attempting to add initializers to the subclass would - // pollute the parent class as well as other subclasses. - if (this.superclass.initializers !== undefined && this.superclass.initializers === this.initializers) { - this.reopenClass({ - initializers: create(this.initializers) - }); - } - - Ember.assert("The initializer '" + initializer.name + "' has already been registered", !this.initializers[initializer.name]); - Ember.assert("An initializer cannot be registered without an initialize function", canInvoke(initializer, 'initialize')); - - this.initializers[initializer.name] = initializer; - }, - - /** - This creates a container with the default Ember naming conventions. - - It also configures the container: - - * registered views are created every time they are looked up (they are - not singletons) - * registered templates are not factories; the registered value is - returned directly. - * the router receives the application as its `namespace` property - * all controllers receive the router as their `target` and `controllers` - properties - * all controllers receive the application as their `namespace` property - * the application view receives the application controller as its - `controller` property - * the application view receives the application template as its - `defaultTemplate` property - - @private - @method buildContainer - @static - @param {Ember.Application} namespace the application to build the - container for. - @return {Ember.Container} the built container - */ - buildContainer: function(namespace) { - var container = new Container(); - - container.set = set; - container.resolver = resolverFor(namespace); - container.normalizeFullName = container.resolver.normalize; - container.describe = container.resolver.describe; - container.makeToString = container.resolver.makeToString; - - container.optionsForType('component', { singleton: false }); - container.optionsForType('view', { singleton: false }); - container.optionsForType('template', { instantiate: false }); - container.optionsForType('helper', { instantiate: false }); - - container.register('application:main', namespace, { instantiate: false }); - - container.register('controller:basic', Controller, { instantiate: false }); - container.register('controller:object', ObjectController, { instantiate: false }); - container.register('controller:array', ArrayController, { instantiate: false }); - - container.register('view:select', SelectView); - - container.register('route:basic', Route, { instantiate: false }); - container.register('event_dispatcher:main', EventDispatcher); - - container.register('router:main', Router); - container.injection('router:main', 'namespace', 'application:main'); - - container.register('location:auto', AutoLocation); - container.register('location:hash', HashLocation); - container.register('location:history', HistoryLocation); - container.register('location:none', NoneLocation); - - container.injection('controller', 'target', 'router:main'); - container.injection('controller', 'namespace', 'application:main'); - - container.register('-bucket-cache:main', BucketCache); - container.injection('router', '_bucketCache', '-bucket-cache:main'); - container.injection('route', '_bucketCache', '-bucket-cache:main'); - container.injection('controller', '_bucketCache', '-bucket-cache:main'); - - container.injection('route', 'router', 'router:main'); - container.injection('location', 'rootURL', '-location-setting:root-url'); - - // DEBUGGING - container.register('resolver-for-debugging:main', container.resolver.__resolver__, { instantiate: false }); - container.injection('container-debug-adapter:main', 'resolver', 'resolver-for-debugging:main'); - container.injection('data-adapter:main', 'containerDebugAdapter', 'container-debug-adapter:main'); - // Custom resolver authors may want to register their own ContainerDebugAdapter with this key - - // ES6TODO: resolve this via import once ember-application package is ES6'ed - if (!ContainerDebugAdapter) { ContainerDebugAdapter = requireModule('ember-extension-support/container_debug_adapter')['default']; } - container.register('container-debug-adapter:main', ContainerDebugAdapter); - - return container; - } - }); - - /** - This function defines the default lookup rules for container lookups: - - * templates are looked up on `Ember.TEMPLATES` - * other names are looked up on the application after classifying the name. - For example, `controller:post` looks up `App.PostController` by default. - * if the default lookup fails, look for registered classes on the container - - This allows the application to register default injections in the container - that could be overridden by the normal naming convention. - - @private - @method resolverFor - @param {Ember.Namespace} namespace the namespace to look for classes - @return {*} the resolved value for a given lookup - */ - function resolverFor(namespace) { - if (namespace.get('resolver')) { - Ember.deprecate('Application.resolver is deprecated in favor of Application.Resolver', false); - } - - var ResolverClass = namespace.get('resolver') || namespace.get('Resolver') || DefaultResolver; - var resolver = ResolverClass.create({ - namespace: namespace - }); - - function resolve(fullName) { - return resolver.resolve(fullName); - } - - resolve.describe = function(fullName) { - return resolver.lookupDescription(fullName); - }; - - resolve.makeToString = function(factory, fullName) { - return resolver.makeToString(factory, fullName); - }; - - resolve.normalize = function(fullName) { - if (resolver.normalize) { - return resolver.normalize(fullName); - } else { - Ember.deprecate('The Resolver should now provide a \'normalize\' function', false); - return fullName; - } - }; - - resolve.__resolver__ = resolver; - - return resolve; - } - - __exports__["default"] = Application; - }); -enifed("ember-application/system/dag", - ["ember-metal/error","exports"], - function(__dependency1__, __exports__) { - "use strict"; - var EmberError = __dependency1__["default"]; - - function visit(vertex, fn, visited, path) { - var name = vertex.name; - var vertices = vertex.incoming; - var names = vertex.incomingNames; - var len = names.length; - var i; - - if (!visited) { - visited = {}; - } - if (!path) { - path = []; - } - if (visited.hasOwnProperty(name)) { - return; - } - path.push(name); - visited[name] = true; - for (i = 0; i < len; i++) { - visit(vertices[names[i]], fn, visited, path); - } - fn(vertex, path); - path.pop(); - } - - - /** - * DAG stands for Directed acyclic graph. - * - * It is used to build a graph of dependencies checking that there isn't circular - * dependencies. p.e Registering initializers with a certain precedence order. - * - * @class DAG - * @constructor - */ - function DAG() { - this.names = []; - this.vertices = Object.create(null); - } - - /** - * DAG Vertex - * - * @class Vertex - * @constructor - */ - - function Vertex(name) { - this.name = name; - this.incoming = {}; - this.incomingNames = []; - this.hasOutgoing = false; - this.value = null; - } - - /** - * Adds a vertex entry to the graph unless it is already added. - * - * @private - * @method add - * @param {String} name The name of the vertex to add - */ - DAG.prototype.add = function(name) { - if (!name) { - throw new Error("Can't add Vertex without name"); - } - if (this.vertices[name] !== undefined) { - return this.vertices[name]; - } - var vertex = new Vertex(name); - this.vertices[name] = vertex; - this.names.push(name); - return vertex; - }; - - /** - * Adds a vertex to the graph and sets its value. - * - * @private - * @method map - * @param {String} name The name of the vertex. - * @param value The value to put in the vertex. - */ - DAG.prototype.map = function(name, value) { - this.add(name).value = value; - }; - - /** - * Connects the vertices with the given names, adding them to the graph if - * necessary, only if this does not produce is any circular dependency. - * - * @private - * @method addEdge - * @param {String} fromName The name the vertex where the edge starts. - * @param {String} toName The name the vertex where the edge ends. - */ - DAG.prototype.addEdge = function(fromName, toName) { - if (!fromName || !toName || fromName === toName) { - return; - } - var from = this.add(fromName); - var to = this.add(toName); - if (to.incoming.hasOwnProperty(fromName)) { - return; - } - function checkCycle(vertex, path) { - if (vertex.name === toName) { - throw new EmberError("cycle detected: " + toName + " <- " + path.join(" <- ")); - } - } - visit(from, checkCycle); - from.hasOutgoing = true; - to.incoming[fromName] = from; - to.incomingNames.push(fromName); - }; - - /** - * Visits all the vertex of the graph calling the given function with each one, - * ensuring that the vertices are visited respecting their precedence. - * - * @method topsort - * @param {Function} fn The function to be invoked on each vertex. - */ - DAG.prototype.topsort = function(fn) { - var visited = {}; - var vertices = this.vertices; - var names = this.names; - var len = names.length; - var i, vertex; - - for (i = 0; i < len; i++) { - vertex = vertices[names[i]]; - if (!vertex.hasOutgoing) { - visit(vertex, fn, visited); - } - } - }; - - /** - * Adds a vertex with the given name and value to the graph and joins it with the - * vertices referenced in _before_ and _after_. If there isn't vertices with those - * names, they are added too. - * - * If either _before_ or _after_ are falsy/empty, the added vertex will not have - * an incoming/outgoing edge. - * - * @method addEdges - * @param {String} name The name of the vertex to be added. - * @param value The value of that vertex. - * @param before An string or array of strings with the names of the vertices before - * which this vertex must be visited. - * @param after An string or array of strings with the names of the vertex after - * which this vertex must be visited. - * - */ - DAG.prototype.addEdges = function(name, value, before, after) { - var i; - this.map(name, value); - if (before) { - if (typeof before === 'string') { - this.addEdge(name, before); - } else { - for (i = 0; i < before.length; i++) { - this.addEdge(name, before[i]); - } - } - } - if (after) { - if (typeof after === 'string') { - this.addEdge(after, name); - } else { - for (i = 0; i < after.length; i++) { - this.addEdge(after[i], name); - } - } - } - }; - - __exports__["default"] = DAG; - }); -enifed("ember-application/system/resolver", - ["ember-metal/core","ember-metal/property_get","ember-metal/logger","ember-runtime/system/string","ember-runtime/system/object","ember-runtime/system/namespace","ember-handlebars","ember-metal/dictionary","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __exports__) { - "use strict"; - /** - @module ember - @submodule ember-application - */ - - var Ember = __dependency1__["default"]; - // Ember.TEMPLATES, Ember.assert - var get = __dependency2__.get; - var Logger = __dependency3__["default"]; - var classify = __dependency4__.classify; - var capitalize = __dependency4__.capitalize; - var decamelize = __dependency4__.decamelize; - var EmberObject = __dependency5__["default"]; - var Namespace = __dependency6__["default"]; - var EmberHandlebars = __dependency7__["default"]; - - var Resolver = EmberObject.extend({ - /** - This will be set to the Application instance when it is - created. - - @property namespace - */ - namespace: null, - normalize: Ember.required(Function), - resolve: Ember.required(Function), - parseName: Ember.required(Function), - lookupDescription: Ember.required(Function), - makeToString: Ember.required(Function), - resolveOther: Ember.required(Function), - _logLookup: Ember.required(Function) - }); - __exports__.Resolver = Resolver; - /** - The DefaultResolver defines the default lookup rules to resolve - container lookups before consulting the container for registered - items: - - * templates are looked up on `Ember.TEMPLATES` - * other names are looked up on the application after converting - the name. For example, `controller:post` looks up - `App.PostController` by default. - * there are some nuances (see examples below) - - ### How Resolving Works - - The container calls this object's `resolve` method with the - `fullName` argument. - - It first parses the fullName into an object using `parseName`. - - Then it checks for the presence of a type-specific instance - method of the form `resolve[Type]` and calls it if it exists. - For example if it was resolving 'template:post', it would call - the `resolveTemplate` method. - - Its last resort is to call the `resolveOther` method. - - The methods of this object are designed to be easy to override - in a subclass. For example, you could enhance how a template - is resolved like so: - - ```javascript - App = Ember.Application.create({ - Resolver: Ember.DefaultResolver.extend({ - resolveTemplate: function(parsedName) { - var resolvedTemplate = this._super(parsedName); - if (resolvedTemplate) { return resolvedTemplate; } - return Ember.TEMPLATES['not_found']; - } - }) - }); - ``` - - Some examples of how names are resolved: - - ``` - 'template:post' //=> Ember.TEMPLATES['post'] - 'template:posts/byline' //=> Ember.TEMPLATES['posts/byline'] - 'template:posts.byline' //=> Ember.TEMPLATES['posts/byline'] - 'template:blogPost' //=> Ember.TEMPLATES['blogPost'] - // OR - // Ember.TEMPLATES['blog_post'] - 'controller:post' //=> App.PostController - 'controller:posts.index' //=> App.PostsIndexController - 'controller:blog/post' //=> Blog.PostController - 'controller:basic' //=> Ember.Controller - 'route:post' //=> App.PostRoute - 'route:posts.index' //=> App.PostsIndexRoute - 'route:blog/post' //=> Blog.PostRoute - 'route:basic' //=> Ember.Route - 'view:post' //=> App.PostView - 'view:posts.index' //=> App.PostsIndexView - 'view:blog/post' //=> Blog.PostView - 'view:basic' //=> Ember.View - 'foo:post' //=> App.PostFoo - 'model:post' //=> App.Post - ``` - - @class DefaultResolver - @namespace Ember - @extends Ember.Object - */ - var dictionary = __dependency8__["default"]; - - __exports__["default"] = EmberObject.extend({ - /** - This will be set to the Application instance when it is - created. - - @property namespace - */ - namespace: null, - - init: function() { - this._parseNameCache = dictionary(null); - }, - normalize: function(fullName) { - var split = fullName.split(':', 2); - var type = split[0]; - var name = split[1]; - - Ember.assert("Tried to normalize a container name without a colon (:) in it. You probably tried to lookup a name that did not contain a type, a colon, and a name. A proper lookup name would be `view:post`.", split.length === 2); - - if (type !== 'template') { - var result = name; - - if (result.indexOf('.') > -1) { - result = result.replace(/\.(.)/g, function(m) { - return m.charAt(1).toUpperCase(); - }); - } - - if (name.indexOf('_') > -1) { - result = result.replace(/_(.)/g, function(m) { - return m.charAt(1).toUpperCase(); - }); - } - - return type + ':' + result; - } else { - return fullName; - } - }, - - - /** - This method is called via the container's resolver method. - It parses the provided `fullName` and then looks up and - returns the appropriate template or class. - - @method resolve - @param {String} fullName the lookup string - @return {Object} the resolved factory - */ - resolve: function(fullName) { - var parsedName = this.parseName(fullName); - var resolveMethodName = parsedName.resolveMethodName; - var resolved; - - if (!(parsedName.name && parsedName.type)) { - throw new TypeError('Invalid fullName: `' + fullName + '`, must be of the form `type:name` '); - } - - if (this[resolveMethodName]) { - resolved = this[resolveMethodName](parsedName); - } - - if (!resolved) { - resolved = this.resolveOther(parsedName); - } - - if (parsedName.root && parsedName.root.LOG_RESOLVER) { - this._logLookup(resolved, parsedName); - } - - return resolved; - }, - /** - Convert the string name of the form 'type:name' to - a Javascript object with the parsed aspects of the name - broken out. - - @protected - @param {String} fullName the lookup string - @method parseName - */ - - parseName: function(fullName) { - return this._parseNameCache[fullName] || ( - this._parseNameCache[fullName] = this._parseName(fullName) - ); - }, - - _parseName: function(fullName) { - var nameParts = fullName.split(':'); - var type = nameParts[0], fullNameWithoutType = nameParts[1]; - var name = fullNameWithoutType; - var namespace = get(this, 'namespace'); - var root = namespace; - - if (type !== 'template' && name.indexOf('/') !== -1) { - var parts = name.split('/'); - name = parts[parts.length - 1]; - var namespaceName = capitalize(parts.slice(0, -1).join('.')); - root = Namespace.byName(namespaceName); - - Ember.assert('You are looking for a ' + name + ' ' + type + ' in the ' + namespaceName + ' namespace, but the namespace could not be found', root); - } - - return { - fullName: fullName, - type: type, - fullNameWithoutType: fullNameWithoutType, - name: name, - root: root, - resolveMethodName: 'resolve' + classify(type) - }; - }, - - /** - Returns a human-readable description for a fullName. Used by the - Application namespace in assertions to describe the - precise name of the class that Ember is looking for, rather than - container keys. - - @protected - @param {String} fullName the lookup string - @method lookupDescription - */ - lookupDescription: function(fullName) { - var parsedName = this.parseName(fullName); - - if (parsedName.type === 'template') { - return 'template at ' + parsedName.fullNameWithoutType.replace(/\./g, '/'); - } - - var description = parsedName.root + '.' + classify(parsedName.name); - - if (parsedName.type !== 'model') { - description += classify(parsedName.type); - } - - return description; - }, - - makeToString: function(factory, fullName) { - return factory.toString(); - }, - /** - Given a parseName object (output from `parseName`), apply - the conventions expected by `Ember.Router` - - @protected - @param {Object} parsedName a parseName object with the parsed - fullName lookup string - @method useRouterNaming - */ - useRouterNaming: function(parsedName) { - parsedName.name = parsedName.name.replace(/\./g, '_'); - if (parsedName.name === 'basic') { - parsedName.name = ''; - } - }, - /** - Look up the template in Ember.TEMPLATES - - @protected - @param {Object} parsedName a parseName object with the parsed - fullName lookup string - @method resolveTemplate - */ - resolveTemplate: function(parsedName) { - var templateName = parsedName.fullNameWithoutType.replace(/\./g, '/'); - - if (Ember.TEMPLATES[templateName]) { - return Ember.TEMPLATES[templateName]; - } - - templateName = decamelize(templateName); - if (Ember.TEMPLATES[templateName]) { - return Ember.TEMPLATES[templateName]; - } - }, - - /** - Lookup the view using `resolveOther` - - @protected - @param {Object} parsedName a parseName object with the parsed - fullName lookup string - @method resolveView - */ - resolveView: function(parsedName) { - this.useRouterNaming(parsedName); - return this.resolveOther(parsedName); - }, - - /** - Lookup the controller using `resolveOther` - - @protected - @param {Object} parsedName a parseName object with the parsed - fullName lookup string - @method resolveController - */ - resolveController: function(parsedName) { - this.useRouterNaming(parsedName); - return this.resolveOther(parsedName); - }, - /** - Lookup the route using `resolveOther` - - @protected - @param {Object} parsedName a parseName object with the parsed - fullName lookup string - @method resolveRoute - */ - resolveRoute: function(parsedName) { - this.useRouterNaming(parsedName); - return this.resolveOther(parsedName); - }, - - /** - Lookup the model on the Application namespace - - @protected - @param {Object} parsedName a parseName object with the parsed - fullName lookup string - @method resolveModel - */ - resolveModel: function(parsedName) { - var className = classify(parsedName.name); - var factory = get(parsedName.root, className); - - if (factory) { return factory; } - }, - /** - Look up the specified object (from parsedName) on the appropriate - namespace (usually on the Application) - - @protected - @param {Object} parsedName a parseName object with the parsed - fullName lookup string - @method resolveHelper - */ - resolveHelper: function(parsedName) { - return this.resolveOther(parsedName) || EmberHandlebars.helpers[parsedName.fullNameWithoutType]; - }, - /** - Look up the specified object (from parsedName) on the appropriate - namespace (usually on the Application) - - @protected - @param {Object} parsedName a parseName object with the parsed - fullName lookup string - @method resolveOther - */ - resolveOther: function(parsedName) { - var className = classify(parsedName.name) + classify(parsedName.type); - var factory = get(parsedName.root, className); - if (factory) { return factory; } - }, - - /** - @method _logLookup - @param {Boolean} found - @param {Object} parsedName - @private - */ - _logLookup: function(found, parsedName) { - var symbol, padding; - - if (found) { symbol = '[✓]'; } - else { symbol = '[ ]'; } - - if (parsedName.fullName.length > 60) { - padding = '.'; - } else { - padding = new Array(60 - parsedName.fullName.length).join('.'); - } - - Logger.info(symbol, parsedName.fullName, padding, this.lookupDescription(parsedName.fullName)); - } - }); - }); -enifed("ember-debug", - ["ember-metal/core","ember-metal/error","ember-metal/logger"], - function(__dependency1__, __dependency2__, __dependency3__) { - "use strict"; - /*global __fail__*/ - - var Ember = __dependency1__["default"]; - var EmberError = __dependency2__["default"]; - var Logger = __dependency3__["default"]; - - /** - Ember Debug - - @module ember - @submodule ember-debug - */ - - /** - @class Ember - */ - - /** - Define an assertion that will throw an exception if the condition is not - met. Ember build tools will remove any calls to `Ember.assert()` when - doing a production build. Example: - - ```javascript - // Test for truthiness - Ember.assert('Must pass a valid object', obj); - - // Fail unconditionally - Ember.assert('This code path should never be run'); - ``` - - @method assert - @param {String} desc A description of the assertion. This will become - the text of the Error thrown if the assertion fails. - @param {Boolean} test Must be truthy for the assertion to pass. If - falsy, an exception will be thrown. - */ - Ember.assert = function(desc, test) { - if (!test) { - throw new EmberError("Assertion Failed: " + desc); - } - }; - - - /** - Display a warning with the provided message. Ember build tools will - remove any calls to `Ember.warn()` when doing a production build. - - @method warn - @param {String} message A warning to display. - @param {Boolean} test An optional boolean. If falsy, the warning - will be displayed. - */ - Ember.warn = function(message, test) { - if (!test) { - Logger.warn("WARNING: "+message); - if ('trace' in Logger) Logger.trace(); - } - }; - - /** - Display a debug notice. Ember build tools will remove any calls to - `Ember.debug()` when doing a production build. - - ```javascript - Ember.debug('I\'m a debug notice!'); - ``` - - @method debug - @param {String} message A debug message to display. - */ - Ember.debug = function(message) { - Logger.debug("DEBUG: "+message); - }; - - /** - Display a deprecation warning with the provided message and a stack trace - (Chrome and Firefox only). Ember build tools will remove any calls to - `Ember.deprecate()` when doing a production build. - - @method deprecate - @param {String} message A description of the deprecation. - @param {Boolean} test An optional boolean. If falsy, the deprecation - will be displayed. - */ - Ember.deprecate = function(message, test) { - if (test) { return; } - - if (Ember.ENV.RAISE_ON_DEPRECATION) { throw new EmberError(message); } - - var error; - - // When using new Error, we can't do the arguments check for Chrome. Alternatives are welcome - try { __fail__.fail(); } catch (e) { error = e; } - - if (Ember.LOG_STACKTRACE_ON_DEPRECATION && error.stack) { - var stack; - var stackStr = ''; - - if (error['arguments']) { - // Chrome - stack = error.stack.replace(/^\s+at\s+/gm, ''). - replace(/^([^\(]+?)([\n$])/gm, '{anonymous}($1)$2'). - replace(/^Object.\s*\(([^\)]+)\)/gm, '{anonymous}($1)').split('\n'); - stack.shift(); - } else { - // Firefox - stack = error.stack.replace(/(?:\n@:0)?\s+$/m, ''). - replace(/^\(/gm, '{anonymous}(').split('\n'); - } - - stackStr = "\n " + stack.slice(2).join("\n "); - message = message + stackStr; - } - - Logger.warn("DEPRECATION: "+message); - }; - - - - /** - Alias an old, deprecated method with its new counterpart. - - Display a deprecation warning with the provided message and a stack trace - (Chrome and Firefox only) when the assigned method is called. - - Ember build tools will not remove calls to `Ember.deprecateFunc()`, though - no warnings will be shown in production. - - ```javascript - Ember.oldMethod = Ember.deprecateFunc('Please use the new, updated method', Ember.newMethod); - ``` - - @method deprecateFunc - @param {String} message A description of the deprecation. - @param {Function} func The new function called to replace its deprecated counterpart. - @return {Function} a new function that wrapped the original function with a deprecation warning - */ - Ember.deprecateFunc = function(message, func) { - return function() { - Ember.deprecate(message); - return func.apply(this, arguments); - }; - }; - - - /** - Run a function meant for debugging. Ember build tools will remove any calls to - `Ember.runInDebug()` when doing a production build. - - ```javascript - Ember.runInDebug(function() { - Ember.Handlebars.EachView.reopen({ - didInsertElement: function() { - console.log('I\'m happy'); - } - }); - }); - ``` - - @method runInDebug - @param {Function} func The function to be executed. - @since 1.5.0 - */ - Ember.runInDebug = function(func) { - func(); - }; - - // Inform the developer about the Ember Inspector if not installed. - if (!Ember.testing) { - var isFirefox = typeof InstallTrigger !== 'undefined'; - var isChrome = !!window.chrome && !window.opera; - - if (typeof window !== 'undefined' && (isFirefox || isChrome) && window.addEventListener) { - window.addEventListener("load", function() { - if (document.documentElement && document.documentElement.dataset && !document.documentElement.dataset.emberExtension) { - var downloadURL; - - if(isChrome) { - downloadURL = 'https://chrome.google.com/webstore/detail/ember-inspector/bmdblncegkenkacieihfhpjfppoconhi'; - } else if(isFirefox) { - downloadURL = 'https://addons.mozilla.org/en-US/firefox/addon/ember-inspector/'; - } - - Ember.debug('For more advanced debugging, install the Ember Inspector from ' + downloadURL); - } - }, false); - } - } - }); -enifed("ember-extension-support", - ["ember-metal/core","ember-extension-support/data_adapter","ember-extension-support/container_debug_adapter"], - function(__dependency1__, __dependency2__, __dependency3__) { - "use strict"; - /** - Ember Extension Support - - @module ember - @submodule ember-extension-support - @requires ember-application - */ - - var Ember = __dependency1__["default"]; - var DataAdapter = __dependency2__["default"]; - var ContainerDebugAdapter = __dependency3__["default"]; - - Ember.DataAdapter = DataAdapter; - Ember.ContainerDebugAdapter = ContainerDebugAdapter; - }); -enifed("ember-extension-support/container_debug_adapter", - ["ember-metal/core","ember-runtime/system/native_array","ember-metal/utils","ember-runtime/system/string","ember-runtime/system/namespace","ember-runtime/system/object","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __exports__) { - "use strict"; - var Ember = __dependency1__["default"]; - var emberA = __dependency2__.A; - var typeOf = __dependency3__.typeOf; - var dasherize = __dependency4__.dasherize; - var classify = __dependency4__.classify; - var Namespace = __dependency5__["default"]; - var EmberObject = __dependency6__["default"]; - - /** - @module ember - @submodule ember-extension-support - */ - - /** - The `ContainerDebugAdapter` helps the container and resolver interface - with tools that debug Ember such as the - [Ember Extension](https://github.com/tildeio/ember-extension) - for Chrome and Firefox. - - This class can be extended by a custom resolver implementer - to override some of the methods with library-specific code. - - The methods likely to be overridden are: - - * `canCatalogEntriesByType` - * `catalogEntriesByType` - - The adapter will need to be registered - in the application's container as `container-debug-adapter:main` - - Example: - - ```javascript - Application.initializer({ - name: "containerDebugAdapter", - - initialize: function(container, application) { - application.register('container-debug-adapter:main', require('app/container-debug-adapter')); - } - }); - ``` - - @class ContainerDebugAdapter - @namespace Ember - @extends EmberObject - @since 1.5.0 - */ - __exports__["default"] = EmberObject.extend({ - /** - The container of the application being debugged. - This property will be injected - on creation. - - @property container - @default null - */ - container: null, - - /** - The resolver instance of the application - being debugged. This property will be injected - on creation. - - @property resolver - @default null - */ - resolver: null, - - /** - Returns true if it is possible to catalog a list of available - classes in the resolver for a given type. - - @method canCatalogEntriesByType - @param {String} type The type. e.g. "model", "controller", "route" - @return {boolean} whether a list is available for this type. - */ - canCatalogEntriesByType: function(type) { - if (type === 'model' || type === 'template') return false; - return true; - }, - - /** - Returns the available classes a given type. - - @method catalogEntriesByType - @param {String} type The type. e.g. "model", "controller", "route" - @return {Array} An array of strings. - */ - catalogEntriesByType: function(type) { - var namespaces = emberA(Namespace.NAMESPACES), types = emberA(), self = this; - var typeSuffixRegex = new RegExp(classify(type) + "$"); - - namespaces.forEach(function(namespace) { - if (namespace !== Ember) { - for (var key in namespace) { - if (!namespace.hasOwnProperty(key)) { continue; } - if (typeSuffixRegex.test(key)) { - var klass = namespace[key]; - if (typeOf(klass) === 'class') { - types.push(dasherize(key.replace(typeSuffixRegex, ''))); - } - } - } - } - }); - return types; - } - }); - }); -enifed("ember-extension-support/data_adapter", - ["ember-metal/core","ember-metal/property_get","ember-metal/run_loop","ember-runtime/system/string","ember-runtime/system/namespace","ember-runtime/system/object","ember-runtime/system/native_array","ember-application/system/application","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __exports__) { - "use strict"; - var Ember = __dependency1__["default"]; - var get = __dependency2__.get; - var run = __dependency3__["default"]; - var dasherize = __dependency4__.dasherize; - var Namespace = __dependency5__["default"]; - var EmberObject = __dependency6__["default"]; - var emberA = __dependency7__.A; - var Application = __dependency8__["default"]; - - /** - @module ember - @submodule ember-extension-support - */ - - /** - The `DataAdapter` helps a data persistence library - interface with tools that debug Ember such - as the [Ember Extension](https://github.com/tildeio/ember-extension) - for Chrome and Firefox. - - This class will be extended by a persistence library - which will override some of the methods with - library-specific code. - - The methods likely to be overridden are: - - * `getFilters` - * `detect` - * `columnsForType` - * `getRecords` - * `getRecordColumnValues` - * `getRecordKeywords` - * `getRecordFilterValues` - * `getRecordColor` - * `observeRecord` - - The adapter will need to be registered - in the application's container as `dataAdapter:main` - - Example: - - ```javascript - Application.initializer({ - name: "data-adapter", - - initialize: function(container, application) { - application.register('data-adapter:main', DS.DataAdapter); - } - }); - ``` - - @class DataAdapter - @namespace Ember - @extends EmberObject - */ - __exports__["default"] = EmberObject.extend({ - init: function() { - this._super(); - this.releaseMethods = emberA(); - }, - - /** - The container of the application being debugged. - This property will be injected - on creation. - - @property container - @default null - @since 1.3.0 - */ - container: null, - - - /** - The container-debug-adapter which is used - to list all models. - - @property containerDebugAdapter - @default undefined - @since 1.5.0 - **/ - containerDebugAdapter: undefined, - - /** - Number of attributes to send - as columns. (Enough to make the record - identifiable). - - @private - @property attributeLimit - @default 3 - @since 1.3.0 - */ - attributeLimit: 3, - - /** - Stores all methods that clear observers. - These methods will be called on destruction. - - @private - @property releaseMethods - @since 1.3.0 - */ - releaseMethods: emberA(), - - /** - Specifies how records can be filtered. - Records returned will need to have a `filterValues` - property with a key for every name in the returned array. - - @public - @method getFilters - @return {Array} List of objects defining filters. - The object should have a `name` and `desc` property. - */ - getFilters: function() { - return emberA(); - }, - - /** - Fetch the model types and observe them for changes. - - @public - @method watchModelTypes - - @param {Function} typesAdded Callback to call to add types. - Takes an array of objects containing wrapped types (returned from `wrapModelType`). - - @param {Function} typesUpdated Callback to call when a type has changed. - Takes an array of objects containing wrapped types. - - @return {Function} Method to call to remove all observers - */ - watchModelTypes: function(typesAdded, typesUpdated) { - var modelTypes = this.getModelTypes(); - var self = this; - var releaseMethods = emberA(); - var typesToSend; - - typesToSend = modelTypes.map(function(type) { - var klass = type.klass; - var wrapped = self.wrapModelType(klass, type.name); - releaseMethods.push(self.observeModelType(klass, typesUpdated)); - return wrapped; - }); - - typesAdded(typesToSend); - - var release = function() { - releaseMethods.forEach(function(fn) { fn(); }); - self.releaseMethods.removeObject(release); - }; - this.releaseMethods.pushObject(release); - return release; - }, - - _nameToClass: function(type) { - if (typeof type === 'string') { - type = this.container.lookupFactory('model:' + type); - } - return type; - }, - - /** - Fetch the records of a given type and observe them for changes. - - @public - @method watchRecords - - @param {Function} recordsAdded Callback to call to add records. - Takes an array of objects containing wrapped records. - The object should have the following properties: - columnValues: {Object} key and value of a table cell - object: {Object} the actual record object - - @param {Function} recordsUpdated Callback to call when a record has changed. - Takes an array of objects containing wrapped records. - - @param {Function} recordsRemoved Callback to call when a record has removed. - Takes the following parameters: - index: the array index where the records were removed - count: the number of records removed - - @return {Function} Method to call to remove all observers - */ - watchRecords: function(type, recordsAdded, recordsUpdated, recordsRemoved) { - var self = this, releaseMethods = emberA(), records = this.getRecords(type), release; - - var recordUpdated = function(updatedRecord) { - recordsUpdated([updatedRecord]); - }; - - var recordsToSend = records.map(function(record) { - releaseMethods.push(self.observeRecord(record, recordUpdated)); - return self.wrapRecord(record); - }); - - - var contentDidChange = function(array, idx, removedCount, addedCount) { - for (var i = idx; i < idx + addedCount; i++) { - var record = array.objectAt(i); - var wrapped = self.wrapRecord(record); - releaseMethods.push(self.observeRecord(record, recordUpdated)); - recordsAdded([wrapped]); - } - - if (removedCount) { - recordsRemoved(idx, removedCount); - } - }; - - var observer = { didChange: contentDidChange, willChange: Ember.K }; - records.addArrayObserver(self, observer); - - release = function() { - releaseMethods.forEach(function(fn) { fn(); }); - records.removeArrayObserver(self, observer); - self.releaseMethods.removeObject(release); - }; - - recordsAdded(recordsToSend); - - this.releaseMethods.pushObject(release); - return release; - }, - - /** - Clear all observers before destruction - @private - @method willDestroy - */ - willDestroy: function() { - this._super(); - this.releaseMethods.forEach(function(fn) { - fn(); - }); - }, - - /** - Detect whether a class is a model. - - Test that against the model class - of your persistence library - - @private - @method detect - @param {Class} klass The class to test - @return boolean Whether the class is a model class or not - */ - detect: function(klass) { - return false; - }, - - /** - Get the columns for a given model type. - - @private - @method columnsForType - @param {Class} type The model type - @return {Array} An array of columns of the following format: - name: {String} name of the column - desc: {String} Humanized description (what would show in a table column name) - */ - columnsForType: function(type) { - return emberA(); - }, - - /** - Adds observers to a model type class. - - @private - @method observeModelType - @param {Class} type The model type class - @param {Function} typesUpdated Called when a type is modified. - @return {Function} The function to call to remove observers - */ - - observeModelType: function(type, typesUpdated) { - var self = this; - var records = this.getRecords(type); - - var onChange = function() { - typesUpdated([self.wrapModelType(type)]); - }; - var observer = { - didChange: function() { - run.scheduleOnce('actions', this, onChange); - }, - willChange: Ember.K - }; - - records.addArrayObserver(this, observer); - - var release = function() { - records.removeArrayObserver(self, observer); - }; - - return release; - }, - - - /** - Wraps a given model type and observes changes to it. - - @private - @method wrapModelType - @param {Class} type A model class - @param {String} Optional name of the class - @return {Object} contains the wrapped type and the function to remove observers - Format: - type: {Object} the wrapped type - The wrapped type has the following format: - name: {String} name of the type - count: {Integer} number of records available - columns: {Columns} array of columns to describe the record - object: {Class} the actual Model type class - release: {Function} The function to remove observers - */ - wrapModelType: function(type, name) { - var records = this.getRecords(type); - var self = this; - var release, typeToSend; - - typeToSend = { - name: name || type.toString(), - count: get(records, 'length'), - columns: this.columnsForType(type), - object: type - }; - - - return typeToSend; - }, - - - /** - Fetches all models defined in the application. - - @private - @method getModelTypes - @return {Array} Array of model types - */ - getModelTypes: function() { - var self = this; - var containerDebugAdapter = this.get('containerDebugAdapter'); - var types; - - if (containerDebugAdapter.canCatalogEntriesByType('model')) { - types = containerDebugAdapter.catalogEntriesByType('model'); - } else { - types = this._getObjectsOnNamespaces(); - } - - // New adapters return strings instead of classes - types = emberA(types).map(function(name) { - return { - klass: self._nameToClass(name), - name: name - }; - }); - types = emberA(types).filter(function(type) { - return self.detect(type.klass); - }); - - return emberA(types); - }, - - /** - Loops over all namespaces and all objects - attached to them - - @private - @method _getObjectsOnNamespaces - @return {Array} Array of model type strings - */ - _getObjectsOnNamespaces: function() { - var namespaces = emberA(Namespace.NAMESPACES); - var types = emberA(); - var self = this; - - namespaces.forEach(function(namespace) { - for (var key in namespace) { - if (!namespace.hasOwnProperty(key)) { continue; } - // Even though we will filter again in `getModelTypes`, - // we should not call `lookupContainer` on non-models - // (especially when `Ember.MODEL_FACTORY_INJECTIONS` is `true`) - if (!self.detect(namespace[key])) { continue; } - var name = dasherize(key); - if (!(namespace instanceof Application) && namespace.toString()) { - name = namespace + '/' + name; - } - types.push(name); - } - }); - return types; - }, - - /** - Fetches all loaded records for a given type. - - @private - @method getRecords - @return {Array} An array of records. - This array will be observed for changes, - so it should update when new records are added/removed. - */ - getRecords: function(type) { - return emberA(); - }, - - /** - Wraps a record and observers changes to it. - - @private - @method wrapRecord - @param {Object} record The record instance. - @return {Object} The wrapped record. Format: - columnValues: {Array} - searchKeywords: {Array} - */ - wrapRecord: function(record) { - var recordToSend = { object: record }; - var columnValues = {}; - var self = this; - - recordToSend.columnValues = this.getRecordColumnValues(record); - recordToSend.searchKeywords = this.getRecordKeywords(record); - recordToSend.filterValues = this.getRecordFilterValues(record); - recordToSend.color = this.getRecordColor(record); - - return recordToSend; - }, - - /** - Gets the values for each column. - - @private - @method getRecordColumnValues - @return {Object} Keys should match column names defined - by the model type. - */ - getRecordColumnValues: function(record) { - return {}; - }, - - /** - Returns keywords to match when searching records. - - @private - @method getRecordKeywords - @return {Array} Relevant keywords for search. - */ - getRecordKeywords: function(record) { - return emberA(); - }, - - /** - Returns the values of filters defined by `getFilters`. - - @private - @method getRecordFilterValues - @param {Object} record The record instance - @return {Object} The filter values - */ - getRecordFilterValues: function(record) { - return {}; - }, - - /** - Each record can have a color that represents its state. - - @private - @method getRecordColor - @param {Object} record The record instance - @return {String} The record's color - Possible options: black, red, blue, green - */ - getRecordColor: function(record) { - return null; - }, - - /** - Observes all relevant properties and re-sends the wrapped record - when a change occurs. - - @private - @method observerRecord - @param {Object} record The record instance - @param {Function} recordUpdated The callback to call when a record is updated. - @return {Function} The function to call to remove all observers. - */ - observeRecord: function(record, recordUpdated) { - return function(){}; - } - }); - }); -enifed("ember-extension-support/initializers", - [], - function() { - "use strict"; - - }); -enifed("ember-handlebars-compiler", - ["ember-metal/core","exports"], - function(__dependency1__, __exports__) { - /* global Handlebars:true */ - - // Remove "use strict"; from transpiled module (in browser builds only) until - // https://bugs.webkit.org/show_bug.cgi?id=138038 is fixed - // - // REMOVE_USE_STRICT: true - - /** - @module ember - @submodule ember-handlebars-compiler - */ - - var Ember = __dependency1__["default"]; - - // ES6Todo: you'll need to import debugger once debugger is es6'd. - if (typeof Ember.assert === 'undefined') { Ember.assert = function(){}; } - if (typeof Ember.FEATURES === 'undefined') { Ember.FEATURES = { isEnabled: function(){} }; } - - var objectCreate = Object.create || function(parent) { - function F() {} - F.prototype = parent; - return new F(); - }; - - // set up for circular references later - var View, Component; - - // ES6Todo: when ember-debug is es6'ed import this. - // var emberAssert = Ember.assert; - var Handlebars = (Ember.imports && Ember.imports.Handlebars) || (this && this.Handlebars); - if (!Handlebars && typeof eriuqer === 'function') { - Handlebars = eriuqer('handlebars'); - } - - Ember.assert("Ember Handlebars requires Handlebars version 1.0 or 1.1. Include " + - "a SCRIPT tag in the HTML HEAD linking to the Handlebars file " + - "before you link to Ember.", Handlebars); - - Ember.assert("Ember Handlebars requires Handlebars version 1.0 or 1.1, " + - "COMPILER_REVISION expected: 4, got: " + Handlebars.COMPILER_REVISION + - " - Please note: Builds of master may have other COMPILER_REVISION values.", - Handlebars.COMPILER_REVISION === 4); - - /** - Prepares the Handlebars templating library for use inside Ember's view - system. - - The `Ember.Handlebars` object is the standard Handlebars library, extended to - use Ember's `get()` method instead of direct property access, which allows - computed properties to be used inside templates. - - To create an `Ember.Handlebars` template, call `Ember.Handlebars.compile()`. - This will return a function that can be used by `Ember.View` for rendering. - - @class Handlebars - @namespace Ember - */ - var EmberHandlebars = Ember.Handlebars = objectCreate(Handlebars); - - /** - Register a bound helper or custom view helper. - - ## Simple bound helper example - - ```javascript - Ember.Handlebars.helper('capitalize', function(value) { - return value.toUpperCase(); - }); - ``` - - The above bound helper can be used inside of templates as follows: - - ```handlebars - {{capitalize name}} - ``` - - In this case, when the `name` property of the template's context changes, - the rendered value of the helper will update to reflect this change. - - For more examples of bound helpers, see documentation for - `Ember.Handlebars.registerBoundHelper`. - - ## Custom view helper example - - Assuming a view subclass named `App.CalendarView` were defined, a helper - for rendering instances of this view could be registered as follows: - - ```javascript - Ember.Handlebars.helper('calendar', App.CalendarView): - ``` - - The above bound helper can be used inside of templates as follows: - - ```handlebars - {{calendar}} - ``` - - Which is functionally equivalent to: - - ```handlebars - {{view 'calendar'}} - ``` - - Options in the helper will be passed to the view in exactly the same - manner as with the `view` helper. - - @method helper - @for Ember.Handlebars - @param {String} name - @param {Function|Ember.View} function or view class constructor - @param {String} dependentKeys* - */ - EmberHandlebars.helper = function(name, value) { - if (!View) { View = requireModule('ember-views/views/view')['default']; } // ES6TODO: stupid circular dep - if (!Component) { Component = requireModule('ember-views/views/component')['default']; } // ES6TODO: stupid circular dep - - Ember.assert("You tried to register a component named '" + name + "', but component names must include a '-'", !Component.detect(value) || name.match(/-/)); - - if (View.detect(value)) { - EmberHandlebars.registerHelper(name, EmberHandlebars.makeViewHelper(value)); - } else { - EmberHandlebars.registerBoundHelper.apply(null, arguments); - } - }; - - /** - Returns a helper function that renders the provided ViewClass. - - Used internally by Ember.Handlebars.helper and other methods - involving helper/component registration. - - @private - @method makeViewHelper - @for Ember.Handlebars - @param {Function} ViewClass view class constructor - @since 1.2.0 - */ - EmberHandlebars.makeViewHelper = function(ViewClass) { - return function(options) { - Ember.assert("You can only pass attributes (such as name=value) not bare values to a helper for a View found in '" + ViewClass.toString() + "'", arguments.length < 2); - return EmberHandlebars.helpers.view.call(this, ViewClass, options); - }; - }; - - /** - @class helpers - @namespace Ember.Handlebars - */ - EmberHandlebars.helpers = objectCreate(Handlebars.helpers); - - /** - Override the the opcode compiler and JavaScript compiler for Handlebars. - - @class Compiler - @namespace Ember.Handlebars - @private - @constructor - */ - EmberHandlebars.Compiler = function() {}; - - // Handlebars.Compiler doesn't exist in runtime-only - if (Handlebars.Compiler) { - EmberHandlebars.Compiler.prototype = objectCreate(Handlebars.Compiler.prototype); - } - - EmberHandlebars.Compiler.prototype.compiler = EmberHandlebars.Compiler; - - /** - @class JavaScriptCompiler - @namespace Ember.Handlebars - @private - @constructor - */ - EmberHandlebars.JavaScriptCompiler = function() {}; - - // Handlebars.JavaScriptCompiler doesn't exist in runtime-only - if (Handlebars.JavaScriptCompiler) { - EmberHandlebars.JavaScriptCompiler.prototype = objectCreate(Handlebars.JavaScriptCompiler.prototype); - EmberHandlebars.JavaScriptCompiler.prototype.compiler = EmberHandlebars.JavaScriptCompiler; - } - - - EmberHandlebars.JavaScriptCompiler.prototype.namespace = "Ember.Handlebars"; - - EmberHandlebars.JavaScriptCompiler.prototype.initializeBuffer = function() { - return "''"; - }; - - /** - Override the default buffer for Ember Handlebars. By default, Handlebars - creates an empty String at the beginning of each invocation and appends to - it. Ember's Handlebars overrides this to append to a single shared buffer. - - @private - @method appendToBuffer - @param string {String} - */ - EmberHandlebars.JavaScriptCompiler.prototype.appendToBuffer = function(string) { - return "data.buffer.push("+string+");"; - }; - - // Hacks ahead: - // Handlebars presently has a bug where the `blockHelperMissing` hook - // doesn't get passed the name of the missing helper name, but rather - // gets passed the value of that missing helper evaluated on the current - // context, which is most likely `undefined` and totally useless. - // - // So we alter the compiled template function to pass the name of the helper - // instead, as expected. - // - // This can go away once the following is closed: - // https://github.com/wycats/handlebars.js/issues/634 - - var DOT_LOOKUP_REGEX = /helpers\.(.*?)\)/; - var BRACKET_STRING_LOOKUP_REGEX = /helpers\['(.*?)'/; - var INVOCATION_SPLITTING_REGEX = /(.*blockHelperMissing\.call\(.*)(stack[0-9]+)(,.*)/; - - EmberHandlebars.JavaScriptCompiler.stringifyLastBlockHelperMissingInvocation = function(source) { - var helperInvocation = source[source.length - 1]; - var helperName = (DOT_LOOKUP_REGEX.exec(helperInvocation) || BRACKET_STRING_LOOKUP_REGEX.exec(helperInvocation))[1]; - var matches = INVOCATION_SPLITTING_REGEX.exec(helperInvocation); - - source[source.length - 1] = matches[1] + "'" + helperName + "'" + matches[3]; - }; - - var stringifyBlockHelperMissing = EmberHandlebars.JavaScriptCompiler.stringifyLastBlockHelperMissingInvocation; - - var originalBlockValue = EmberHandlebars.JavaScriptCompiler.prototype.blockValue; - EmberHandlebars.JavaScriptCompiler.prototype.blockValue = function() { - originalBlockValue.apply(this, arguments); - stringifyBlockHelperMissing(this.source); - }; - - var originalAmbiguousBlockValue = EmberHandlebars.JavaScriptCompiler.prototype.ambiguousBlockValue; - EmberHandlebars.JavaScriptCompiler.prototype.ambiguousBlockValue = function() { - originalAmbiguousBlockValue.apply(this, arguments); - stringifyBlockHelperMissing(this.source); - }; - - /** - Rewrite simple mustaches from `{{foo}}` to `{{bind "foo"}}`. This means that - all simple mustaches in Ember's Handlebars will also set up an observer to - keep the DOM up to date when the underlying property changes. - - @private - @method mustache - @for Ember.Handlebars.Compiler - @param mustache - */ - EmberHandlebars.Compiler.prototype.mustache = function(mustache) { - if (!(mustache.params.length || mustache.hash)) { - var id = new Handlebars.AST.IdNode([{ part: '_triageMustache' }]); - - // Update the mustache node to include a hash value indicating whether the original node - // was escaped. This will allow us to properly escape values when the underlying value - // changes and we need to re-render the value. - if (!mustache.escaped) { - mustache.hash = mustache.hash || new Handlebars.AST.HashNode([]); - mustache.hash.pairs.push(["unescaped", new Handlebars.AST.StringNode("true")]); - } - mustache = new Handlebars.AST.MustacheNode([id].concat([mustache.id]), mustache.hash, !mustache.escaped); - } - - return Handlebars.Compiler.prototype.mustache.call(this, mustache); - }; - - /** - Used for precompilation of Ember Handlebars templates. This will not be used - during normal app execution. - - @method precompile - @for Ember.Handlebars - @static - @param {String|Object} value The template to precompile or an Handlebars AST - @param {Boolean} asObject optional parameter, defaulting to true, of whether or not the - compiled template should be returned as an Object or a String - */ - EmberHandlebars.precompile = function(value, asObject) { - var ast = Handlebars.parse(value); - - var options = { - knownHelpers: { - action: true, - unbound: true, - 'bind-attr': true, - template: true, - view: true, - _triageMustache: true - }, - data: true, - stringParams: true - }; - - asObject = asObject === undefined ? true : asObject; - - var environment = new EmberHandlebars.Compiler().compile(ast, options); - return new EmberHandlebars.JavaScriptCompiler().compile(environment, options, undefined, asObject); - }; - - // We don't support this for Handlebars runtime-only - if (Handlebars.compile) { - /** - The entry point for Ember Handlebars. This replaces the default - `Handlebars.compile` and turns on template-local data and String - parameters. - - @method compile - @for Ember.Handlebars - @static - @param {String} string The template to compile - @return {Function} - */ - EmberHandlebars.compile = function(string) { - var ast = Handlebars.parse(string); - var options = { data: true, stringParams: true }; - var environment = new EmberHandlebars.Compiler().compile(ast, options); - var templateSpec = new EmberHandlebars.JavaScriptCompiler().compile(environment, options, undefined, true); - - var template = EmberHandlebars.template(templateSpec); - template.isMethod = false; //Make sure we don't wrap templates with ._super - - return template; - }; - } - - __exports__["default"] = EmberHandlebars; - }); -enifed("ember-handlebars", - ["ember-handlebars-compiler","ember-metal/core","ember-runtime/system/lazy_load","ember-handlebars/loader","ember-handlebars/ext","ember-handlebars/string","ember-handlebars/helpers/shared","ember-handlebars/helpers/binding","ember-handlebars/helpers/collection","ember-handlebars/helpers/view","ember-handlebars/helpers/unbound","ember-handlebars/helpers/debug","ember-handlebars/helpers/each","ember-handlebars/helpers/template","ember-handlebars/helpers/partial","ember-handlebars/helpers/yield","ember-handlebars/helpers/loc","ember-handlebars/controls/checkbox","ember-handlebars/controls/select","ember-handlebars/controls/text_area","ember-handlebars/controls/text_field","ember-handlebars/controls/text_support","ember-handlebars/controls","ember-handlebars/component_lookup","ember-handlebars/views/handlebars_bound_view","ember-handlebars/views/metamorph_view","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __dependency11__, __dependency12__, __dependency13__, __dependency14__, __dependency15__, __dependency16__, __dependency17__, __dependency18__, __dependency19__, __dependency20__, __dependency21__, __dependency22__, __dependency23__, __dependency24__, __dependency25__, __dependency26__, __exports__) { - "use strict"; - var EmberHandlebars = __dependency1__["default"]; - var Ember = __dependency2__["default"]; - // to add to globals - - var runLoadHooks = __dependency3__.runLoadHooks; - var bootstrap = __dependency4__["default"]; - - var normalizePath = __dependency5__.normalizePath; - var template = __dependency5__.template; - var makeBoundHelper = __dependency5__.makeBoundHelper; - var registerBoundHelper = __dependency5__.registerBoundHelper; - var resolveHash = __dependency5__.resolveHash; - var resolveParams = __dependency5__.resolveParams; - var getEscaped = __dependency5__.getEscaped; - var handlebarsGet = __dependency5__.handlebarsGet; - var evaluateUnboundHelper = __dependency5__.evaluateUnboundHelper; - var helperMissingHelper = __dependency5__.helperMissingHelper; - var blockHelperMissingHelper = __dependency5__.blockHelperMissingHelper; - - - // side effect of extending StringUtils of htmlSafe - - var resolvePaths = __dependency7__["default"]; - var bind = __dependency8__.bind; - var _triageMustacheHelper = __dependency8__._triageMustacheHelper; - var resolveHelper = __dependency8__.resolveHelper; - var bindHelper = __dependency8__.bindHelper; - var boundIfHelper = __dependency8__.boundIfHelper; - var unboundIfHelper = __dependency8__.unboundIfHelper; - var withHelper = __dependency8__.withHelper; - var ifHelper = __dependency8__.ifHelper; - var unlessHelper = __dependency8__.unlessHelper; - var bindAttrHelper = __dependency8__.bindAttrHelper; - var bindAttrHelperDeprecated = __dependency8__.bindAttrHelperDeprecated; - var bindClasses = __dependency8__.bindClasses; - - var collectionHelper = __dependency9__["default"]; - var ViewHelper = __dependency10__.ViewHelper; - var viewHelper = __dependency10__.viewHelper; - var unboundHelper = __dependency11__["default"]; - var logHelper = __dependency12__.logHelper; - var debuggerHelper = __dependency12__.debuggerHelper; - var EachView = __dependency13__.EachView; - var GroupedEach = __dependency13__.GroupedEach; - var eachHelper = __dependency13__.eachHelper; - var templateHelper = __dependency14__["default"]; - var partialHelper = __dependency15__["default"]; - var yieldHelper = __dependency16__["default"]; - var locHelper = __dependency17__["default"]; - - - var Checkbox = __dependency18__["default"]; - var Select = __dependency19__.Select; - var SelectOption = __dependency19__.SelectOption; - var SelectOptgroup = __dependency19__.SelectOptgroup; - var TextArea = __dependency20__["default"]; - var TextField = __dependency21__["default"]; - var TextSupport = __dependency22__["default"]; - var inputHelper = __dependency23__.inputHelper; - var textareaHelper = __dependency23__.textareaHelper; - - - var ComponentLookup = __dependency24__["default"]; - var _HandlebarsBoundView = __dependency25__._HandlebarsBoundView; - var SimpleHandlebarsView = __dependency25__.SimpleHandlebarsView; - var _wrapMap = __dependency26__._wrapMap; - var _SimpleMetamorphView = __dependency26__._SimpleMetamorphView; - var _MetamorphView = __dependency26__._MetamorphView; - var _Metamorph = __dependency26__._Metamorph; - - - /** - Ember Handlebars - - @module ember - @submodule ember-handlebars - @requires ember-views - */ - - // Ember.Handlebars.Globals - EmberHandlebars.bootstrap = bootstrap; - EmberHandlebars.template = template; - EmberHandlebars.makeBoundHelper = makeBoundHelper; - EmberHandlebars.registerBoundHelper = registerBoundHelper; - EmberHandlebars.resolveHash = resolveHash; - EmberHandlebars.resolveParams = resolveParams; - EmberHandlebars.resolveHelper = resolveHelper; - EmberHandlebars.get = handlebarsGet; - EmberHandlebars.getEscaped = getEscaped; - EmberHandlebars.evaluateUnboundHelper = evaluateUnboundHelper; - EmberHandlebars.bind = bind; - EmberHandlebars.bindClasses = bindClasses; - EmberHandlebars.EachView = EachView; - EmberHandlebars.GroupedEach = GroupedEach; - EmberHandlebars.resolvePaths = resolvePaths; - EmberHandlebars.ViewHelper = ViewHelper; - EmberHandlebars.normalizePath = normalizePath; - - - // Ember Globals - Ember.Handlebars = EmberHandlebars; - Ember.ComponentLookup = ComponentLookup; - Ember._SimpleHandlebarsView = SimpleHandlebarsView; - Ember._HandlebarsBoundView = _HandlebarsBoundView; - Ember._SimpleMetamorphView = _SimpleMetamorphView; - Ember._MetamorphView = _MetamorphView; - Ember._Metamorph = _Metamorph; - Ember._metamorphWrapMap = _wrapMap; - Ember.TextSupport = TextSupport; - Ember.Checkbox = Checkbox; - Ember.Select = Select; - Ember.SelectOption = SelectOption; - Ember.SelectOptgroup = SelectOptgroup; - Ember.TextArea = TextArea; - Ember.TextField = TextField; - Ember.TextSupport = TextSupport; - - // register helpers - EmberHandlebars.registerHelper('helperMissing', helperMissingHelper); - EmberHandlebars.registerHelper('blockHelperMissing', blockHelperMissingHelper); - EmberHandlebars.registerHelper('bind', bindHelper); - EmberHandlebars.registerHelper('boundIf', boundIfHelper); - EmberHandlebars.registerHelper('_triageMustache', _triageMustacheHelper); - EmberHandlebars.registerHelper('unboundIf', unboundIfHelper); - EmberHandlebars.registerHelper('with', withHelper); - EmberHandlebars.registerHelper('if', ifHelper); - EmberHandlebars.registerHelper('unless', unlessHelper); - EmberHandlebars.registerHelper('bind-attr', bindAttrHelper); - EmberHandlebars.registerHelper('bindAttr', bindAttrHelperDeprecated); - EmberHandlebars.registerHelper('collection', collectionHelper); - EmberHandlebars.registerHelper("log", logHelper); - EmberHandlebars.registerHelper("debugger", debuggerHelper); - EmberHandlebars.registerHelper("each", eachHelper); - EmberHandlebars.registerHelper("loc", locHelper); - EmberHandlebars.registerHelper("partial", partialHelper); - EmberHandlebars.registerHelper("template", templateHelper); - EmberHandlebars.registerHelper("yield", yieldHelper); - EmberHandlebars.registerHelper("view", viewHelper); - EmberHandlebars.registerHelper("unbound", unboundHelper); - EmberHandlebars.registerHelper("input", inputHelper); - EmberHandlebars.registerHelper("textarea", textareaHelper); - - // run load hooks - runLoadHooks('Ember.Handlebars', EmberHandlebars); - - __exports__["default"] = EmberHandlebars; - }); -enifed("ember-handlebars/component_lookup", - ["ember-runtime/system/object","exports"], - function(__dependency1__, __exports__) { - "use strict"; - var EmberObject = __dependency1__["default"]; - - var ComponentLookup = EmberObject.extend({ - lookupFactory: function(name, container) { - - container = container || this.container; - - var fullName = 'component:' + name; - var templateFullName = 'template:components/' + name; - var templateRegistered = container && container.has(templateFullName); - - if (templateRegistered) { - container.injection(fullName, 'layout', templateFullName); - } - - var Component = container.lookupFactory(fullName); - - // Only treat as a component if either the component - // or a template has been registered. - if (templateRegistered || Component) { - if (!Component) { - container.register(fullName, Ember.Component); - Component = container.lookupFactory(fullName); - } - return Component; - } - } - }); - - __exports__["default"] = ComponentLookup; - }); -enifed("ember-handlebars/controls", - ["ember-handlebars/controls/checkbox","ember-handlebars/controls/text_field","ember-handlebars/controls/text_area","ember-metal/core","ember-handlebars-compiler","ember-handlebars/ext","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __exports__) { - "use strict"; - var Checkbox = __dependency1__["default"]; - var TextField = __dependency2__["default"]; - var TextArea = __dependency3__["default"]; - - var Ember = __dependency4__["default"]; - // Ember.assert - // var emberAssert = Ember.assert; - - var EmberHandlebars = __dependency5__["default"]; - var handlebarsGet = __dependency6__.handlebarsGet; - var helpers = EmberHandlebars.helpers; - /** - @module ember - @submodule ember-handlebars-compiler - */ - - function _resolveOption(context, options, key) { - if (options.hashTypes[key] === "ID") { - return handlebarsGet(context, options.hash[key], options); - } else { - return options.hash[key]; - } - } - - /** - - The `{{input}}` helper inserts an HTML `` tag into the template, - with a `type` value of either `text` or `checkbox`. If no `type` is provided, - `text` will be the default value applied. The attributes of `{{input}}` - match those of the native HTML tag as closely as possible for these two types. - - ## Use as text field - An `{{input}}` with no `type` or a `type` of `text` will render an HTML text input. - The following HTML attributes can be set via the helper: - - - - - - - - - - - - -
`readonly``required``autofocus`
`value``placeholder``disabled`
`size``tabindex``maxlength`
`name``min``max`
`pattern``accept``autocomplete`
`autosave``formaction``formenctype`
`formmethod``formnovalidate``formtarget`
`height``inputmode``multiple`
`step``width``form`
`selectionDirection``spellcheck` 
- - - When set to a quoted string, these values will be directly applied to the HTML - element. When left unquoted, these values will be bound to a property on the - template's current rendering context (most typically a controller instance). - - ## Unbound: - - ```handlebars - {{input value="http://www.facebook.com"}} - ``` - - - ```html - - ``` - - ## Bound: - - ```javascript - App.ApplicationController = Ember.Controller.extend({ - firstName: "Stanley", - entryNotAllowed: true - }); - ``` - - - ```handlebars - {{input type="text" value=firstName disabled=entryNotAllowed size="50"}} - ``` - - - ```html - - ``` - - ## Actions - - The helper can send multiple actions based on user events. - - The action property defines the action which is sent when - the user presses the return key. - - ```handlebars - {{input action="submit"}} - ``` - - The helper allows some user events to send actions. - - * `enter` - * `insert-newline` - * `escape-press` - * `focus-in` - * `focus-out` - * `key-press` - - - For example, if you desire an action to be sent when the input is blurred, - you only need to setup the action name to the event name property. - - ```handlebars - {{input focus-in="alertMessage"}} - ``` - - See more about [Text Support Actions](/api/classes/Ember.TextField.html) - - ## Extension - - Internally, `{{input type="text"}}` creates an instance of `Ember.TextField`, passing - arguments from the helper to `Ember.TextField`'s `create` method. You can extend the - capabilities of text inputs in your applications by reopening this class. For example, - if you are building a Bootstrap project where `data-*` attributes are used, you - can add one to the `TextField`'s `attributeBindings` property: - - - ```javascript - Ember.TextField.reopen({ - attributeBindings: ['data-error'] - }); - ``` - - Keep in mind when writing `Ember.TextField` subclasses that `Ember.TextField` - itself extends `Ember.Component`, meaning that it does NOT inherit - the `controller` of the parent view. - - See more about [Ember components](/api/classes/Ember.Component.html) - - - ## Use as checkbox - - An `{{input}}` with a `type` of `checkbox` will render an HTML checkbox input. - The following HTML attributes can be set via the helper: - - * `checked` - * `disabled` - * `tabindex` - * `indeterminate` - * `name` - * `autofocus` - * `form` - - - When set to a quoted string, these values will be directly applied to the HTML - element. When left unquoted, these values will be bound to a property on the - template's current rendering context (most typically a controller instance). - - ## Unbound: - - ```handlebars - {{input type="checkbox" name="isAdmin"}} - ``` - - ```html - - ``` - - ## Bound: - - ```javascript - App.ApplicationController = Ember.Controller.extend({ - isAdmin: true - }); - ``` - - - ```handlebars - {{input type="checkbox" checked=isAdmin }} - ``` - - - ```html - - ``` - - ## Extension - - Internally, `{{input type="checkbox"}}` creates an instance of `Ember.Checkbox`, passing - arguments from the helper to `Ember.Checkbox`'s `create` method. You can extend the - capablilties of checkbox inputs in your applications by reopening this class. For example, - if you wanted to add a css class to all checkboxes in your application: - - - ```javascript - Ember.Checkbox.reopen({ - classNames: ['my-app-checkbox'] - }); - ``` - - - @method input - @for Ember.Handlebars.helpers - @param {Hash} options - */ - function inputHelper(options) { - Ember.assert('You can only pass attributes to the `input` helper, not arguments', arguments.length < 2); - - var hash = options.hash; - var types = options.hashTypes; - var inputType = _resolveOption(this, options, 'type'); - var onEvent = hash.on; - - if (inputType === 'checkbox') { - delete hash.type; - delete types.type; - - Ember.assert("{{input type='checkbox'}} does not support setting `value=someBooleanValue`; you must use `checked=someBooleanValue` instead.", options.hashTypes.value !== 'ID'); - - return helpers.view.call(this, Checkbox, options); - } else { - delete hash.on; - - hash.onEvent = onEvent || 'enter'; - return helpers.view.call(this, TextField, options); - } - } - - __exports__.inputHelper = inputHelper;/** - `{{textarea}}` inserts a new instance of ` - ``` - - Bound: - - In the following example, the `writtenWords` property on `App.ApplicationController` - will be updated live as the user types 'Lots of text that IS bound' into - the text area of their browser's window. - - ```javascript - App.ApplicationController = Ember.Controller.extend({ - writtenWords: "Lots of text that IS bound" - }); - ``` - - ```handlebars - {{textarea value=writtenWords}} - ``` - - Would result in the following HTML: - - ```html - - ``` - - If you wanted a one way binding between the text area and a div tag - somewhere else on your screen, you could use `Ember.computed.oneWay`: - - ```javascript - App.ApplicationController = Ember.Controller.extend({ - writtenWords: "Lots of text that IS bound", - outputWrittenWords: Ember.computed.oneWay("writtenWords") - }); - ``` - - ```handlebars - {{textarea value=writtenWords}} - -
- {{outputWrittenWords}} -
- ``` - - Would result in the following HTML: - - ```html - - - <-- the following div will be updated in real time as you type --> - -
- Lots of text that IS bound -
- ``` - - Finally, this example really shows the power and ease of Ember when two - properties are bound to eachother via `Ember.computed.alias`. Type into - either text area box and they'll both stay in sync. Note that - `Ember.computed.alias` costs more in terms of performance, so only use it when - your really binding in both directions: - - ```javascript - App.ApplicationController = Ember.Controller.extend({ - writtenWords: "Lots of text that IS bound", - twoWayWrittenWords: Ember.computed.alias("writtenWords") - }); - ``` - - ```handlebars - {{textarea value=writtenWords}} - {{textarea value=twoWayWrittenWords}} - ``` - - ```html - - - <-- both updated in real time --> - - - ``` - - ## Actions - - The helper can send multiple actions based on user events. - - The action property defines the action which is send when - the user presses the return key. - - ```handlebars - {{input action="submit"}} - ``` - - The helper allows some user events to send actions. - - * `enter` - * `insert-newline` - * `escape-press` - * `focus-in` - * `focus-out` - * `key-press` - - For example, if you desire an action to be sent when the input is blurred, - you only need to setup the action name to the event name property. - - ```handlebars - {{textarea focus-in="alertMessage"}} - ``` - - See more about [Text Support Actions](/api/classes/Ember.TextArea.html) - - ## Extension - - Internally, `{{textarea}}` creates an instance of `Ember.TextArea`, passing - arguments from the helper to `Ember.TextArea`'s `create` method. You can - extend the capabilities of text areas in your application by reopening this - class. For example, if you are building a Bootstrap project where `data-*` - attributes are used, you can globally add support for a `data-*` attribute - on all `{{textarea}}`s' in your app by reopening `Ember.TextArea` or - `Ember.TextSupport` and adding it to the `attributeBindings` concatenated - property: - - ```javascript - Ember.TextArea.reopen({ - attributeBindings: ['data-error'] - }); - ``` - - Keep in mind when writing `Ember.TextArea` subclasses that `Ember.TextArea` - itself extends `Ember.Component`, meaning that it does NOT inherit - the `controller` of the parent view. - - See more about [Ember components](/api/classes/Ember.Component.html) - - @method textarea - @for Ember.Handlebars.helpers - @param {Hash} options - */ - function textareaHelper(options) { - Ember.assert('You can only pass attributes to the `textarea` helper, not arguments', arguments.length < 2); - - var hash = options.hash; - var types = options.hashTypes; - - return helpers.view.call(this, TextArea, options); - } - - __exports__.textareaHelper = textareaHelper; - }); -enifed("ember-handlebars/controls/checkbox", - ["ember-metal/property_get","ember-metal/property_set","ember-views/views/view","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __exports__) { - "use strict"; - var get = __dependency1__.get; - var set = __dependency2__.set; - var View = __dependency3__["default"]; - - /** - @module ember - @submodule ember-handlebars - */ - - /** - The internal class used to create text inputs when the `{{input}}` - helper is used with `type` of `checkbox`. - - See [handlebars.helpers.input](/api/classes/Ember.Handlebars.helpers.html#method_input) for usage details. - - ## Direct manipulation of `checked` - - The `checked` attribute of an `Ember.Checkbox` object should always be set - through the Ember object or by interacting with its rendered element - representation via the mouse, keyboard, or touch. Updating the value of the - checkbox via jQuery will result in the checked value of the object and its - element losing synchronization. - - ## Layout and LayoutName properties - - Because HTML `input` elements are self closing `layout` and `layoutName` - properties will not be applied. See [Ember.View](/api/classes/Ember.View.html)'s - layout section for more information. - - @class Checkbox - @namespace Ember - @extends Ember.View - */ - __exports__["default"] = View.extend({ - instrumentDisplay: '{{input type="checkbox"}}', - - classNames: ['ember-checkbox'], - - tagName: 'input', - - attributeBindings: [ - 'type', - 'checked', - 'indeterminate', - 'disabled', - 'tabindex', - 'name', - 'autofocus', - 'required', - 'form' - ], - - type: 'checkbox', - checked: false, - disabled: false, - indeterminate: false, - - init: function() { - this._super(); - this.on('change', this, this._updateElementValue); - }, - - didInsertElement: function() { - this._super(); - get(this, 'element').indeterminate = !!get(this, 'indeterminate'); - }, - - _updateElementValue: function() { - set(this, 'checked', this.$().prop('checked')); - } - }); - }); -enifed("ember-handlebars/controls/select", - ["ember-handlebars-compiler","ember-metal/enumerable_utils","ember-metal/property_get","ember-metal/property_set","ember-views/views/view","ember-views/views/collection_view","ember-metal/utils","ember-metal/is_none","ember-metal/computed","ember-runtime/system/native_array","ember-metal/mixin","ember-metal/properties","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __dependency11__, __dependency12__, __exports__) { - "use strict"; - /** - @module ember - @submodule ember-handlebars - */ - - var EmberHandlebars = __dependency1__["default"]; - - var forEach = __dependency2__.forEach; - var indexOf = __dependency2__.indexOf; - var indexesOf = __dependency2__.indexesOf; - var replace = __dependency2__.replace; - - var get = __dependency3__.get; - var set = __dependency4__.set; - var View = __dependency5__["default"]; - var CollectionView = __dependency6__["default"]; - var isArray = __dependency7__.isArray; - var isNone = __dependency8__["default"]; - var computed = __dependency9__.computed; - var emberA = __dependency10__.A; - var observer = __dependency11__.observer; - var defineProperty = __dependency12__.defineProperty; - - var precompileTemplate = EmberHandlebars.compile; - - var SelectOption = View.extend({ - instrumentDisplay: 'Ember.SelectOption', - - tagName: 'option', - attributeBindings: ['value', 'selected'], - - defaultTemplate: function(context, options) { - options = { data: options.data, hash: {} }; - EmberHandlebars.helpers.bind.call(context, "view.label", options); - }, - - init: function() { - this.labelPathDidChange(); - this.valuePathDidChange(); - - this._super(); - }, - - selected: computed(function() { - var content = get(this, 'content'); - var selection = get(this, 'parentView.selection'); - if (get(this, 'parentView.multiple')) { - return selection && indexOf(selection, content.valueOf()) > -1; - } else { - // Primitives get passed through bindings as objects... since - // `new Number(4) !== 4`, we use `==` below - return content == selection; // jshint ignore:line - } - }).property('content', 'parentView.selection'), - - labelPathDidChange: observer('parentView.optionLabelPath', function() { - var labelPath = get(this, 'parentView.optionLabelPath'); - - if (!labelPath) { return; } - - defineProperty(this, 'label', computed(function() { - return get(this, labelPath); - }).property(labelPath)); - }), - - valuePathDidChange: observer('parentView.optionValuePath', function() { - var valuePath = get(this, 'parentView.optionValuePath'); - - if (!valuePath) { return; } - - defineProperty(this, 'value', computed(function() { - return get(this, valuePath); - }).property(valuePath)); - }) - }); - - var SelectOptgroup = CollectionView.extend({ - instrumentDisplay: 'Ember.SelectOptgroup', - - tagName: 'optgroup', - attributeBindings: ['label'], - - selectionBinding: 'parentView.selection', - multipleBinding: 'parentView.multiple', - optionLabelPathBinding: 'parentView.optionLabelPath', - optionValuePathBinding: 'parentView.optionValuePath', - - itemViewClassBinding: 'parentView.optionView' - }); - - /** - The `Ember.Select` view class renders a - [select](https://developer.mozilla.org/en/HTML/Element/select) HTML element, - allowing the user to choose from a list of options. - - The text and `value` property of each ` - - - ``` - - The `value` attribute of the selected `"); - return buffer; - } - - function program3(depth0,data) { - - var stack1; - stack1 = helpers.each.call(depth0, "view.groupedContent", {hash:{},hashTypes:{},hashContexts:{},inverse:self.noop,fn:self.program(4, program4, data),contexts:[depth0],types:["ID"],data:data}); - if(stack1 || stack1 === 0) { data.buffer.push(stack1); } - else { data.buffer.push(''); } - } - function program4(depth0,data) { - - - data.buffer.push(escapeExpression(helpers.view.call(depth0, "view.groupView", {hash:{ - 'content': ("content"), - 'label': ("label") - },hashTypes:{'content': "ID",'label': "ID"},hashContexts:{'content': depth0,'label': depth0},contexts:[depth0],types:["ID"],data:data}))); - } - - function program6(depth0,data) { - - var stack1; - stack1 = helpers.each.call(depth0, "view.content", {hash:{},hashTypes:{},hashContexts:{},inverse:self.noop,fn:self.program(7, program7, data),contexts:[depth0],types:["ID"],data:data}); - if(stack1 || stack1 === 0) { data.buffer.push(stack1); } - else { data.buffer.push(''); } - } - function program7(depth0,data) { - - - data.buffer.push(escapeExpression(helpers.view.call(depth0, "view.optionView", {hash:{ - 'content': ("") - },hashTypes:{'content': "ID"},hashContexts:{'content': depth0},contexts:[depth0],types:["ID"],data:data}))); - } - - stack1 = helpers['if'].call(depth0, "view.prompt", {hash:{},hashTypes:{},hashContexts:{},inverse:self.noop,fn:self.program(1, program1, data),contexts:[depth0],types:["ID"],data:data}); - if(stack1 || stack1 === 0) { data.buffer.push(stack1); } - stack1 = helpers['if'].call(depth0, "view.optionGroupPath", {hash:{},hashTypes:{},hashContexts:{},inverse:self.program(6, program6, data),fn:self.program(3, program3, data),contexts:[depth0],types:["ID"],data:data}); - if(stack1 || stack1 === 0) { data.buffer.push(stack1); } - return buffer; - - }), - attributeBindings: ['multiple', 'disabled', 'tabindex', 'name', 'required', 'autofocus', - 'form', 'size'], - - /** - The `multiple` attribute of the select element. Indicates whether multiple - options can be selected. - - @property multiple - @type Boolean - @default false - */ - multiple: false, - - /** - The `disabled` attribute of the select element. Indicates whether - the element is disabled from interactions. - - @property disabled - @type Boolean - @default false - */ - disabled: false, - - /** - The `required` attribute of the select element. Indicates whether - a selected option is required for form validation. - - @property required - @type Boolean - @default false - @since 1.5.0 - */ - required: false, - - /** - The list of options. - - If `optionLabelPath` and `optionValuePath` are not overridden, this should - be a list of strings, which will serve simultaneously as labels and values. - - Otherwise, this should be a list of objects. For instance: - - ```javascript - var App = Ember.Application.create(); - var App.MySelect = Ember.Select.extend({ - content: Ember.A([ - { id: 1, firstName: 'Yehuda' }, - { id: 2, firstName: 'Tom' } - ]), - optionLabelPath: 'content.firstName', - optionValuePath: 'content.id' - }); - ``` - - @property content - @type Array - @default null - */ - content: null, - - /** - When `multiple` is `false`, the element of `content` that is currently - selected, if any. - - When `multiple` is `true`, an array of such elements. - - @property selection - @type Object or Array - @default null - */ - selection: null, - - /** - In single selection mode (when `multiple` is `false`), value can be used to - get the current selection's value or set the selection by it's value. - - It is not currently supported in multiple selection mode. - - @property value - @type String - @default null - */ - value: computed(function(key, value) { - if (arguments.length === 2) { return value; } - var valuePath = get(this, 'optionValuePath').replace(/^content\.?/, ''); - return valuePath ? get(this, 'selection.' + valuePath) : get(this, 'selection'); - }).property('selection'), - - /** - If given, a top-most dummy option will be rendered to serve as a user - prompt. - - @property prompt - @type String - @default null - */ - prompt: null, - - /** - The path of the option labels. See [content](/api/classes/Ember.Select.html#property_content). - - @property optionLabelPath - @type String - @default 'content' - */ - optionLabelPath: 'content', - - /** - The path of the option values. See [content](/api/classes/Ember.Select.html#property_content). - - @property optionValuePath - @type String - @default 'content' - */ - optionValuePath: 'content', - - /** - The path of the option group. - When this property is used, `content` should be sorted by `optionGroupPath`. - - @property optionGroupPath - @type String - @default null - */ - optionGroupPath: null, - - /** - The view class for optgroup. - - @property groupView - @type Ember.View - @default Ember.SelectOptgroup - */ - groupView: SelectOptgroup, - - groupedContent: computed(function() { - var groupPath = get(this, 'optionGroupPath'); - var groupedContent = emberA(); - var content = get(this, 'content') || []; - - forEach(content, function(item) { - var label = get(item, groupPath); - - if (get(groupedContent, 'lastObject.label') !== label) { - groupedContent.pushObject({ - label: label, - content: emberA() - }); - } - - get(groupedContent, 'lastObject.content').push(item); - }); - - return groupedContent; - }).property('optionGroupPath', 'content.@each'), - - /** - The view class for option. - - @property optionView - @type Ember.View - @default Ember.SelectOption - */ - optionView: SelectOption, - - _change: function() { - if (get(this, 'multiple')) { - this._changeMultiple(); - } else { - this._changeSingle(); - } - }, - - selectionDidChange: observer('selection.@each', function() { - var selection = get(this, 'selection'); - if (get(this, 'multiple')) { - if (!isArray(selection)) { - set(this, 'selection', emberA([selection])); - return; - } - this._selectionDidChangeMultiple(); - } else { - this._selectionDidChangeSingle(); - } - }), - - valueDidChange: observer('value', function() { - var content = get(this, 'content'); - var value = get(this, 'value'); - var valuePath = get(this, 'optionValuePath').replace(/^content\.?/, ''); - var selectedValue = (valuePath ? get(this, 'selection.' + valuePath) : get(this, 'selection')); - var selection; - - if (value !== selectedValue) { - selection = content ? content.find(function(obj) { - return value === (valuePath ? get(obj, valuePath) : obj); - }) : null; - - this.set('selection', selection); - } - }), - - - _triggerChange: function() { - var selection = get(this, 'selection'); - var value = get(this, 'value'); - - if (!isNone(selection)) { this.selectionDidChange(); } - if (!isNone(value)) { this.valueDidChange(); } - - this._change(); - }, - - _changeSingle: function() { - var selectedIndex = this.$()[0].selectedIndex; - var content = get(this, 'content'); - var prompt = get(this, 'prompt'); - - if (!content || !get(content, 'length')) { return; } - if (prompt && selectedIndex === 0) { set(this, 'selection', null); return; } - - if (prompt) { selectedIndex -= 1; } - set(this, 'selection', content.objectAt(selectedIndex)); - }, - - - _changeMultiple: function() { - var options = this.$('option:selected'); - var prompt = get(this, 'prompt'); - var offset = prompt ? 1 : 0; - var content = get(this, 'content'); - var selection = get(this, 'selection'); - - if (!content) { return; } - if (options) { - var selectedIndexes = options.map(function() { - return this.index - offset; - }).toArray(); - var newSelection = content.objectsAt(selectedIndexes); - - if (isArray(selection)) { - replace(selection, 0, get(selection, 'length'), newSelection); - } else { - set(this, 'selection', newSelection); - } - } - }, - - _selectionDidChangeSingle: function() { - var el = this.get('element'); - if (!el) { return; } - - var content = get(this, 'content'); - var selection = get(this, 'selection'); - var selectionIndex = content ? indexOf(content, selection) : -1; - var prompt = get(this, 'prompt'); - - if (prompt) { selectionIndex += 1; } - if (el) { el.selectedIndex = selectionIndex; } - }, - - _selectionDidChangeMultiple: function() { - var content = get(this, 'content'); - var selection = get(this, 'selection'); - var selectedIndexes = content ? indexesOf(content, selection) : [-1]; - var prompt = get(this, 'prompt'); - var offset = prompt ? 1 : 0; - var options = this.$('option'); - var adjusted; - - if (options) { - options.each(function() { - adjusted = this.index > -1 ? this.index - offset : -1; - this.selected = indexOf(selectedIndexes, adjusted) > -1; - }); - } - }, - - init: function() { - this._super(); - this.on("didInsertElement", this, this._triggerChange); - this.on("change", this, this._change); - } - }); - - __exports__["default"] = Select; - __exports__.Select = Select; - __exports__.SelectOption = SelectOption; - __exports__.SelectOptgroup = SelectOptgroup; - }); -enifed("ember-handlebars/controls/text_area", - ["ember-metal/property_get","ember-views/views/component","ember-handlebars/controls/text_support","ember-metal/mixin","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __exports__) { - "use strict"; - - /** - @module ember - @submodule ember-handlebars - */ - var get = __dependency1__.get; - var Component = __dependency2__["default"]; - var TextSupport = __dependency3__["default"]; - var observer = __dependency4__.observer; - - /** - The internal class used to create textarea element when the `{{textarea}}` - helper is used. - - See [handlebars.helpers.textarea](/api/classes/Ember.Handlebars.helpers.html#method_textarea) for usage details. - - ## Layout and LayoutName properties - - Because HTML `textarea` elements do not contain inner HTML the `layout` and - `layoutName` properties will not be applied. See [Ember.View](/api/classes/Ember.View.html)'s - layout section for more information. - - @class TextArea - @namespace Ember - @extends Ember.Component - @uses Ember.TextSupport - */ - __exports__["default"] = Component.extend(TextSupport, { - instrumentDisplay: '{{textarea}}', - - classNames: ['ember-text-area'], - - tagName: "textarea", - attributeBindings: ['rows', 'cols', 'name', 'selectionEnd', 'selectionStart', 'wrap', 'lang', 'dir'], - rows: null, - cols: null, - - _updateElementValue: observer('value', function() { - // We do this check so cursor position doesn't get affected in IE - var value = get(this, 'value'); - var $el = this.$(); - if ($el && value !== $el.val()) { - $el.val(value); - } - }), - - init: function() { - this._super(); - this.on("didInsertElement", this, this._updateElementValue); - } - }); - }); -enifed("ember-handlebars/controls/text_field", - ["ember-metal/property_get","ember-metal/property_set","ember-views/views/component","ember-handlebars/controls/text_support","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __exports__) { - "use strict"; - /** - @module ember - @submodule ember-handlebars - */ - - var get = __dependency1__.get; - var set = __dependency2__.set; - var Component = __dependency3__["default"]; - var TextSupport = __dependency4__["default"]; - - /** - - The internal class used to create text inputs when the `{{input}}` - helper is used with `type` of `text`. - - See [Handlebars.helpers.input](/api/classes/Ember.Handlebars.helpers.html#method_input) for usage details. - - ## Layout and LayoutName properties - - Because HTML `input` elements are self closing `layout` and `layoutName` - properties will not be applied. See [Ember.View](/api/classes/Ember.View.html)'s - layout section for more information. - - @class TextField - @namespace Ember - @extends Ember.Component - @uses Ember.TextSupport - */ - __exports__["default"] = Component.extend(TextSupport, { - instrumentDisplay: '{{input type="text"}}', - - classNames: ['ember-text-field'], - tagName: "input", - attributeBindings: ['type', 'value', 'size', 'pattern', 'name', 'min', 'max', - 'accept', 'autocomplete', 'autosave', 'formaction', - 'formenctype', 'formmethod', 'formnovalidate', 'formtarget', - 'height', 'inputmode', 'list', 'multiple', 'step', 'lang', 'dir', - 'width'], - - /** - The `value` attribute of the input element. As the user inputs text, this - property is updated live. - - @property value - @type String - @default "" - */ - value: "", - - /** - The `type` attribute of the input element. - - @property type - @type String - @default "text" - */ - type: "text", - - /** - The `size` of the text field in characters. - - @property size - @type String - @default null - */ - size: null, - - /** - The `pattern` attribute of input element. - - @property pattern - @type String - @default null - */ - pattern: null, - - /** - The `min` attribute of input element used with `type="number"` or `type="range"`. - - @property min - @type String - @default null - @since 1.4.0 - */ - min: null, - - /** - The `max` attribute of input element used with `type="number"` or `type="range"`. - - @property max - @type String - @default null - @since 1.4.0 - */ - max: null - }); - }); -enifed("ember-handlebars/controls/text_support", - ["ember-metal/property_get","ember-metal/property_set","ember-metal/mixin","ember-runtime/mixins/target_action_support","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __exports__) { - "use strict"; - /** - @module ember - @submodule ember-handlebars - */ - - var get = __dependency1__.get; - var set = __dependency2__.set; - var Mixin = __dependency3__.Mixin; - var TargetActionSupport = __dependency4__["default"]; - - /** - Shared mixin used by `Ember.TextField` and `Ember.TextArea`. - - @class TextSupport - @namespace Ember - @uses Ember.TargetActionSupport - @extends Ember.Mixin - @private - */ - var TextSupport = Mixin.create(TargetActionSupport, { - value: "", - - attributeBindings: ['placeholder', 'disabled', 'maxlength', 'tabindex', 'readonly', - 'autofocus', 'form', 'selectionDirection', 'spellcheck', 'required', - 'title', 'autocapitalize', 'autocorrect'], - placeholder: null, - disabled: false, - maxlength: null, - - init: function() { - this._super(); - this.on("focusOut", this, this._elementValueDidChange); - this.on("change", this, this._elementValueDidChange); - this.on("paste", this, this._elementValueDidChange); - this.on("cut", this, this._elementValueDidChange); - this.on("input", this, this._elementValueDidChange); - this.on("keyUp", this, this.interpretKeyEvents); - }, - - /** - The action to be sent when the user presses the return key. - - This is similar to the `{{action}}` helper, but is fired when - the user presses the return key when editing a text field, and sends - the value of the field as the context. - - @property action - @type String - @default null - */ - action: null, - - /** - The event that should send the action. - - Options are: - - * `enter`: the user pressed enter - * `keyPress`: the user pressed a key - - @property onEvent - @type String - @default enter - */ - onEvent: 'enter', - - /** - Whether the `keyUp` event that triggers an `action` to be sent continues - propagating to other views. - - By default, when the user presses the return key on their keyboard and - the text field has an `action` set, the action will be sent to the view's - controller and the key event will stop propagating. - - If you would like parent views to receive the `keyUp` event even after an - action has been dispatched, set `bubbles` to true. - - @property bubbles - @type Boolean - @default false - */ - bubbles: false, - - interpretKeyEvents: function(event) { - var map = TextSupport.KEY_EVENTS; - var method = map[event.keyCode]; - - this._elementValueDidChange(); - if (method) { return this[method](event); } - }, - - _elementValueDidChange: function() { - set(this, 'value', this.$().val()); - }, - - /** - Called when the user inserts a new line. - - Called by the `Ember.TextSupport` mixin on keyUp if keycode matches 13. - Uses sendAction to send the `enter` action. - - @method insertNewline - @param {Event} event - */ - insertNewline: function(event) { - sendAction('enter', this, event); - sendAction('insert-newline', this, event); - }, - - /** - Called when the user hits escape. - - Called by the `Ember.TextSupport` mixin on keyUp if keycode matches 27. - Uses sendAction to send the `escape-press` action. - - @method cancel - @param {Event} event - */ - cancel: function(event) { - sendAction('escape-press', this, event); - }, - - /** - Called when the text area is focused. - - Uses sendAction to send the `focus-in` action. - - @method focusIn - @param {Event} event - */ - focusIn: function(event) { - sendAction('focus-in', this, event); - }, - - /** - Called when the text area is blurred. - - Uses sendAction to send the `focus-out` action. - - @method focusOut - @param {Event} event - */ - focusOut: function(event) { - sendAction('focus-out', this, event); - }, - - /** - Called when the user presses a key. Enabled by setting - the `onEvent` property to `keyPress`. - - Uses sendAction to send the `key-press` action. - - @method keyPress - @param {Event} event - */ - keyPress: function(event) { - sendAction('key-press', this, event); - } - - }); - - TextSupport.KEY_EVENTS = { - 13: 'insertNewline', - 27: 'cancel' - }; - - // In principle, this shouldn't be necessary, but the legacy - // sendAction semantics for TextField are different from - // the component semantics so this method normalizes them. - function sendAction(eventName, view, event) { - var action = get(view, eventName); - var on = get(view, 'onEvent'); - var value = get(view, 'value'); - - // back-compat support for keyPress as an event name even though - // it's also a method name that consumes the event (and therefore - // incompatible with sendAction semantics). - if (on === eventName || (on === 'keyPress' && eventName === 'key-press')) { - view.sendAction('action', value); - } - - view.sendAction(eventName, value); - - if (action || on === eventName) { - if(!get(view, 'bubbles')) { - event.stopPropagation(); - } - } - } - - __exports__["default"] = TextSupport; - }); -enifed("ember-handlebars/ext", - ["ember-metal/core","ember-runtime/system/string","ember-handlebars-compiler","ember-metal/property_get","ember-metal/error","ember-metal/mixin","ember-views/views/view","ember-handlebars/views/metamorph_view","ember-metal/path_cache","ember-metal/is_empty","ember-metal/cache","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __dependency11__, __exports__) { - "use strict"; - var Ember = __dependency1__["default"]; - // Ember.FEATURES, Ember.assert, Ember.Handlebars, Ember.lookup - // var emberAssert = Ember.assert; - - var fmt = __dependency2__.fmt; - - var EmberHandlebars = __dependency3__["default"]; - var helpers = EmberHandlebars.helpers; - - var get = __dependency4__.get; - var EmberError = __dependency5__["default"]; - var IS_BINDING = __dependency6__.IS_BINDING; - - var View = __dependency7__["default"]; - var _Metamorph = __dependency8__._Metamorph; - var detectIsGlobal = __dependency9__.isGlobal; - - // late bound via requireModule because of circular dependencies. - var resolveHelper, SimpleHandlebarsView; - - var isEmpty = __dependency10__["default"]; - - var slice = [].slice; - var originalTemplate = EmberHandlebars.template; - - /** - If a path starts with a reserved keyword, returns the root - that should be used. - - @private - @method normalizePath - @for Ember - @param root {Object} - @param path {String} - @param data {Hash} - */ - - var Cache = __dependency11__["default"]; - - var FIRST_SEGMENT_CACHE = new Cache(1000, function(path){ - return path.split('.', 1)[0]; - }); - - function normalizePath(root, path, data) { - var keywords = (data && data.keywords) || {}; - var keyword, isKeyword; - - // Get the first segment of the path. For example, if the - // path is "foo.bar.baz", returns "foo". - keyword = FIRST_SEGMENT_CACHE.get(path); - - // Test to see if the first path is a keyword that has been - // passed along in the view's data hash. If so, we will treat - // that object as the new root. - if (keywords.hasOwnProperty(keyword)) { - // Look up the value in the template's data hash. - root = keywords[keyword]; - isKeyword = true; - - // Handle cases where the entire path is the reserved - // word. In that case, return the object itself. - if (path === keyword) { - path = ''; - } else { - // Strip the keyword from the path and look up - // the remainder from the newly found root. - path = path.substr(keyword.length+1); - } - } - - return { - root: root, - path: path, - isKeyword: isKeyword - }; - } - - - /** - Lookup both on root and on window. If the path starts with - a keyword, the corresponding object will be looked up in the - template's data hash and used to resolve the path. - - @method get - @for Ember.Handlebars - @param {Object} root The object to look up the property on - @param {String} path The path to be lookedup - @param {Object} options The template's option hash - */ - function handlebarsGet(root, path, options) { - var data = options && options.data; - var normalizedPath = normalizePath(root, path, data); - var value; - - // In cases where the path begins with a keyword, change the - // root to the value represented by that keyword, and ensure - // the path is relative to it. - root = normalizedPath.root; - path = normalizedPath.path; - - // Ember.get with a null root and GlobalPath will fall back to - // Ember.lookup, which is no longer allowed in templates. - // - // But when outputting a primitive, root will be the primitive - // and path a blank string. These primitives should pass through - // to `get`. - if (root || path === '') { - value = get(root, path); - } - - if (detectIsGlobal(path)) { - if (value === undefined && root !== Ember.lookup) { - root = Ember.lookup; - value = get(root, path); - } - if (root === Ember.lookup || root === null) { - Ember.deprecate("Global lookup of "+path+" from a Handlebars template is deprecated."); - } - } - - return value; - } - - function lookupViewInContainer(container, path) { - Ember.assert("View requires a container to resolve views not passed in through the context", !!container); - return container.lookupFactory('view:'+path); - } - - function lookupViewByClassName(path) { - var viewClass; - if (detectIsGlobal(path)) { - viewClass = get(path); - Ember.deprecate('Resolved the view "'+path+'" on the global context. Pass a view name to be looked up on the container instead, such as {{view "select"}}. http://emberjs.com/guides/deprecations#toc_global-lookup-of-views-since-1-8', !viewClass); - return viewClass; - } - } - - /** - handlebarsGetView resolves a view based on strings passed into a template. - For example: - - ```handlebars - {{view "some-view"}} - {{view view.someView}} - {{view App.SomeView}} {{! deprecated }} - ``` - - A value is first checked to be a string- non-strings are presumed to be - an object and returned. This handles the "access a view on a context" - case (line 2 in the above examples). - - Next a string is normalized, then called on the context with `get`. If - there is still no value, a GlobalPath will be fetched from the global - context (raising a deprecation) and a localPath will be passed to the - container to be looked up. - - @private - @for Ember.Handlebars - @param {Object} context The context of the template being rendered - @param {String} path The path to be lookedup - @param {Object} container The container - @param {Object} options The options from the template - */ - function handlebarsGetView(context, path, container, options) { - var viewClass; - var data; - var pathType; - if (options) { - data = options.data; - pathType = options.types && options.types[0]; - } - - if ('string' === typeof path) { - if('STRING' === pathType && container) { - viewClass = lookupViewInContainer(container, path); - Ember.deprecate('Quoted view names must refer to a view in the container.', viewClass); - - } - - if(!viewClass) { - viewClass = lookupViewByClassName(path); - } - - if(!viewClass) { - if (data) { - var normalizedPath = normalizePath(context, path, data); - context = normalizedPath.root; - path = normalizedPath.path; - } - - // Only lookup view class on context if there is a context. If not, - // the global lookup path on get may kick in. - viewClass = context && get(context, path); - - if(!viewClass) { - // try the container once more with the normalized path - viewClass = lookupViewInContainer(container, path); - } - } - } else { - viewClass = path; - } - - // Sometimes a view's value is yet another path - if ('string' === typeof viewClass && data && data.view) { - viewClass = handlebarsGetView(data.view, viewClass, container, { - data: data, - types: ['ID'] - }); - } - - Ember.assert( - fmt(path+" must be a subclass or an instance of Ember.View, not %@", [viewClass]), - View.detect(viewClass) || View.detectInstance(viewClass) - ); - - return viewClass; - } - - /** - This method uses `Ember.Handlebars.get` to lookup a value, then ensures - that the value is escaped properly. - - If `unescaped` is a truthy value then the escaping will not be performed. - - @method getEscaped - @for Ember.Handlebars - @param {Object} root The object to look up the property on - @param {String} path The path to be lookedup - @param {Object} options The template's option hash - @since 1.4.0 - */ - function getEscaped(root, path, options) { - var result = handlebarsGet(root, path, options); - - if (result === null || result === undefined) { - result = ""; - } else if (!(result instanceof Handlebars.SafeString)) { - result = String(result); - } - if (!options.hash.unescaped){ - result = Handlebars.Utils.escapeExpression(result); - } - - return result; - } - - __exports__.getEscaped = getEscaped;function resolveParams(context, params, options) { - var resolvedParams = [], types = options.types, param, type; - - for (var i=0, l=params.length; i{{user.name}} - -
-
{{user.role.label}}
- {{user.role.id}} - -

{{user.role.description}}

-
- ``` - - `{{with}}` can be our best friend in these cases, - instead of writing `user.role.*` over and over, we use `{{#with user.role}}`. - Now the context within the `{{#with}} .. {{/with}}` block is `user.role` so you can do the following: - - ```handlebars -
{{user.name}}
- -
- {{#with user.role}} -
{{label}}
- {{id}} - -

{{description}}

- {{/with}} -
- ``` - - ### `as` operator - - This operator aliases the scope to a new name. It's helpful for semantic clarity and to retain - default scope or to reference from another `{{with}}` block. - - ```handlebars - // posts might not be - {{#with user.posts as blogPosts}} -
- There are {{blogPosts.length}} blog posts written by {{user.name}}. -
- - {{#each post in blogPosts}} -
  • {{post.title}}
  • - {{/each}} - {{/with}} - ``` - - Without the `as` operator, it would be impossible to reference `user.name` in the example above. - - NOTE: The alias should not reuse a name from the bound property path. - For example: `{{#with foo.bar as foo}}` is not supported because it attempts to alias using - the first part of the property path, `foo`. Instead, use `{{#with foo.bar as baz}}`. - - ### `controller` option - - Adding `controller='something'` instructs the `{{with}}` helper to create and use an instance of - the specified controller with the new context as its content. - - This is very similar to using an `itemController` option with the `{{each}}` helper. - - ```handlebars - {{#with users.posts controller='userBlogPosts'}} - {{!- The current context is wrapped in our controller instance }} - {{/with}} - ``` - - In the above example, the template provided to the `{{with}}` block is now wrapped in the - `userBlogPost` controller, which provides a very elegant way to decorate the context with custom - functions/properties. - - @method with - @for Ember.Handlebars.helpers - @param {Function} context - @param {Hash} options - @return {String} HTML string - */ - function withHelper(context, options) { - var bindContext, preserveContext, controller; - var helperName = 'with'; - - if (arguments.length === 4) { - var keywordName, path, rootPath, normalized, contextPath; - - Ember.assert("If you pass more than one argument to the with helper, it must be in the form #with foo as bar", arguments[1] === "as"); - options = arguments[3]; - keywordName = arguments[2]; - path = arguments[0]; - - if (path) { - helperName += ' ' + path + ' as ' + keywordName; - } - - Ember.assert("You must pass a block to the with helper", options.fn && options.fn !== Handlebars.VM.noop); - - var localizedOptions = o_create(options); - localizedOptions.data = o_create(options.data); - localizedOptions.data.keywords = o_create(options.data.keywords || {}); - - if (isGlobalPath(path)) { - contextPath = path; - } else { - normalized = normalizePath(this, path, options.data); - path = normalized.path; - rootPath = normalized.root; - - // This is a workaround for the fact that you cannot bind separate objects - // together. When we implement that functionality, we should use it here. - var contextKey = jQuery.expando + guidFor(rootPath); - localizedOptions.data.keywords[contextKey] = rootPath; - // if the path is '' ("this"), just bind directly to the current context - contextPath = path ? contextKey + '.' + path : contextKey; - } - - localizedOptions.hash.keywordName = keywordName; - localizedOptions.hash.keywordPath = contextPath; - - bindContext = this; - context = contextPath; - options = localizedOptions; - preserveContext = true; - } else { - Ember.assert("You must pass exactly one argument to the with helper", arguments.length === 2); - Ember.assert("You must pass a block to the with helper", options.fn && options.fn !== Handlebars.VM.noop); - - helperName += ' ' + context; - bindContext = options.contexts[0]; - preserveContext = false; - } - - options.helperName = helperName; - options.isWithHelper = true; - - return bind.call(bindContext, context, options, preserveContext, exists); - } - /** - See [boundIf](/api/classes/Ember.Handlebars.helpers.html#method_boundIf) - and [unboundIf](/api/classes/Ember.Handlebars.helpers.html#method_unboundIf) - - @method if - @for Ember.Handlebars.helpers - @param {Function} context - @param {Hash} options - @return {String} HTML string - */ - function ifHelper(context, options) { - Ember.assert("You must pass exactly one argument to the if helper", arguments.length === 2); - Ember.assert("You must pass a block to the if helper", options.fn && options.fn !== Handlebars.VM.noop); - - options.helperName = options.helperName || ('if ' + context); - - if (options.data.isUnbound) { - return helpers.unboundIf.call(options.contexts[0], context, options); - } else { - return helpers.boundIf.call(options.contexts[0], context, options); - } - } - - /** - @method unless - @for Ember.Handlebars.helpers - @param {Function} context - @param {Hash} options - @return {String} HTML string - */ - function unlessHelper(context, options) { - Ember.assert("You must pass exactly one argument to the unless helper", arguments.length === 2); - Ember.assert("You must pass a block to the unless helper", options.fn && options.fn !== Handlebars.VM.noop); - - var fn = options.fn; - var inverse = options.inverse; - var helperName = 'unless'; - - if (context) { - helperName += ' ' + context; - } - - options.fn = inverse; - options.inverse = fn; - - options.helperName = options.helperName || helperName; - - if (options.data.isUnbound) { - return helpers.unboundIf.call(options.contexts[0], context, options); - } else { - return helpers.boundIf.call(options.contexts[0], context, options); - } - } - - /** - `bind-attr` allows you to create a binding between DOM element attributes and - Ember objects. For example: - - ```handlebars - imageTitle - ``` - - The above handlebars template will fill the ``'s `src` attribute with - the value of the property referenced with `"imageUrl"` and its `alt` - attribute with the value of the property referenced with `"imageTitle"`. - - If the rendering context of this template is the following object: - - ```javascript - { - imageUrl: 'http://lolcats.info/haz-a-funny', - imageTitle: 'A humorous image of a cat' - } - ``` - - The resulting HTML output will be: - - ```html - A humorous image of a cat - ``` - - `bind-attr` cannot redeclare existing DOM element attributes. The use of `src` - in the following `bind-attr` example will be ignored and the hard coded value - of `src="/failwhale.gif"` will take precedence: - - ```handlebars - imageTitle - ``` - - ### `bind-attr` and the `class` attribute - - `bind-attr` supports a special syntax for handling a number of cases unique - to the `class` DOM element attribute. The `class` attribute combines - multiple discrete values into a single attribute as a space-delimited - list of strings. Each string can be: - - * a string return value of an object's property. - * a boolean return value of an object's property - * a hard-coded value - - A string return value works identically to other uses of `bind-attr`. The - return value of the property will become the value of the attribute. For - example, the following view and template: - - ```javascript - AView = View.extend({ - someProperty: function() { - return "aValue"; - }.property() - }) - ``` - - ```handlebars - - ``` - - A boolean return value will insert a specified class name if the property - returns `true` and remove the class name if the property returns `false`. - - A class name is provided via the syntax - `somePropertyName:class-name-if-true`. - - ```javascript - AView = View.extend({ - someBool: true - }) - ``` - - ```handlebars - - ``` - - Result in the following rendered output: - - ```html - - ``` - - An additional section of the binding can be provided if you want to - replace the existing class instead of removing it when the boolean - value changes: - - ```handlebars - - ``` - - A hard-coded value can be used by prepending `:` to the desired - class name: `:class-name-to-always-apply`. - - ```handlebars - - ``` - - Results in the following rendered output: - - ```html - - ``` - - All three strategies - string return value, boolean return value, and - hard-coded value – can be combined in a single declaration: - - ```handlebars - - ``` - - @method bind-attr - @for Ember.Handlebars.helpers - @param {Hash} options - @return {String} HTML string - */ - function bindAttrHelper(options) { - var attrs = options.hash; - - Ember.assert("You must specify at least one hash argument to bind-attr", !!keys(attrs).length); - - var view = options.data.view; - var ret = []; - - // we relied on the behavior of calling without - // context to mean this === window, but when running - // "use strict", it's possible for this to === undefined; - var ctx = this || window; - - // Generate a unique id for this element. This will be added as a - // data attribute to the element so it can be looked up when - // the bound property changes. - var dataId = uuid(); - - // Handle classes differently, as we can bind multiple classes - var classBindings = attrs['class']; - if (classBindings != null) { - var classResults = bindClasses(ctx, classBindings, view, dataId, options); - - ret.push('class="' + Handlebars.Utils.escapeExpression(classResults.join(' ')) + '"'); - delete attrs['class']; - } - - var attrKeys = keys(attrs); - - // For each attribute passed, create an observer and emit the - // current value of the property as an attribute. - forEach.call(attrKeys, function(attr) { - var path = attrs[attr]; - var normalized; - - Ember.assert(fmt("You must provide an expression as the value of bound attribute. You specified: %@=%@", [attr, path]), typeof path === 'string'); - - normalized = normalizePath(ctx, path, options.data); - - var value = (path === 'this') ? normalized.root : handlebarsGet(ctx, path, options); - var type = typeOf(value); - - Ember.assert(fmt("Attributes must be numbers, strings or booleans, not %@", [value]), value === null || value === undefined || type === 'number' || type === 'string' || type === 'boolean'); - - var observer; - - observer = function observer() { - var result = handlebarsGet(ctx, path, options); - - Ember.assert(fmt("Attributes must be numbers, strings or booleans, not %@", [result]), - result === null || result === undefined || typeof result === 'number' || - typeof result === 'string' || typeof result === 'boolean'); - - var elem = view.$("[data-bindattr-" + dataId + "='" + dataId + "']"); - - // If we aren't able to find the element, it means the element - // to which we were bound has been removed from the view. - // In that case, we can assume the template has been re-rendered - // and we need to clean up the observer. - if (!elem || elem.length === 0) { - removeObserver(normalized.root, normalized.path, observer); - return; - } - - View.applyAttributeBindings(elem, attr, result); - }; - - // Add an observer to the view for when the property changes. - // When the observer fires, find the element using the - // unique data id and update the attribute to the new value. - // Note: don't add observer when path is 'this' or path - // is whole keyword e.g. {{#each x in list}} ... {{bind-attr attr="x"}} - if (path !== 'this' && !(normalized.isKeyword && normalized.path === '' )) { - view.registerObserver(normalized.root, normalized.path, observer); - } - - // if this changes, also change the logic in ember-views/lib/views/view.js - if ((type === 'string' || (type === 'number' && !isNaN(value)))) { - ret.push(attr + '="' + Handlebars.Utils.escapeExpression(value) + '"'); - } else if (value && type === 'boolean') { - // The developer controls the attr name, so it should always be safe - ret.push(attr + '="' + attr + '"'); - } - }, this); - - // Add the unique identifier - // NOTE: We use all lower-case since Firefox has problems with mixed case in SVG - ret.push('data-bindattr-' + dataId + '="' + dataId + '"'); - return new SafeString(ret.join(' ')); - } - - /** - See `bind-attr` - - @method bindAttr - @for Ember.Handlebars.helpers - @deprecated - @param {Function} context - @param {Hash} options - @return {String} HTML string - */ - function bindAttrHelperDeprecated() { - Ember.warn("The 'bindAttr' view helper is deprecated in favor of 'bind-attr'"); - return helpers['bind-attr'].apply(this, arguments); - } - - /** - Helper that, given a space-separated string of property paths and a context, - returns an array of class names. Calling this method also has the side - effect of setting up observers at those property paths, such that if they - change, the correct class name will be reapplied to the DOM element. - - For example, if you pass the string "fooBar", it will first look up the - "fooBar" value of the context. If that value is true, it will add the - "foo-bar" class to the current element (i.e., the dasherized form of - "fooBar"). If the value is a string, it will add that string as the class. - Otherwise, it will not add any new class name. - - @private - @method bindClasses - @for Ember.Handlebars - @param {Ember.Object} context The context from which to lookup properties - @param {String} classBindings A string, space-separated, of class bindings - to use - @param {View} view The view in which observers should look for the - element to update - @param {Srting} bindAttrId Optional bindAttr id used to lookup elements - @return {Array} An array of class names to add - */ - function bindClasses(context, classBindings, view, bindAttrId, options) { - var ret = []; - var newClass, value, elem; - - // Helper method to retrieve the property from the context and - // determine which class string to return, based on whether it is - // a Boolean or not. - var classStringForPath = function(root, parsedPath, options) { - var val; - var path = parsedPath.path; - - if (path === 'this') { - val = root; - } else if (path === '') { - val = true; - } else { - val = handlebarsGet(root, path, options); - } - - return View._classStringForValue(path, val, parsedPath.className, parsedPath.falsyClassName); - }; - - // For each property passed, loop through and setup - // an observer. - forEach.call(classBindings.split(' '), function(binding) { - - // Variable in which the old class value is saved. The observer function - // closes over this variable, so it knows which string to remove when - // the property changes. - var oldClass; - var observer; - var parsedPath = View._parsePropertyPath(binding); - var path = parsedPath.path; - var pathRoot = context; - var normalized; - - if (path !== '' && path !== 'this') { - normalized = normalizePath(context, path, options.data); - - pathRoot = normalized.root; - path = normalized.path; - } - - // Set up an observer on the context. If the property changes, toggle the - // class name. - observer = function() { - // Get the current value of the property - newClass = classStringForPath(context, parsedPath, options); - elem = bindAttrId ? view.$("[data-bindattr-" + bindAttrId + "='" + bindAttrId + "']") : view.$(); - - // If we can't find the element anymore, a parent template has been - // re-rendered and we've been nuked. Remove the observer. - if (!elem || elem.length === 0) { - removeObserver(pathRoot, path, observer); - } else { - // If we had previously added a class to the element, remove it. - if (oldClass) { - elem.removeClass(oldClass); - } - - // If necessary, add a new class. Make sure we keep track of it so - // it can be removed in the future. - if (newClass) { - elem.addClass(newClass); - oldClass = newClass; - } else { - oldClass = null; - } - } - }; - - if (path !== '' && path !== 'this') { - view.registerObserver(pathRoot, path, observer); - } - - // We've already setup the observer; now we just need to figure out the - // correct behavior right now on the first pass through. - value = classStringForPath(context, parsedPath, options); - - if (value) { - ret.push(value); - - // Make sure we save the current value so that it can be removed if the - // observer fires. - oldClass = value; - } - }); - - return ret; - } - - __exports__.bind = bind; - __exports__._triageMustacheHelper = _triageMustacheHelper; - __exports__.resolveHelper = resolveHelper; - __exports__.bindHelper = bindHelper; - __exports__.boundIfHelper = boundIfHelper; - __exports__.unboundIfHelper = unboundIfHelper; - __exports__.withHelper = withHelper; - __exports__.ifHelper = ifHelper; - __exports__.unlessHelper = unlessHelper; - __exports__.bindAttrHelper = bindAttrHelper; - __exports__.bindAttrHelperDeprecated = bindAttrHelperDeprecated; - __exports__.bindClasses = bindClasses; - }); -enifed("ember-handlebars/helpers/collection", - ["ember-metal/core","ember-metal/utils","ember-handlebars-compiler","ember-runtime/system/string","ember-metal/property_get","ember-handlebars/ext","ember-handlebars/helpers/view","ember-metal/computed","ember-views/views/collection_view","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __exports__) { - "use strict"; - /** - @module ember - @submodule ember-handlebars - */ - - var Ember = __dependency1__["default"]; - // Ember.assert, Ember.deprecate - var inspect = __dependency2__.inspect; - - // var emberAssert = Ember.assert; - // emberDeprecate = Ember.deprecate; - - var EmberHandlebars = __dependency3__["default"]; - var helpers = EmberHandlebars.helpers; - - var fmt = __dependency4__.fmt; - var get = __dependency5__.get; - var handlebarsGet = __dependency6__.handlebarsGet; - var handlebarsGetView = __dependency6__.handlebarsGetView; - var ViewHelper = __dependency7__.ViewHelper; - var computed = __dependency8__.computed; - var CollectionView = __dependency9__["default"]; - - var alias = computed.alias; - /** - `{{collection}}` is a `Ember.Handlebars` helper for adding instances of - `Ember.CollectionView` to a template. See [Ember.CollectionView](/api/classes/Ember.CollectionView.html) - for additional information on how a `CollectionView` functions. - - `{{collection}}`'s primary use is as a block helper with a `contentBinding` - option pointing towards an `Ember.Array`-compatible object. An `Ember.View` - instance will be created for each item in its `content` property. Each view - will have its own `content` property set to the appropriate item in the - collection. - - The provided block will be applied as the template for each item's view. - - Given an empty `` the following template: - - ```handlebars - {{! application.hbs }} - {{#collection content=model}} - Hi {{view.content.name}} - {{/collection}} - ``` - - And the following application code - - ```javascript - App = Ember.Application.create(); - App.ApplicationRoute = Ember.Route.extend({ - model: function(){ - return [{name: 'Yehuda'},{name: 'Tom'},{name: 'Peter'}]; - } - }); - ``` - - The following HTML will result: - - ```html -
    -
    Hi Yehuda
    -
    Hi Tom
    -
    Hi Peter
    -
    - ``` - - ### Non-block version of collection - - If you provide an `itemViewClass` option that has its own `template` you may - omit the block. - - The following template: - - ```handlebars - {{! application.hbs }} - {{collection content=model itemViewClass="an-item"}} - ``` - - And application code - - ```javascript - App = Ember.Application.create(); - App.ApplicationRoute = Ember.Route.extend({ - model: function(){ - return [{name: 'Yehuda'},{name: 'Tom'},{name: 'Peter'}]; - } - }); - - App.AnItemView = Ember.View.extend({ - template: Ember.Handlebars.compile("Greetings {{view.content.name}}") - }); - ``` - - Will result in the HTML structure below - - ```html -
    -
    Greetings Yehuda
    -
    Greetings Tom
    -
    Greetings Peter
    -
    - ``` - - ### Specifying a CollectionView subclass - - By default the `{{collection}}` helper will create an instance of - `Ember.CollectionView`. You can supply a `Ember.CollectionView` subclass to - the helper by passing it as the first argument: - - ```handlebars - {{#collection "my-custom-collection" content=model}} - Hi {{view.content.name}} - {{/collection}} - ``` - - This example would look for the class `App.MyCustomCollection`. - - ### Forwarded `item.*`-named Options - - As with the `{{view}}`, helper options passed to the `{{collection}}` will be - set on the resulting `Ember.CollectionView` as properties. Additionally, - options prefixed with `item` will be applied to the views rendered for each - item (note the camelcasing): - - ```handlebars - {{#collection content=model - itemTagName="p" - itemClassNames="greeting"}} - Howdy {{view.content.name}} - {{/collection}} - ``` - - Will result in the following HTML structure: - - ```html -
    -

    Howdy Yehuda

    -

    Howdy Tom

    -

    Howdy Peter

    -
    - ``` - - @method collection - @for Ember.Handlebars.helpers - @param {String} path - @param {Hash} options - @return {String} HTML string - @deprecated Use `{{each}}` helper instead. - */ - function collectionHelper(path, options) { - Ember.deprecate("Using the {{collection}} helper without specifying a class has been deprecated as the {{each}} helper now supports the same functionality.", path !== 'collection'); - - // If no path is provided, treat path param as options. - if (path && path.data && path.data.isRenderData) { - options = path; - path = undefined; - Ember.assert("You cannot pass more than one argument to the collection helper", arguments.length === 1); - } else { - Ember.assert("You cannot pass more than one argument to the collection helper", arguments.length === 2); - } - - var fn = options.fn, - data = options.data, - inverse = options.inverse, - view = options.data.view, - // This should be deterministic, and should probably come from a - // parent view and not the controller. - container = (view.controller && view.controller.container ? view.controller.container : view.container); - - // If passed a path string, convert that into an object. - // Otherwise, just default to the standard class. - var collectionClass; - if (path) { - collectionClass = handlebarsGetView(this, path, container, options); - Ember.assert(fmt("%@ #collection: Could not find collection class %@", [data.view, path]), !!collectionClass); - } - else { - collectionClass = CollectionView; - } - - var hash = options.hash; - var itemHash = {}; - var match; - - // Extract item view class if provided else default to the standard class - var collectionPrototype = collectionClass.proto(); - var itemViewClass; - - if (hash.itemView) { - itemViewClass = handlebarsGetView(this, hash.itemView, container, options); - } else if (hash.itemViewClass) { - itemViewClass = handlebarsGetView(collectionPrototype, hash.itemViewClass, container, options); - } else { - itemViewClass = handlebarsGetView(collectionPrototype, collectionPrototype.itemViewClass, container, options); - } - - Ember.assert(fmt("%@ #collection: Could not find itemViewClass %@", [data.view, itemViewClass]), !!itemViewClass); - - delete hash.itemViewClass; - delete hash.itemView; - - // Go through options passed to the {{collection}} helper and extract options - // that configure item views instead of the collection itself. - for (var prop in hash) { - if (hash.hasOwnProperty(prop)) { - match = prop.match(/^item(.)(.*)$/); - - if (match && prop !== 'itemController') { - // Convert itemShouldFoo -> shouldFoo - itemHash[match[1].toLowerCase() + match[2]] = hash[prop]; - // Delete from hash as this will end up getting passed to the - // {{view}} helper method. - delete hash[prop]; - } - } - } - - if (fn) { - itemHash.template = fn; - delete options.fn; - } - - var emptyViewClass; - if (inverse && inverse !== EmberHandlebars.VM.noop) { - emptyViewClass = get(collectionPrototype, 'emptyViewClass'); - emptyViewClass = emptyViewClass.extend({ - template: inverse, - tagName: itemHash.tagName - }); - } else if (hash.emptyViewClass) { - emptyViewClass = handlebarsGetView(this, hash.emptyViewClass, container, options); - } - if (emptyViewClass) { hash.emptyView = emptyViewClass; } - - if (hash.keyword) { - itemHash._context = this; - } else { - itemHash._context = alias('content'); - } - - var viewOptions = ViewHelper.propertiesFromHTMLOptions({ data: data, hash: itemHash }, this); - hash.itemViewClass = itemViewClass.extend(viewOptions); - - options.helperName = options.helperName || 'collection'; - - return helpers.view.call(this, collectionClass, options); - } - - __exports__["default"] = collectionHelper; - }); -enifed("ember-handlebars/helpers/debug", - ["ember-metal/core","ember-metal/utils","ember-metal/logger","ember-metal/property_get","ember-handlebars/ext","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __exports__) { - "use strict"; - /*jshint debug:true*/ - - /** - @module ember - @submodule ember-handlebars - */ - var Ember = __dependency1__["default"]; - // Ember.FEATURES, - var inspect = __dependency2__.inspect; - var Logger = __dependency3__["default"]; - - var get = __dependency4__.get; - var normalizePath = __dependency5__.normalizePath; - var handlebarsGet = __dependency5__.handlebarsGet; - - var a_slice = [].slice; - - /** - `log` allows you to output the value of variables in the current rendering - context. `log` also accepts primitive types such as strings or numbers. - - ```handlebars - {{log "myVariable:" myVariable }} - ``` - - @method log - @for Ember.Handlebars.helpers - @param {String} property - */ - function logHelper() { - var params = a_slice.call(arguments, 0, -1); - var options = arguments[arguments.length - 1]; - var logger = Logger.log; - var values = []; - var allowPrimitives = true; - - for (var i = 0; i < params.length; i++) { - var type = options.types[i]; - - if (type === 'ID' || !allowPrimitives) { - var context = (options.contexts && options.contexts[i]) || this; - var normalized = normalizePath(context, params[i], options.data); - - if (normalized.path === 'this') { - values.push(normalized.root); - } else { - values.push(handlebarsGet(normalized.root, normalized.path, options)); - } - } else { - values.push(params[i]); - } - } - - logger.apply(logger, values); - } - - /** - Execute the `debugger` statement in the current context. - - ```handlebars - {{debugger}} - ``` - - Before invoking the `debugger` statement, there - are a few helpful variables defined in the - body of this helper that you can inspect while - debugging that describe how and where this - helper was invoked: - - - templateContext: this is most likely a controller - from which this template looks up / displays properties - - typeOfTemplateContext: a string description of - what the templateContext is - - For example, if you're wondering why a value `{{foo}}` - isn't rendering as expected within a template, you - could place a `{{debugger}}` statement, and when - the `debugger;` breakpoint is hit, you can inspect - `templateContext`, determine if it's the object you - expect, and/or evaluate expressions in the console - to perform property lookups on the `templateContext`: - - ``` - > templateContext.get('foo') // -> "" - ``` - - @method debugger - @for Ember.Handlebars.helpers - @param {String} property - */ - function debuggerHelper(options) { - - // These are helpful values you can inspect while debugging. - var templateContext = this; - var typeOfTemplateContext = inspect(templateContext); - Ember.Logger.info('Use `this` to access the context of the calling template.'); - - debugger; - } - - __exports__.logHelper = logHelper; - __exports__.debuggerHelper = debuggerHelper; - }); -enifed("ember-handlebars/helpers/each", - ["ember-metal/core","ember-handlebars-compiler","ember-runtime/system/string","ember-metal/property_get","ember-metal/property_set","ember-views/views/collection_view","ember-metal/binding","ember-runtime/mixins/controller","ember-runtime/controllers/array_controller","ember-runtime/mixins/array","ember-runtime/copy","ember-metal/run_loop","ember-metal/events","ember-handlebars/ext","ember-metal/computed","ember-metal/observer","ember-handlebars/views/metamorph_view","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __dependency11__, __dependency12__, __dependency13__, __dependency14__, __dependency15__, __dependency16__, __dependency17__, __exports__) { - "use strict"; - - /** - @module ember - @submodule ember-handlebars - */ - var Ember = __dependency1__["default"]; - // Ember.assert;, Ember.K - var K = Ember.K; - - var EmberHandlebars = __dependency2__["default"]; - var helpers = EmberHandlebars.helpers; - - var fmt = __dependency3__.fmt; - var get = __dependency4__.get; - var set = __dependency5__.set; - var CollectionView = __dependency6__["default"]; - var Binding = __dependency7__.Binding; - var ControllerMixin = __dependency8__["default"]; - var ArrayController = __dependency9__["default"]; - var EmberArray = __dependency10__["default"]; - var copy = __dependency11__["default"]; - var run = __dependency12__["default"]; - var on = __dependency13__.on; - var handlebarsGet = __dependency14__.handlebarsGet; - var computed = __dependency15__.computed; - - var addObserver = __dependency16__.addObserver; - var removeObserver = __dependency16__.removeObserver; - var addBeforeObserver = __dependency16__.addBeforeObserver; - var removeBeforeObserver = __dependency16__.removeBeforeObserver; - - var _Metamorph = __dependency17__._Metamorph; - var _MetamorphView = __dependency17__._MetamorphView; - - var EachView = CollectionView.extend(_Metamorph, { - - init: function() { - var itemController = get(this, 'itemController'); - var binding; - - if (itemController) { - var controller = get(this, 'controller.container').lookupFactory('controller:array').create({ - _isVirtual: true, - parentController: get(this, 'controller'), - itemController: itemController, - target: get(this, 'controller'), - _eachView: this - }); - - this.disableContentObservers(function() { - set(this, 'content', controller); - binding = new Binding('content', '_eachView.dataSource').oneWay(); - binding.connect(controller); - }); - - set(this, '_arrayController', controller); - } else { - this.disableContentObservers(function() { - binding = new Binding('content', 'dataSource').oneWay(); - binding.connect(this); - }); - } - - return this._super(); - }, - - _assertArrayLike: function(content) { - Ember.assert(fmt("The value that #each loops over must be an Array. You " + - "passed %@, but it should have been an ArrayController", - [content.constructor]), - !ControllerMixin.detect(content) || - (content && content.isGenerated) || - content instanceof ArrayController); - Ember.assert(fmt("The value that #each loops over must be an Array. You passed %@", [(ControllerMixin.detect(content) && content.get('model') !== undefined) ? fmt("'%@' (wrapped in %@)", [content.get('model'), content]) : content]), EmberArray.detect(content)); - }, - - disableContentObservers: function(callback) { - removeBeforeObserver(this, 'content', null, '_contentWillChange'); - removeObserver(this, 'content', null, '_contentDidChange'); - - callback.call(this); - - addBeforeObserver(this, 'content', null, '_contentWillChange'); - addObserver(this, 'content', null, '_contentDidChange'); - }, - - itemViewClass: _MetamorphView, - emptyViewClass: _MetamorphView, - - createChildView: function(view, attrs) { - view = this._super(view, attrs); - - // At the moment, if a container view subclass wants - // to insert keywords, it is responsible for cloning - // the keywords hash. This will be fixed momentarily. - var keyword = get(this, 'keyword'); - var content = get(view, 'content'); - - if (keyword) { - var data = get(view, 'templateData'); - - data = copy(data); - data.keywords = view.cloneKeywords(); - set(view, 'templateData', data); - - // In this case, we do not bind, because the `content` of - // a #each item cannot change. - data.keywords[keyword] = content; - } - - // If {{#each}} is looping over an array of controllers, - // point each child view at their respective controller. - if (content && content.isController) { - set(view, 'controller', content); - } - - return view; - }, - - destroy: function() { - if (!this._super()) { return; } - - var arrayController = get(this, '_arrayController'); - - if (arrayController) { - arrayController.destroy(); - } - - return this; - } - }); - - var GroupedEach = EmberHandlebars.GroupedEach = function(context, path, options) { - var self = this; - var normalized = EmberHandlebars.normalizePath(context, path, options.data); - - this.context = context; - this.path = path; - this.options = options; - this.template = options.fn; - this.containingView = options.data.view; - this.normalizedRoot = normalized.root; - this.normalizedPath = normalized.path; - this.content = this.lookupContent(); - - this.addContentObservers(); - this.addArrayObservers(); - - this.containingView.on('willClearRender', function() { - self.destroy(); - }); - }; - - GroupedEach.prototype = { - contentWillChange: function() { - this.removeArrayObservers(); - }, - - contentDidChange: function() { - this.content = this.lookupContent(); - this.addArrayObservers(); - this.rerenderContainingView(); - }, - - contentArrayWillChange: K, - - contentArrayDidChange: function() { - this.rerenderContainingView(); - }, - - lookupContent: function() { - return handlebarsGet(this.normalizedRoot, this.normalizedPath, this.options); - }, - - addArrayObservers: function() { - if (!this.content) { return; } - - this.content.addArrayObserver(this, { - willChange: 'contentArrayWillChange', - didChange: 'contentArrayDidChange' - }); - }, - - removeArrayObservers: function() { - if (!this.content) { return; } - - this.content.removeArrayObserver(this, { - willChange: 'contentArrayWillChange', - didChange: 'contentArrayDidChange' - }); - }, - - addContentObservers: function() { - addBeforeObserver(this.normalizedRoot, this.normalizedPath, this, this.contentWillChange); - addObserver(this.normalizedRoot, this.normalizedPath, this, this.contentDidChange); - }, - - removeContentObservers: function() { - removeBeforeObserver(this.normalizedRoot, this.normalizedPath, this.contentWillChange); - removeObserver(this.normalizedRoot, this.normalizedPath, this.contentDidChange); - }, - - render: function() { - if (!this.content) { return; } - - var content = this.content; - var contentLength = get(content, 'length'); - var options = this.options; - var data = options.data; - var template = this.template; - - data.insideEach = true; - for (var i = 0; i < contentLength; i++) { - var context = content.objectAt(i); - options.data.keywords[options.hash.keyword] = context; - template(context, { data: data }); - } - }, - - rerenderContainingView: function() { - var self = this; - run.scheduleOnce('render', this, function() { - // It's possible it's been destroyed after we enqueued a re-render call. - if (!self.destroyed) { - self.containingView.rerender(); - } - }); - }, - - destroy: function() { - this.removeContentObservers(); - if (this.content) { - this.removeArrayObservers(); - } - this.destroyed = true; - } - }; - - /** - The `{{#each}}` helper loops over elements in a collection. It is an extension - of the base Handlebars `{{#each}}` helper. - - The default behavior of `{{#each}}` is to yield its inner block once for every - item in an array. Each yield will provide the item as the context of the block. - - ```javascript - var developers = [{name: 'Yehuda'},{name: 'Tom'}, {name: 'Paul'}]; - ``` - - ```handlebars - {{#each developers}} - {{name}} - {{! `this` is each developer }} - {{/each}} - ``` - - `{{#each}}` supports an alternative syntax with element naming. This preserves - context of the yielded block: - - ```handlebars - {{#each person in developers}} - {{person.name}} - {{! `this` is whatever it was outside the #each }} - {{/each}} - ``` - - The same rules apply to arrays of primitives, but the items may need to be - references with `{{this}}`. - - ```javascript - var developerNames = ['Yehuda', 'Tom', 'Paul'] - ``` - - ```handlebars - {{#each developerNames}} - {{this}} - {{/each}} - ``` - - ### {{else}} condition - - `{{#each}}` can have a matching `{{else}}`. The contents of this block will render - if the collection is empty. - - ``` - {{#each person in developers}} - {{person.name}} - {{else}} -

    Sorry, nobody is available for this task.

    - {{/each}} - ``` - - ### Specifying an alternative view for each item - - `itemViewClass` can control which view will be used during the render of each - item's template. - - The following template: - - ```handlebars -
      - {{#each developers itemViewClass="person"}} - {{name}} - {{/each}} -
    - ``` - - Will use the following view for each item - - ```javascript - App.PersonView = Ember.View.extend({ - tagName: 'li' - }); - ``` - - Resulting in HTML output that looks like the following: - - ```html -
      -
    • Yehuda
    • -
    • Tom
    • -
    • Paul
    • -
    - ``` - - `itemViewClass` also enables a non-block form of `{{each}}`. The view - must {{#crossLink "Ember.View/toc_templates"}}provide its own template{{/crossLink}}, - and then the block should be dropped. An example that outputs the same HTML - as the previous one: - - ```javascript - App.PersonView = Ember.View.extend({ - tagName: 'li', - template: '{{name}}' - }); - ``` - - ```handlebars -
      - {{each developers itemViewClass="person"}} -
    - ``` - - ### Specifying an alternative view for no items (else) - - The `emptyViewClass` option provides the same flexibility to the `{{else}}` - case of the each helper. - - ```javascript - App.NoPeopleView = Ember.View.extend({ - tagName: 'li', - template: 'No person is available, sorry' - }); - ``` - - ```handlebars -
      - {{#each developers emptyViewClass="no-people"}} -
    • {{name}}
    • - {{/each}} -
    - ``` - - ### Wrapping each item in a controller - - Controllers in Ember manage state and decorate data. In many cases, - providing a controller for each item in a list can be useful. - Specifically, an {{#crossLink "Ember.ObjectController"}}Ember.ObjectController{{/crossLink}} - should probably be used. Item controllers are passed the item they - will present as a `model` property, and an object controller will - proxy property lookups to `model` for us. - - This allows state and decoration to be added to the controller - while any other property lookups are delegated to the model. An example: - - ```javascript - App.RecruitController = Ember.ObjectController.extend({ - isAvailableForHire: function() { - return !this.get('isEmployed') && this.get('isSeekingWork'); - }.property('isEmployed', 'isSeekingWork') - }) - ``` - - ```handlebars - {{#each person in developers itemController="recruit"}} - {{person.name}} {{#if person.isAvailableForHire}}Hire me!{{/if}} - {{/each}} - ``` - - ### (Experimental) Grouped Each - - If a list's membership often changes, but properties of items in that - group rarely change, a significant improvement in template rendering - time can be achieved by using the experimental [group helper](https://github.com/emberjs/group-helper). - - ```handlebars - {{#group}} - {{#each people}} - {{firstName}} {{lastName}} - {{/each}} - {{/group}} - ``` - - When the membership of `people` changes, or when any property changes, the entire - `{{#group}}` block will be re-rendered. - - An `{{#each}}` inside the `{{#group}}` helper can opt-out of the special group - behavior by passing the `groupedRows` option. For example: - - ```handlebars - {{#group}} - {{#each dealers}} - {{! uses group's special behavior }} - {{firstName}} {{lastName}} - {{/each}} - - {{#each car in cars groupedRows=true}} - {{! does not use group's special behavior }} - {{car.make}} {{car.model}} {{car.color}} - {{/each}} - {{/group}} - ``` - - Any change to the `dealers` collection will cause the entire group to be re-rendered. - Changes to the `cars` collection will be re-rendered individually, as they are with - normal `{{#each}}` usage. - - `{{#group}}` is implemented with an `itemViewClass`, so specifying an `itemViewClass` - on an `{{#each}}` will also disable the special re-rendering behavior. - - @method each - @for Ember.Handlebars.helpers - @param [name] {String} name for item (used with `in`) - @param [path] {String} path - @param [options] {Object} Handlebars key/value pairs of options - @param [options.itemViewClass] {String} a path to a view class used for each item - @param [options.emptyViewClass] {String} a path to a view class used for each item - @param [options.itemController] {String} name of a controller to be created for each item - @param [options.groupedRows] {boolean} enable normal item-by-item rendering when inside a `#group` helper - */ - function eachHelper(path, options) { - var ctx; - var helperName = 'each'; - - if (arguments.length === 4) { - Ember.assert("If you pass more than one argument to the each helper, it must be in the form #each foo in bar", arguments[1] === "in"); - - var keywordName = arguments[0]; - - - options = arguments[3]; - path = arguments[2]; - - helperName += ' ' + keywordName + ' in ' + path; - - if (path === '') { path = "this"; } - - options.hash.keyword = keywordName; - - } else if (arguments.length === 1) { - options = path; - path = 'this'; - } else { - helperName += ' ' + path; - } - - options.hash.dataSourceBinding = path; - // Set up emptyView as a metamorph with no tag - //options.hash.emptyViewClass = Ember._MetamorphView; - - // can't rely on this default behavior when use strict - ctx = this || window; - - options.helperName = options.helperName || helperName; - - if (options.data.insideGroup && !options.hash.groupedRows && !options.hash.itemViewClass) { - new GroupedEach(ctx, path, options).render(); - } else { - return helpers.collection.call(ctx, EmberHandlebars.EachView, options); - } - } - - __exports__.EachView = EachView; - __exports__.GroupedEach = GroupedEach; - __exports__.eachHelper = eachHelper; - }); -enifed("ember-handlebars/helpers/loc", - ["ember-runtime/system/string","exports"], - function(__dependency1__, __exports__) { - "use strict"; - var loc = __dependency1__.loc; - - /** - @module ember - @submodule ember-handlebars - */ - - /** - Calls [Ember.String.loc](/api/classes/Ember.String.html#method_loc) with the - provided string. - - This is a convenient way to localize text within a template: - - ```javascript - Ember.STRINGS = { - '_welcome_': 'Bonjour' - }; - ``` - - ```handlebars -
    - {{loc '_welcome_'}} -
    - ``` - - ```html -
    - Bonjour -
    - ``` - - See [Ember.String.loc](/api/classes/Ember.String.html#method_loc) for how to - set up localized string references. - - @method loc - @for Ember.Handlebars.helpers - @param {String} str The string to format - @see {Ember.String#loc} - */ - __exports__["default"] = loc; - }); -enifed("ember-handlebars/helpers/partial", - ["ember-metal/core","ember-metal/is_none","ember-handlebars/ext","ember-handlebars/helpers/binding","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __exports__) { - "use strict"; - var Ember = __dependency1__["default"]; - // Ember.assert - // var emberAssert = Ember.assert; - - var isNone = __dependency2__.isNone; - var handlebarsGet = __dependency3__.handlebarsGet; - var bind = __dependency4__.bind; - - /** - @module ember - @submodule ember-handlebars - */ - - /** - The `partial` helper renders another template without - changing the template context: - - ```handlebars - {{foo}} - {{partial "nav"}} - ``` - - The above example template will render a template named - "_nav", which has the same context as the parent template - it's rendered into, so if the "_nav" template also referenced - `{{foo}}`, it would print the same thing as the `{{foo}}` - in the above example. - - If a "_nav" template isn't found, the `partial` helper will - fall back to a template named "nav". - - ## Bound template names - - The parameter supplied to `partial` can also be a path - to a property containing a template name, e.g.: - - ```handlebars - {{partial someTemplateName}} - ``` - - The above example will look up the value of `someTemplateName` - on the template context (e.g. a controller) and use that - value as the name of the template to render. If the resolved - value is falsy, nothing will be rendered. If `someTemplateName` - changes, the partial will be re-rendered using the new template - name. - - ## Setting the partial's context with `with` - - The `partial` helper can be used in conjunction with the `with` - helper to set a context that will be used by the partial: - - ```handlebars - {{#with currentUser}} - {{partial "user_info"}} - {{/with}} - ``` - - @method partial - @for Ember.Handlebars.helpers - @param {String} partialName the name of the template to render minus the leading underscore - */ - - __exports__["default"] = function partialHelper(name, options) { - - var context = (options.contexts && options.contexts.length) ? options.contexts[0] : this; - - options.helperName = options.helperName || 'partial'; - - if (options.types[0] === "ID") { - // Helper was passed a property path; we need to - // create a binding that will re-render whenever - // this property changes. - options.fn = function(context, fnOptions) { - var partialName = handlebarsGet(context, name, fnOptions); - renderPartial(context, partialName, fnOptions); - }; - - return bind.call(context, name, options, true, exists); - } else { - // Render the partial right into parent template. - renderPartial(context, name, options); - } - } - - function exists(value) { - return !isNone(value); - } - - function renderPartial(context, name, options) { - var nameParts = name.split("/"); - var lastPart = nameParts[nameParts.length - 1]; - - nameParts[nameParts.length - 1] = "_" + lastPart; - - var view = options.data.view; - var underscoredName = nameParts.join("/"); - var template = view.templateForName(underscoredName); - var deprecatedTemplate = !template && view.templateForName(name); - - Ember.assert("Unable to find partial with name '"+name+"'.", template || deprecatedTemplate); - - template = template || deprecatedTemplate; - - template(context, { data: options.data }); - } - }); -enifed("ember-handlebars/helpers/shared", - ["ember-handlebars/ext","exports"], - function(__dependency1__, __exports__) { - "use strict"; - var handlebarsGet = __dependency1__.handlebarsGet; - - __exports__["default"] = function resolvePaths(options) { - var ret = []; - var contexts = options.contexts; - var roots = options.roots; - var data = options.data; - - for (var i=0, l=contexts.length; i{{unbound somePropertyThatDoesntChange}} - ``` - - `unbound` can also be used in conjunction with a bound helper to - render it in its unbound form: - - ```handlebars -
    {{unbound helperName somePropertyThatDoesntChange}}
    - ``` - - @method unbound - @for Ember.Handlebars.helpers - @param {String} property - @return {String} HTML string - */ - __exports__["default"] = function unboundHelper(property, fn) { - var options = arguments[arguments.length - 1]; - var container = options.data.view.container; - var helper, context, out, ctx; - - ctx = this; - if (arguments.length > 2) { - // Unbound helper call. - options.data.isUnbound = true; - helper = resolveHelper(container, property) || helpers.helperMissing; - out = helper.apply(ctx, slice.call(arguments, 1)); - delete options.data.isUnbound; - return out; - } - - context = (fn.contexts && fn.contexts.length) ? fn.contexts[0] : ctx; - return handlebarsGet(context, property, fn); - } - }); -enifed("ember-handlebars/helpers/view", - ["ember-metal/core","ember-runtime/system/object","ember-metal/property_get","ember-metal/property_set","ember-metal/mixin","ember-views/system/jquery","ember-views/views/view","ember-metal/binding","ember-metal/keys","ember-handlebars/ext","ember-runtime/system/string","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __dependency11__, __exports__) { - "use strict"; - /*globals Handlebars */ - - /** - @module ember - @submodule ember-handlebars - */ - - var Ember = __dependency1__["default"]; - // Ember.warn, Ember.assert - // var emberWarn = Ember.warn, emberAssert = Ember.assert; - - var EmberObject = __dependency2__["default"]; - var get = __dependency3__.get; - var set = __dependency4__.set; - var IS_BINDING = __dependency5__.IS_BINDING; - var jQuery = __dependency6__["default"]; - var View = __dependency7__["default"]; - var isGlobalPath = __dependency8__.isGlobalPath; - var keys = __dependency9__["default"]; - var normalizePath = __dependency10__.normalizePath; - var handlebarsGet = __dependency10__.handlebarsGet; - var handlebarsGetView = __dependency10__.handlebarsGetView; - var EmberString = __dependency11__["default"]; - - - var LOWERCASE_A_Z = /^[a-z]/; - var VIEW_PREFIX = /^view\./; - - function makeBindings(thisContext, options) { - var hash = options.hash; - var hashType = options.hashTypes; - - for (var prop in hash) { - if (hashType[prop] === 'ID') { - - var value = hash[prop]; - - if (IS_BINDING.test(prop)) { - Ember.warn("You're attempting to render a view by passing " + prop + "=" + value + " to a view helper, but this syntax is ambiguous. You should either surround " + value + " in quotes or remove `Binding` from " + prop + "."); - } else { - hash[prop + 'Binding'] = value; - hashType[prop + 'Binding'] = 'STRING'; - delete hash[prop]; - delete hashType[prop]; - } - } - } - - if (hash.hasOwnProperty('idBinding')) { - // id can't be bound, so just perform one-time lookup. - hash.id = handlebarsGet(thisContext, hash.idBinding, options); - hashType.id = 'STRING'; - delete hash.idBinding; - delete hashType.idBinding; - } - } - - var ViewHelper = EmberObject.create({ - propertiesFromHTMLOptions: function(options) { - var hash = options.hash; - var data = options.data; - var classes = hash['class']; - - var extensions = { - helperName: options.helperName || '' - }; - - if (hash.id) { - extensions.elementId = hash.id; - } - - if (hash.tag) { - extensions.tagName = hash.tag; - } - - if (classes) { - classes = classes.split(' '); - extensions.classNames = classes; - } - - if (hash.classBinding) { - extensions.classNameBindings = hash.classBinding.split(' '); - } - - if (hash.classNameBindings) { - if (extensions.classNameBindings === undefined) { - extensions.classNameBindings = []; - } - extensions.classNameBindings = extensions.classNameBindings.concat(hash.classNameBindings.split(' ')); - } - - if (hash.attributeBindings) { - Ember.assert("Setting 'attributeBindings' via Handlebars is not allowed. Please subclass Ember.View and set it there instead."); - extensions.attributeBindings = null; - } - - // Set the proper context for all bindings passed to the helper. This applies to regular attribute bindings - // as well as class name bindings. If the bindings are local, make them relative to the current context - // instead of the view. - var path; - var hashKeys = keys(hash); - - for (var i = 0, l = hashKeys.length; i < l; i++) { - var prop = hashKeys[i]; - var isBinding = IS_BINDING.test(prop); - - if (prop !== 'classNameBindings') { - extensions[prop] = hash[prop]; - } - - // Test if the property ends in "Binding" - if (isBinding && typeof extensions[prop] === 'string') { - path = this.contextualizeBindingPath(hash[prop], data); - if (path) { - extensions[prop] = path; - } - } - } - - if (extensions.classNameBindings) { - // Evaluate the context of class name bindings: - for (var j = 0, k = extensions.classNameBindings.length; j < k; j++) { - var full = extensions.classNameBindings[j]; - - if (typeof full === 'string') { - // Contextualize the path of classNameBinding so this: - // - // classNameBinding="isGreen:green" - // - // is converted to this: - // - // classNameBinding="_parentView.context.isGreen:green" - var parsedPath = View._parsePropertyPath(full); - if (parsedPath.path !== '') { - path = this.contextualizeBindingPath(parsedPath.path, data); - if (path) { - extensions.classNameBindings[j] = path + parsedPath.classNames; - } - } - } - } - } - - return extensions; - }, - - // Transform bindings from the current context to a context that can be evaluated within the view. - // Returns null if the path shouldn't be changed. - // - // TODO: consider the addition of a prefix that would allow this method to return `path`. - contextualizeBindingPath: function(path, data) { - var normalized = normalizePath(null, path, data); - if (normalized.isKeyword) { - return 'templateData.keywords.' + path; - } else if (isGlobalPath(path)) { - return null; - } else if (path === 'this' || path === '') { - return '_parentView.context'; - } else { - return '_parentView.context.' + path; - } - }, - - helper: function(thisContext, path, options) { - var data = options.data; - var fn = options.fn; - var newView; - var newViewProto; - - makeBindings(thisContext, options); - - var container = this.container || (data && data.view && data.view.container); - newView = handlebarsGetView(thisContext, path, container, options); - - if (View.detectInstance(newView)) { - newViewProto = newView; - } else { - newViewProto = newView.proto(); - } - - var viewOptions = this.propertiesFromHTMLOptions(options, thisContext); - var currentView = data.view; - viewOptions.templateData = data; - - if (fn) { - Ember.assert("You cannot provide a template block if you also specified a templateName", !get(viewOptions, 'templateName') && !get(newViewProto, 'templateName')); - viewOptions.template = fn; - } - - // We only want to override the `_context` computed property if there is - // no specified controller. See View#_context for more information. - if (!newViewProto.controller && !newViewProto.controllerBinding && !viewOptions.controller && !viewOptions.controllerBinding) { - viewOptions._context = thisContext; - } - - currentView.appendChild(newView, viewOptions); - }, - - instanceHelper: function(thisContext, newView, options) { - var data = options.data; - var fn = options.fn; - - makeBindings(thisContext, options); - - Ember.assert( - 'Only a instance of a view may be passed to the ViewHelper.instanceHelper', - View.detectInstance(newView) - ); - - var viewOptions = this.propertiesFromHTMLOptions(options, thisContext); - var currentView = data.view; - viewOptions.templateData = data; - - if (fn) { - Ember.assert("You cannot provide a template block if you also specified a templateName", !get(viewOptions, 'templateName') && !get(newView, 'templateName')); - viewOptions.template = fn; - } - - // We only want to override the `_context` computed property if there is - // no specified controller. See View#_context for more information. - if (!newView.controller && !newView.controllerBinding && !viewOptions.controller && !viewOptions.controllerBinding) { - viewOptions._context = thisContext; - } - - currentView.appendChild(newView, viewOptions); - } - }); - __exports__.ViewHelper = ViewHelper; - /** - `{{view}}` inserts a new instance of an `Ember.View` into a template passing its - options to the `Ember.View`'s `create` method and using the supplied block as - the view's own template. - - An empty `` and the following template: - - ```handlebars - A span: - {{#view tagName="span"}} - hello. - {{/view}} - ``` - - Will result in HTML structure: - - ```html - - - -
    - A span: - - Hello. - -
    - - ``` - - ### `parentView` setting - - The `parentView` property of the new `Ember.View` instance created through - `{{view}}` will be set to the `Ember.View` instance of the template where - `{{view}}` was called. - - ```javascript - aView = Ember.View.create({ - template: Ember.Handlebars.compile("{{#view}} my parent: {{parentView.elementId}} {{/view}}") - }); - - aView.appendTo('body'); - ``` - - Will result in HTML structure: - - ```html -
    -
    - my parent: ember1 -
    -
    - ``` - - ### Setting CSS id and class attributes - - The HTML `id` attribute can be set on the `{{view}}`'s resulting element with - the `id` option. This option will _not_ be passed to `Ember.View.create`. - - ```handlebars - {{#view tagName="span" id="a-custom-id"}} - hello. - {{/view}} - ``` - - Results in the following HTML structure: - - ```html -
    - - hello. - -
    - ``` - - The HTML `class` attribute can be set on the `{{view}}`'s resulting element - with the `class` or `classNameBindings` options. The `class` option will - directly set the CSS `class` attribute and will not be passed to - `Ember.View.create`. `classNameBindings` will be passed to `create` and use - `Ember.View`'s class name binding functionality: - - ```handlebars - {{#view tagName="span" class="a-custom-class"}} - hello. - {{/view}} - ``` - - Results in the following HTML structure: - - ```html -
    - - hello. - -
    - ``` - - ### Supplying a different view class - - `{{view}}` can take an optional first argument before its supplied options to - specify a path to a custom view class. - - ```handlebars - {{#view "custom"}}{{! will look up App.CustomView }} - hello. - {{/view}} - ``` - - The first argument can also be a relative path accessible from the current - context. - - ```javascript - MyApp = Ember.Application.create({}); - MyApp.OuterView = Ember.View.extend({ - innerViewClass: Ember.View.extend({ - classNames: ['a-custom-view-class-as-property'] - }), - template: Ember.Handlebars.compile('{{#view view.innerViewClass}} hi {{/view}}') - }); - - MyApp.OuterView.create().appendTo('body'); - ``` - - Will result in the following HTML: - - ```html -
    -
    - hi -
    -
    - ``` - - ### Blockless use - - If you supply a custom `Ember.View` subclass that specifies its own template - or provide a `templateName` option to `{{view}}` it can be used without - supplying a block. Attempts to use both a `templateName` option and supply a - block will throw an error. - - ```javascript - var App = Ember.Application.create(); - App.WithTemplateDefinedView = Ember.View.extend({ - templateName: 'defined-template' - }); - ``` - - ```handlebars - {{! application.hbs }} - {{view 'with-template-defined'}} - ``` - - ```handlebars - {{! defined-template.hbs }} - Some content for the defined template view. - ``` - - ### `viewName` property - - You can supply a `viewName` option to `{{view}}`. The `Ember.View` instance - will be referenced as a property of its parent view by this name. - - ```javascript - aView = Ember.View.create({ - template: Ember.Handlebars.compile('{{#view viewName="aChildByName"}} hi {{/view}}') - }); - - aView.appendTo('body'); - aView.get('aChildByName') // the instance of Ember.View created by {{view}} helper - ``` - - @method view - @for Ember.Handlebars.helpers - @param {String} path - @param {Hash} options - @return {String} HTML string - */ - function viewHelper(path, options) { - Ember.assert("The view helper only takes a single argument", arguments.length <= 2); - - // If no path is provided, treat path param as options - // and get an instance of the registered `view:toplevel` - if (path && path.data && path.data.isRenderData) { - options = path; - if (options.data && options.data.view && options.data.view.container) { - path = options.data.view.container.lookupFactory('view:toplevel'); - } else { - path = View; - } - } - - options.helperName = options.helperName || 'view'; - - return ViewHelper.helper(this, path, options); - } - - __exports__.viewHelper = viewHelper; - }); -enifed("ember-handlebars/helpers/yield", - ["ember-metal/core","ember-metal/property_get","exports"], - function(__dependency1__, __dependency2__, __exports__) { - "use strict"; - /** - @module ember - @submodule ember-handlebars - */ - - var Ember = __dependency1__["default"]; - // var emberAssert = Ember.assert; - - var get = __dependency2__.get; - - /** - `{{yield}}` denotes an area of a template that will be rendered inside - of another template. It has two main uses: - - ### Use with `layout` - When used in a Handlebars template that is assigned to an `Ember.View` - instance's `layout` property Ember will render the layout template first, - inserting the view's own rendered output at the `{{yield}}` location. - - An empty `` and the following application code: - - ```javascript - AView = Ember.View.extend({ - classNames: ['a-view-with-layout'], - layout: Ember.Handlebars.compile('
    {{yield}}
    '), - template: Ember.Handlebars.compile('I am wrapped') - }); - - aView = AView.create(); - aView.appendTo('body'); - ``` - - Will result in the following HTML output: - - ```html - -
    -
    - I am wrapped -
    -
    - - ``` - - The `yield` helper cannot be used outside of a template assigned to an - `Ember.View`'s `layout` property and will throw an error if attempted. - - ```javascript - BView = Ember.View.extend({ - classNames: ['a-view-with-layout'], - template: Ember.Handlebars.compile('{{yield}}') - }); - - bView = BView.create(); - bView.appendTo('body'); - - // throws - // Uncaught Error: assertion failed: - // You called yield in a template that was not a layout - ``` - - ### Use with Ember.Component - When designing components `{{yield}}` is used to denote where, inside the component's - template, an optional block passed to the component should render: - - ```handlebars - - {{#labeled-textfield value=someProperty}} - First name: - {{/labeled-textfield}} - ``` - - ```handlebars - - - ``` - - Result: - - ```html - - ``` - - @method yield - @for Ember.Handlebars.helpers - @param {Hash} options - @return {String} HTML string - */ - __exports__["default"] = function yieldHelper(options) { - var view = options.data.view; - - while (view && !get(view, 'layout')) { - if (view._contextView) { - view = view._contextView; - } else { - view = get(view, '_parentView'); - } - } - - Ember.assert("You called yield in a template that was not a layout", !!view); - - view._yield(this, options); - } - }); -enifed("ember-handlebars/loader", - ["ember-handlebars/component_lookup","ember-views/system/jquery","ember-metal/error","ember-runtime/system/lazy_load","ember-handlebars-compiler","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __exports__) { - "use strict"; - /*globals Handlebars */ - - var ComponentLookup = __dependency1__["default"]; - var jQuery = __dependency2__["default"]; - var EmberError = __dependency3__["default"]; - var onLoad = __dependency4__.onLoad; - - var EmberHandlebars = __dependency5__["default"]; - - /** - @module ember - @submodule ember-handlebars - */ - - /** - Find templates stored in the head tag as script tags and make them available - to `Ember.CoreView` in the global `Ember.TEMPLATES` object. This will be run - as as jQuery DOM-ready callback. - - Script tags with `text/x-handlebars` will be compiled - with Ember's Handlebars and are suitable for use as a view's template. - Those with type `text/x-raw-handlebars` will be compiled with regular - Handlebars and are suitable for use in views' computed properties. - - @private - @method bootstrap - @for Ember.Handlebars - @static - @param ctx - */ - function bootstrap(ctx) { - var selectors = 'script[type="text/x-handlebars"], script[type="text/x-raw-handlebars"]'; - - jQuery(selectors, ctx) - .each(function() { - // Get a reference to the script tag - var script = jQuery(this); - - var compile = (script.attr('type') === 'text/x-raw-handlebars') ? - jQuery.proxy(Handlebars.compile, Handlebars) : - jQuery.proxy(EmberHandlebars.compile, EmberHandlebars); - // Get the name of the script, used by Ember.View's templateName property. - // First look for data-template-name attribute, then fall back to its - // id if no name is found. - var templateName = script.attr('data-template-name') || script.attr('id') || 'application'; - var template = compile(script.html()); - - // Check if template of same name already exists - if (Ember.TEMPLATES[templateName] !== undefined) { - throw new EmberError('Template named "' + templateName + '" already exists.'); - } - - // For templates which have a name, we save them and then remove them from the DOM - Ember.TEMPLATES[templateName] = template; - - // Remove script tag from DOM - script.remove(); - }); - } - - function _bootstrap() { - bootstrap( jQuery(document) ); - } - - function registerComponentLookup(container) { - container.register('component-lookup:main', ComponentLookup); - } - - /* - We tie this to application.load to ensure that we've at least - attempted to bootstrap at the point that the application is loaded. - - We also tie this to document ready since we're guaranteed that all - the inline templates are present at this point. - - There's no harm to running this twice, since we remove the templates - from the DOM after processing. - */ - - onLoad('Ember.Application', function(Application) { - Application.initializer({ - name: 'domTemplates', - initialize: _bootstrap - }); - - Application.initializer({ - name: 'registerComponentLookup', - after: 'domTemplates', - initialize: registerComponentLookup - }); - }); - - __exports__["default"] = bootstrap; - }); -enifed("ember-handlebars/string", - ["ember-runtime/system/string","exports"], - function(__dependency1__, __exports__) { - "use strict"; - // required so we can extend this object. - var EmberStringUtils = __dependency1__["default"]; - - /** - Mark a string as safe for unescaped output with Handlebars. If you - return HTML from a Handlebars helper, use this function to - ensure Handlebars does not escape the HTML. - - ```javascript - Ember.String.htmlSafe('
    someString
    ') - ``` - - @method htmlSafe - @for Ember.String - @static - @return {Handlebars.SafeString} a string that will not be html escaped by Handlebars - */ - function htmlSafe(str) { - if (typeof str !== 'string') { - str = ''+str; - } - return new Handlebars.SafeString(str); - } - - EmberStringUtils.htmlSafe = htmlSafe; - if (Ember.EXTEND_PROTOTYPES === true || Ember.EXTEND_PROTOTYPES.String) { - - /** - Mark a string as being safe for unescaped output with Handlebars. - - ```javascript - '
    someString
    '.htmlSafe() - ``` - - See [Ember.String.htmlSafe](/api/classes/Ember.String.html#method_htmlSafe). - - @method htmlSafe - @for String - @return {Handlebars.SafeString} a string that will not be html escaped by Handlebars - */ - String.prototype.htmlSafe = function() { - return htmlSafe(this); - }; - } - - __exports__["default"] = htmlSafe; - }); -enifed("ember-handlebars/views/handlebars_bound_view", - ["ember-handlebars-compiler","ember-metal/core","ember-metal/error","ember-metal/property_get","ember-metal/property_set","ember-metal/merge","ember-metal/run_loop","ember-views/views/view","ember-handlebars/string","ember-views/views/states","ember-handlebars/views/metamorph_view","ember-handlebars/ext","ember-metal/utils","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __dependency11__, __dependency12__, __dependency13__, __exports__) { - "use strict"; - /*globals Handlebars, Metamorph:true */ - /*jshint newcap:false*/ - - - /** - @module ember - @submodule ember-handlebars - */ - - var EmberHandlebars = __dependency1__["default"]; - // EmberHandlebars.SafeString; - var SafeString = EmberHandlebars.SafeString; - - var Ember = __dependency2__["default"]; - // Ember.K - var K = Ember.K; - - var EmberError = __dependency3__["default"]; - var get = __dependency4__.get; - var set = __dependency5__.set; - var merge = __dependency6__["default"]; - var run = __dependency7__["default"]; - var View = __dependency8__["default"]; - var htmlSafe = __dependency9__["default"]; - var cloneStates = __dependency10__.cloneStates; - var states = __dependency10__.states; - var viewStates = states; - - var _MetamorphView = __dependency11__["default"]; - var handlebarsGet = __dependency12__.handlebarsGet; - var uuid = __dependency13__.uuid; - - function SimpleHandlebarsView(path, pathRoot, isEscaped, templateData) { - this.path = path; - this.pathRoot = pathRoot; - this.isEscaped = isEscaped; - this.templateData = templateData; - this[Ember.GUID_KEY] = uuid(); - this._lastNormalizedValue = undefined; - this.state = 'preRender'; - this.updateId = null; - this._parentView = null; - this.buffer = null; - this._morph = null; - } - - SimpleHandlebarsView.prototype = { - isVirtual: true, - isView: true, - - destroy: function () { - if (this.updateId) { - run.cancel(this.updateId); - this.updateId = null; - } - if (this._parentView) { - this._parentView.removeChild(this); - } - this.morph = null; - this.state = 'destroyed'; - }, - - propertyWillChange: K, - - propertyDidChange: K, - - normalizedValue: function() { - var path = this.path; - var pathRoot = this.pathRoot; - var escape = this.isEscaped; - var result, templateData; - - // Use the pathRoot as the result if no path is provided. This - // happens if the path is `this`, which gets normalized into - // a `pathRoot` of the current Handlebars context and a path - // of `''`. - if (path === '') { - result = pathRoot; - } else { - templateData = this.templateData; - result = handlebarsGet(pathRoot, path, { data: templateData }); - } - - if (!escape && !(result instanceof SafeString)) { - result = htmlSafe(result); - } - - return result; - }, - - render: function(buffer) { - var value = this.normalizedValue(); - this._lastNormalizedValue = value; - buffer._element = value; - }, - - rerender: function() { - switch(this.state) { - case 'preRender': - case 'destroyed': - break; - case 'inBuffer': - throw new EmberError("Something you did tried to replace an {{expression}} before it was inserted into the DOM."); - case 'hasElement': - case 'inDOM': - this.updateId = run.scheduleOnce('render', this, 'update'); - break; - } - return this; - }, - - update: function () { - this.updateId = null; - var value = this.normalizedValue(); - // doesn't diff SafeString instances - if (value !== this._lastNormalizedValue) { - this._lastNormalizedValue = value; - this._morph.update(value); - } - }, - - _transitionTo: function(state) { - this.state = state; - } - }; - - states = cloneStates(viewStates); - - merge(states._default, { - rerenderIfNeeded: K - }); - - merge(states.inDOM, { - rerenderIfNeeded: function(view) { - if (view.normalizedValue() !== view._lastNormalizedValue) { - view.rerender(); - } - } - }); - - /** - `Ember._HandlebarsBoundView` is a private view created by the Handlebars - `{{bind}}` helpers that is used to keep track of bound properties. - - Every time a property is bound using a `{{mustache}}`, an anonymous subclass - of `Ember._HandlebarsBoundView` is created with the appropriate sub-template - and context set up. When the associated property changes, just the template - for this view will re-render. - - @class _HandlebarsBoundView - @namespace Ember - @extends Ember._MetamorphView - @private - */ - var _HandlebarsBoundView = _MetamorphView.extend({ - instrumentName: 'boundHandlebars', - - _states: states, - - /** - The function used to determine if the `displayTemplate` or - `inverseTemplate` should be rendered. This should be a function that takes - a value and returns a Boolean. - - @property shouldDisplayFunc - @type Function - @default null - */ - shouldDisplayFunc: null, - - /** - Whether the template rendered by this view gets passed the context object - of its parent template, or gets passed the value of retrieving `path` - from the `pathRoot`. - - For example, this is true when using the `{{#if}}` helper, because the - template inside the helper should look up properties relative to the same - object as outside the block. This would be `false` when used with `{{#with - foo}}` because the template should receive the object found by evaluating - `foo`. - - @property preserveContext - @type Boolean - @default false - */ - preserveContext: false, - - /** - If `preserveContext` is true, this is the object that will be used - to render the template. - - @property previousContext - @type Object - */ - previousContext: null, - - /** - The template to render when `shouldDisplayFunc` evaluates to `true`. - - @property displayTemplate - @type Function - @default null - */ - displayTemplate: null, - - /** - The template to render when `shouldDisplayFunc` evaluates to `false`. - - @property inverseTemplate - @type Function - @default null - */ - inverseTemplate: null, - - - /** - The path to look up on `pathRoot` that is passed to - `shouldDisplayFunc` to determine which template to render. - - In addition, if `preserveContext` is `false,` the object at this path will - be passed to the template when rendering. - - @property path - @type String - @default null - */ - path: null, - - /** - The object from which the `path` will be looked up. Sometimes this is the - same as the `previousContext`, but in cases where this view has been - generated for paths that start with a keyword such as `view` or - `controller`, the path root will be that resolved object. - - @property pathRoot - @type Object - */ - pathRoot: null, - - normalizedValue: function() { - var path = get(this, 'path'); - var pathRoot = get(this, 'pathRoot'); - var valueNormalizer = get(this, 'valueNormalizerFunc'); - var result, templateData; - - // Use the pathRoot as the result if no path is provided. This - // happens if the path is `this`, which gets normalized into - // a `pathRoot` of the current Handlebars context and a path - // of `''`. - if (path === '') { - result = pathRoot; - } else { - templateData = get(this, 'templateData'); - result = handlebarsGet(pathRoot, path, { data: templateData }); - } - - return valueNormalizer ? valueNormalizer(result) : result; - }, - - rerenderIfNeeded: function() { - this.currentState.rerenderIfNeeded(this); - }, - - /** - Determines which template to invoke, sets up the correct state based on - that logic, then invokes the default `Ember.View` `render` implementation. - - This method will first look up the `path` key on `pathRoot`, - then pass that value to the `shouldDisplayFunc` function. If that returns - `true,` the `displayTemplate` function will be rendered to DOM. Otherwise, - `inverseTemplate`, if specified, will be rendered. - - For example, if this `Ember._HandlebarsBoundView` represented the `{{#with - foo}}` helper, it would look up the `foo` property of its context, and - `shouldDisplayFunc` would always return true. The object found by looking - up `foo` would be passed to `displayTemplate`. - - @method render - @param {Ember.RenderBuffer} buffer - */ - render: function(buffer) { - // If not invoked via a triple-mustache ({{{foo}}}), escape - // the content of the template. - var escape = get(this, 'isEscaped'); - - var shouldDisplay = get(this, 'shouldDisplayFunc'); - var preserveContext = get(this, 'preserveContext'); - var context = get(this, 'previousContext'); - - var inverseTemplate = get(this, 'inverseTemplate'); - var displayTemplate = get(this, 'displayTemplate'); - - var result = this.normalizedValue(); - - this._lastNormalizedValue = result; - - // First, test the conditional to see if we should - // render the template or not. - if (shouldDisplay(result)) { - set(this, 'template', displayTemplate); - - // If we are preserving the context (for example, if this - // is an #if block, call the template with the same object. - if (preserveContext) { - set(this, '_context', context); - } else { - // Otherwise, determine if this is a block bind or not. - // If so, pass the specified object to the template - if (displayTemplate) { - set(this, '_context', result); - } else { - // This is not a bind block, just push the result of the - // expression to the render context and return. - if (result === null || result === undefined) { - result = ""; - } else if (!(result instanceof SafeString)) { - result = String(result); - } - - if (escape) { result = Handlebars.Utils.escapeExpression(result); } - buffer.push(result); - return; - } - } - } else if (inverseTemplate) { - set(this, 'template', inverseTemplate); - - if (preserveContext) { - set(this, '_context', context); - } else { - set(this, '_context', result); - } - } else { - set(this, 'template', function() { return ''; }); - } - - return this._super(buffer); - } - }); - - __exports__._HandlebarsBoundView = _HandlebarsBoundView; - __exports__.SimpleHandlebarsView = SimpleHandlebarsView; - }); -enifed("ember-handlebars/views/metamorph_view", - ["ember-metal/core","ember-views/views/core_view","ember-views/views/view","ember-metal/mixin","ember-metal/run_loop","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __exports__) { - "use strict"; - /* global Metamorph:true */ - - /*jshint newcap:false*/ - var Ember = __dependency1__["default"]; - // Ember.deprecate - - var CoreView = __dependency2__["default"]; - var View = __dependency3__["default"]; - var Mixin = __dependency4__.Mixin; - var run = __dependency5__["default"]; - - /** - @module ember - @submodule ember-handlebars - */ - - function notifyMutationListeners() { - run.once(View, 'notifyMutationListeners'); - } - - // The `morph` and `outerHTML` properties are internal only - // and not observable. - - /** - @class _Metamorph - @namespace Ember - @private - */ - var _Metamorph = Mixin.create({ - isVirtual: true, - tagName: '', - - instrumentName: 'metamorph', - - init: function() { - this._super(); - Ember.deprecate('Supplying a tagName to Metamorph views is unreliable and is deprecated. You may be setting the tagName on a Handlebars helper that creates a Metamorph.', !this.tagName); - } - }); - __exports__._Metamorph = _Metamorph; - /** - @class _MetamorphView - @namespace Ember - @extends Ember.View - @uses Ember._Metamorph - @private - */ - var _MetamorphView = View.extend(_Metamorph); - __exports__._MetamorphView = _MetamorphView; - /** - @class _SimpleMetamorphView - @namespace Ember - @extends Ember.CoreView - @uses Ember._Metamorph - @private - */ - var _SimpleMetamorphView = CoreView.extend(_Metamorph); - __exports__._SimpleMetamorphView = _SimpleMetamorphView;__exports__["default"] = View.extend(_Metamorph); - }); -enifed("ember-metal-views", - ["ember-metal-views/renderer","exports"], - function(__dependency1__, __exports__) { - "use strict"; - var Renderer = __dependency1__["default"]; - __exports__.Renderer = Renderer; - }); -enifed("ember-metal-views/renderer", - ["morph","exports"], - function(__dependency1__, __exports__) { - "use strict"; - var DOMHelper = __dependency1__.DOMHelper; - - function Renderer() { - this._uuid = 0; - this._views = new Array(2000); - this._queue = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]; - this._parents = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]; - this._elements = new Array(17); - this._inserts = {}; - this._dom = new DOMHelper(); - } - - function Renderer_renderTree(_view, _parentView, _insertAt) { - var views = this._views; - views[0] = _view; - var insertAt = _insertAt === undefined ? -1 : _insertAt; - var index = 0; - var total = 1; - var levelBase = _parentView ? _parentView._level+1 : 0; - - var root = _parentView == null ? _view : _parentView._root; - - // if root view has a _morph assigned - var willInsert = !!root._morph; - - var queue = this._queue; - queue[0] = 0; - var length = 1; - - var parentIndex = -1; - var parents = this._parents; - var parent = _parentView || null; - var elements = this._elements; - var element = null; - var contextualElement = null; - var level = 0; - - var view = _view; - var children, i, l, child; - while (length) { - elements[level] = element; - if (!view._morph) { - // ensure props we add are in same order - view._morph = null; - } - view._root = root; - this.uuid(view); - view._level = levelBase + level; - if (view._elementCreated) { - this.remove(view, false, true); - } - - this.willCreateElement(view); - - contextualElement = view._morph && view._morph.contextualElement; - if (!contextualElement && parent && parent._childViewsMorph) { - contextualElement = parent._childViewsMorph.contextualElement; - } - if (!contextualElement && view._didCreateElementWithoutMorph) { - // This code path is only used by createElement and rerender when createElement - // was previously called on a view. - contextualElement = document.body; - } - Ember.assert("Required contextualElement for view "+_view+" is missing", contextualElement); - element = this.createElement(view, contextualElement); - - parents[level++] = parentIndex; - parentIndex = index; - parent = view; - - // enqueue for end - queue[length++] = index; - // enqueue children - children = this.childViews(view); - if (children) { - for (i=children.length-1;i>=0;i--) { - child = children[i]; - index = total++; - views[index] = child; - queue[length++] = index; - view = child; - } - } - - index = queue[--length]; - view = views[index]; - - while (parentIndex === index) { - level--; - view._elementCreated = true; - this.didCreateElement(view); - if (willInsert) { - this.willInsertElement(view); - } - - if (level === 0) { - length--; - break; - } - - parentIndex = parents[level]; - parent = parentIndex === -1 ? _parentView : views[parentIndex]; - this.insertElement(view, parent, element, -1); - index = queue[--length]; - view = views[index]; - element = elements[level]; - elements[level] = null; - } - } - - this.insertElement(view, _parentView, element, insertAt); - - for (i=total-1;i>=0;i--) { - if (willInsert) { - views[i]._elementInserted = true; - this.didInsertElement(views[i]); - } - views[i] = null; - } - - return element; - } - - Renderer.prototype.uuid = function Renderer_uuid(view) { - if (view._uuid === undefined) { - view._uuid = ++this._uuid; - view._renderer = this; - } // else assert(view._renderer === this) - return view._uuid; - }; - - Renderer.prototype.scheduleInsert = - function Renderer_scheduleInsert(view, morph) { - if (view._morph || view._elementCreated) { - throw new Error("You cannot insert a View that has already been rendered"); - } - Ember.assert("You cannot insert a View without a morph", morph); - view._morph = morph; - var viewId = this.uuid(view); - this._inserts[viewId] = this.scheduleRender(this, function() { - this._inserts[viewId] = null; - this.renderTree(view); - }); - }; - - Renderer.prototype.appendTo = - function Renderer_appendTo(view, target) { - var morph = this._dom.appendMorph(target); - this.scheduleInsert(view, morph); - }; - - Renderer.prototype.replaceIn = - function Renderer_replaceIn(view, target) { - var morph = this._dom.createMorph(target, null, null); - this.scheduleInsert(view, morph); - }; - - function Renderer_remove(_view, shouldDestroy, reset) { - var viewId = this.uuid(_view); - - if (this._inserts[viewId]) { - this.cancelRender(this._inserts[viewId]); - this._inserts[viewId] = undefined; - } - - if (!_view._elementCreated) { - return; - } - - var removeQueue = []; - var destroyQueue = []; - var morph = _view._morph; - var idx, len, view, staticChildren, queue, - childViews, i, l, parentView; - - removeQueue.push(_view); - - for (idx=0; idx -1; - }; - - var defineNativeShim = function(nativeFunc, shim) { - if (isNativeFunc(nativeFunc)) { - return nativeFunc; - } - return shim; - }; - - // From: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/array/map - var map = defineNativeShim(ArrayPrototype.map, function(fun /*, thisp */) { - //"use strict"; - - if (this === void 0 || this === null || typeof fun !== "function") { - throw new TypeError(); - } - - var t = Object(this); - var len = t.length >>> 0; - var res = new Array(len); - var thisp = arguments[1]; - - for (var i = 0; i < len; i++) { - if (i in t) { - res[i] = fun.call(thisp, t[i], i, t); - } - } - - return res; - }); - - // From: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/array/foreach - var forEach = defineNativeShim(ArrayPrototype.forEach, function(fun /*, thisp */) { - //"use strict"; - - if (this === void 0 || this === null || typeof fun !== "function") { - throw new TypeError(); - } - - var t = Object(this); - var len = t.length >>> 0; - var thisp = arguments[1]; - - for (var i = 0; i < len; i++) { - if (i in t) { - fun.call(thisp, t[i], i, t); - } - } - }); - - var indexOf = defineNativeShim(ArrayPrototype.indexOf, function (obj, fromIndex) { - if (fromIndex === null || fromIndex === undefined) { - fromIndex = 0; - } - else if (fromIndex < 0) { - fromIndex = Math.max(0, this.length + fromIndex); - } - - for (var i = fromIndex, j = this.length; i < j; i++) { - if (this[i] === obj) { - return i; - } - } - return -1; - }); - - var lastIndexOf = defineNativeShim(ArrayPrototype.lastIndexOf, function(obj, fromIndex) { - var len = this.length; - var idx; - - if (fromIndex === undefined) fromIndex = len-1; - else fromIndex = (fromIndex < 0) ? Math.ceil(fromIndex) : Math.floor(fromIndex); - if (fromIndex < 0) fromIndex += len; - - for(idx = fromIndex;idx>=0;idx--) { - if (this[idx] === obj) return idx ; - } - return -1; - }); - - var filter = defineNativeShim(ArrayPrototype.filter, function (fn, context) { - var i, value; - var result = []; - var length = this.length; - - for (i = 0; i < length; i++) { - if (this.hasOwnProperty(i)) { - value = this[i]; - if (fn.call(context, value, i, this)) { - result.push(value); - } - } - } - return result; - }); - - if (Ember.SHIM_ES5) { - ArrayPrototype.map = ArrayPrototype.map || map; - ArrayPrototype.forEach = ArrayPrototype.forEach || forEach; - ArrayPrototype.filter = ArrayPrototype.filter || filter; - ArrayPrototype.indexOf = ArrayPrototype.indexOf || indexOf; - ArrayPrototype.lastIndexOf = ArrayPrototype.lastIndexOf || lastIndexOf; - } - - /** - Array polyfills to support ES5 features in older browsers. - - @namespace Ember - @property ArrayPolyfills - */ - __exports__.map = map; - __exports__.forEach = forEach; - __exports__.filter = filter; - __exports__.indexOf = indexOf; - __exports__.lastIndexOf = lastIndexOf; - }); -enifed("ember-metal/binding", - ["ember-metal/core","ember-metal/property_get","ember-metal/property_set","ember-metal/utils","ember-metal/observer","ember-metal/run_loop","ember-metal/path_cache","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __exports__) { - "use strict"; - var Ember = __dependency1__["default"]; - // Ember.Logger, Ember.LOG_BINDINGS, assert - var get = __dependency2__.get; - var set = __dependency3__.set; - var trySet = __dependency3__.trySet; - var guidFor = __dependency4__.guidFor; - var addObserver = __dependency5__.addObserver; - var removeObserver = __dependency5__.removeObserver; - var _suspendObserver = __dependency5__._suspendObserver; - var run = __dependency6__["default"]; - var isGlobalPath = __dependency7__.isGlobal; - - - // ES6TODO: where is Ember.lookup defined? - /** - @module ember-metal - */ - - // .......................................................... - // CONSTANTS - // - - /** - Debug parameter you can turn on. This will log all bindings that fire to - the console. This should be disabled in production code. Note that you - can also enable this from the console or temporarily. - - @property LOG_BINDINGS - @for Ember - @type Boolean - @default false - */ - Ember.LOG_BINDINGS = false || !!Ember.ENV.LOG_BINDINGS; - - /** - Returns true if the provided path is global (e.g., `MyApp.fooController.bar`) - instead of local (`foo.bar.baz`). - - @method isGlobalPath - @for Ember - @private - @param {String} path - @return Boolean - */ - - function getWithGlobals(obj, path) { - return get(isGlobalPath(path) ? Ember.lookup : obj, path); - } - - // .......................................................... - // BINDING - // - - function Binding(toPath, fromPath) { - this._direction = undefined; - this._from = fromPath; - this._to = toPath; - this._readyToSync = undefined; - this._oneWay = undefined; - } - - /** - @class Binding - @namespace Ember - */ - - Binding.prototype = { - /** - This copies the Binding so it can be connected to another object. - - @method copy - @return {Ember.Binding} `this` - */ - copy: function () { - var copy = new Binding(this._to, this._from); - if (this._oneWay) { copy._oneWay = true; } - return copy; - }, - - // .......................................................... - // CONFIG - // - - /** - This will set `from` property path to the specified value. It will not - attempt to resolve this property path to an actual object until you - connect the binding. - - The binding will search for the property path starting at the root object - you pass when you `connect()` the binding. It follows the same rules as - `get()` - see that method for more information. - - @method from - @param {String} path the property path to connect to - @return {Ember.Binding} `this` - */ - from: function(path) { - this._from = path; - return this; - }, - - /** - This will set the `to` property path to the specified value. It will not - attempt to resolve this property path to an actual object until you - connect the binding. - - The binding will search for the property path starting at the root object - you pass when you `connect()` the binding. It follows the same rules as - `get()` - see that method for more information. - - @method to - @param {String|Tuple} path A property path or tuple - @return {Ember.Binding} `this` - */ - to: function(path) { - this._to = path; - return this; - }, - - /** - Configures the binding as one way. A one-way binding will relay changes - on the `from` side to the `to` side, but not the other way around. This - means that if you change the `to` side directly, the `from` side may have - a different value. - - @method oneWay - @return {Ember.Binding} `this` - */ - oneWay: function() { - this._oneWay = true; - return this; - }, - - /** - @method toString - @return {String} string representation of binding - */ - toString: function() { - var oneWay = this._oneWay ? '[oneWay]' : ''; - return "Ember.Binding<" + guidFor(this) + ">(" + this._from + " -> " + this._to + ")" + oneWay; - }, - - // .......................................................... - // CONNECT AND SYNC - // - - /** - Attempts to connect this binding instance so that it can receive and relay - changes. This method will raise an exception if you have not set the - from/to properties yet. - - @method connect - @param {Object} obj The root object for this binding. - @return {Ember.Binding} `this` - */ - connect: function(obj) { - Ember.assert('Must pass a valid object to Ember.Binding.connect()', !!obj); - - var fromPath = this._from; - var toPath = this._to; - trySet(obj, toPath, getWithGlobals(obj, fromPath)); - - // add an observer on the object to be notified when the binding should be updated - addObserver(obj, fromPath, this, this.fromDidChange); - - // if the binding is a two-way binding, also set up an observer on the target - if (!this._oneWay) { addObserver(obj, toPath, this, this.toDidChange); } - - this._readyToSync = true; - - return this; - }, - - /** - Disconnects the binding instance. Changes will no longer be relayed. You - will not usually need to call this method. - - @method disconnect - @param {Object} obj The root object you passed when connecting the binding. - @return {Ember.Binding} `this` - */ - disconnect: function(obj) { - Ember.assert('Must pass a valid object to Ember.Binding.disconnect()', !!obj); - - var twoWay = !this._oneWay; - - // remove an observer on the object so we're no longer notified of - // changes that should update bindings. - removeObserver(obj, this._from, this, this.fromDidChange); - - // if the binding is two-way, remove the observer from the target as well - if (twoWay) { removeObserver(obj, this._to, this, this.toDidChange); } - - this._readyToSync = false; // disable scheduled syncs... - return this; - }, - - // .......................................................... - // PRIVATE - // - - /* called when the from side changes */ - fromDidChange: function(target) { - this._scheduleSync(target, 'fwd'); - }, - - /* called when the to side changes */ - toDidChange: function(target) { - this._scheduleSync(target, 'back'); - }, - - _scheduleSync: function(obj, dir) { - var existingDir = this._direction; - - // if we haven't scheduled the binding yet, schedule it - if (existingDir === undefined) { - run.schedule('sync', this, this._sync, obj); - this._direction = dir; - } - - // If both a 'back' and 'fwd' sync have been scheduled on the same object, - // default to a 'fwd' sync so that it remains deterministic. - if (existingDir === 'back' && dir === 'fwd') { - this._direction = 'fwd'; - } - }, - - _sync: function(obj) { - var log = Ember.LOG_BINDINGS; - - // don't synchronize destroyed objects or disconnected bindings - if (obj.isDestroyed || !this._readyToSync) { return; } - - // get the direction of the binding for the object we are - // synchronizing from - var direction = this._direction; - - var fromPath = this._from; - var toPath = this._to; - - this._direction = undefined; - - // if we're synchronizing from the remote object... - if (direction === 'fwd') { - var fromValue = getWithGlobals(obj, this._from); - if (log) { - Ember.Logger.log(' ', this.toString(), '->', fromValue, obj); - } - if (this._oneWay) { - trySet(obj, toPath, fromValue); - } else { - _suspendObserver(obj, toPath, this, this.toDidChange, function () { - trySet(obj, toPath, fromValue); - }); - } - // if we're synchronizing *to* the remote object - } else if (direction === 'back') { - var toValue = get(obj, this._to); - if (log) { - Ember.Logger.log(' ', this.toString(), '<-', toValue, obj); - } - _suspendObserver(obj, fromPath, this, this.fromDidChange, function () { - trySet(isGlobalPath(fromPath) ? Ember.lookup : obj, fromPath, toValue); - }); - } - } - - }; - - function mixinProperties(to, from) { - for (var key in from) { - if (from.hasOwnProperty(key)) { - to[key] = from[key]; - } - } - } - - mixinProperties(Binding, { - - /* - See `Ember.Binding.from`. - - @method from - @static - */ - from: function(from) { - var C = this; - return new C(undefined, from); - }, - - /* - See `Ember.Binding.to`. - - @method to - @static - */ - to: function(to) { - var C = this; - return new C(to, undefined); - }, - - /** - Creates a new Binding instance and makes it apply in a single direction. - A one-way binding will relay changes on the `from` side object (supplied - as the `from` argument) the `to` side, but not the other way around. - This means that if you change the "to" side directly, the "from" side may have - a different value. - - See `Binding.oneWay`. - - @method oneWay - @param {String} from from path. - @param {Boolean} [flag] (Optional) passing nothing here will make the - binding `oneWay`. You can instead pass `false` to disable `oneWay`, making the - binding two way again. - @return {Ember.Binding} `this` - */ - oneWay: function(from, flag) { - var C = this; - return new C(undefined, from).oneWay(flag); - } - - }); - /** - An `Ember.Binding` connects the properties of two objects so that whenever - the value of one property changes, the other property will be changed also. - - ## Automatic Creation of Bindings with `/^*Binding/`-named Properties - - You do not usually create Binding objects directly but instead describe - bindings in your class or object definition using automatic binding - detection. - - Properties ending in a `Binding` suffix will be converted to `Ember.Binding` - instances. The value of this property should be a string representing a path - to another object or a custom binding instance created using Binding helpers - (see "One Way Bindings"): - - ``` - valueBinding: "MyApp.someController.title" - ``` - - This will create a binding from `MyApp.someController.title` to the `value` - property of your object instance automatically. Now the two values will be - kept in sync. - - ## One Way Bindings - - One especially useful binding customization you can use is the `oneWay()` - helper. This helper tells Ember that you are only interested in - receiving changes on the object you are binding from. For example, if you - are binding to a preference and you want to be notified if the preference - has changed, but your object will not be changing the preference itself, you - could do: - - ``` - bigTitlesBinding: Ember.Binding.oneWay("MyApp.preferencesController.bigTitles") - ``` - - This way if the value of `MyApp.preferencesController.bigTitles` changes the - `bigTitles` property of your object will change also. However, if you - change the value of your `bigTitles` property, it will not update the - `preferencesController`. - - One way bindings are almost twice as fast to setup and twice as fast to - execute because the binding only has to worry about changes to one side. - - You should consider using one way bindings anytime you have an object that - may be created frequently and you do not intend to change a property; only - to monitor it for changes (such as in the example above). - - ## Adding Bindings Manually - - All of the examples above show you how to configure a custom binding, but the - result of these customizations will be a binding template, not a fully active - Binding instance. The binding will actually become active only when you - instantiate the object the binding belongs to. It is useful however, to - understand what actually happens when the binding is activated. - - For a binding to function it must have at least a `from` property and a `to` - property. The `from` property path points to the object/key that you want to - bind from while the `to` path points to the object/key you want to bind to. - - When you define a custom binding, you are usually describing the property - you want to bind from (such as `MyApp.someController.value` in the examples - above). When your object is created, it will automatically assign the value - you want to bind `to` based on the name of your binding key. In the - examples above, during init, Ember objects will effectively call - something like this on your binding: - - ```javascript - binding = Ember.Binding.from("valueBinding").to("value"); - ``` - - This creates a new binding instance based on the template you provide, and - sets the to path to the `value` property of the new object. Now that the - binding is fully configured with a `from` and a `to`, it simply needs to be - connected to become active. This is done through the `connect()` method: - - ```javascript - binding.connect(this); - ``` - - Note that when you connect a binding you pass the object you want it to be - connected to. This object will be used as the root for both the from and - to side of the binding when inspecting relative paths. This allows the - binding to be automatically inherited by subclassed objects as well. - - This also allows you to bind between objects using the paths you declare in - `from` and `to`: - - ```javascript - // Example 1 - binding = Ember.Binding.from("App.someObject.value").to("value"); - binding.connect(this); - - // Example 2 - binding = Ember.Binding.from("parentView.value").to("App.someObject.value"); - binding.connect(this); - ``` - - Now that the binding is connected, it will observe both the from and to side - and relay changes. - - If you ever needed to do so (you almost never will, but it is useful to - understand this anyway), you could manually create an active binding by - using the `Ember.bind()` helper method. (This is the same method used by - to setup your bindings on objects): - - ```javascript - Ember.bind(MyApp.anotherObject, "value", "MyApp.someController.value"); - ``` - - Both of these code fragments have the same effect as doing the most friendly - form of binding creation like so: - - ```javascript - MyApp.anotherObject = Ember.Object.create({ - valueBinding: "MyApp.someController.value", - - // OTHER CODE FOR THIS OBJECT... - }); - ``` - - Ember's built in binding creation method makes it easy to automatically - create bindings for you. You should always use the highest-level APIs - available, even if you understand how it works underneath. - - @class Binding - @namespace Ember - @since Ember 0.9 - */ - // Ember.Binding = Binding; ES6TODO: where to put this? - - - /** - Global helper method to create a new binding. Just pass the root object - along with a `to` and `from` path to create and connect the binding. - - @method bind - @for Ember - @param {Object} obj The root object of the transform. - @param {String} to The path to the 'to' side of the binding. - Must be relative to obj. - @param {String} from The path to the 'from' side of the binding. - Must be relative to obj or a global path. - @return {Ember.Binding} binding instance - */ - function bind(obj, to, from) { - return new Binding(to, from).connect(obj); - } - - __exports__.bind = bind;/** - @method oneWay - @for Ember - @param {Object} obj The root object of the transform. - @param {String} to The path to the 'to' side of the binding. - Must be relative to obj. - @param {String} from The path to the 'from' side of the binding. - Must be relative to obj or a global path. - @return {Ember.Binding} binding instance - */ - function oneWay(obj, to, from) { - return new Binding(to, from).oneWay().connect(obj); - } - - __exports__.oneWay = oneWay;__exports__.Binding = Binding; - __exports__.isGlobalPath = isGlobalPath; - }); -enifed("ember-metal/cache", - ["ember-metal/dictionary","exports"], - function(__dependency1__, __exports__) { - "use strict"; - var dictionary = __dependency1__["default"]; - __exports__["default"] = Cache; - - function Cache(limit, func) { - this.store = dictionary(null); - this.size = 0; - this.misses = 0; - this.hits = 0; - this.limit = limit; - this.func = func; - } - - var FALSE = function() { }; - var ZERO = function() { }; - var UNDEFINED = function() { }; - var NULL = function() { }; - - Cache.prototype = { - set: function(key, value) { - if (this.limit > this.size) { - this.size ++; - if (value === undefined) { - this.store[key] = UNDEFINED; - } else { - this.store[key] = value; - } - } - - return value; - }, - - get: function(key) { - var value = this.store[key]; - - if (value === undefined) { - this.misses ++; - value = this.set(key, this.func(key)); - } else if (value === UNDEFINED) { - this.hits ++; - value = undefined; - } else { - this.hits ++; - // nothing to translate - } - - return value; - }, - - purge: function() { - this.store = dictionary(null); - this.size = 0; - this.hits = 0; - this.misses = 0; - } - }; - }); -enifed("ember-metal/chains", - ["ember-metal/core","ember-metal/property_get","ember-metal/utils","ember-metal/array","ember-metal/watch_key","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __exports__) { - "use strict"; - var Ember = __dependency1__["default"]; - // warn, assert, etc; - var get = __dependency2__.get; - var normalizeTuple = __dependency2__.normalizeTuple; - var meta = __dependency3__.meta; - var forEach = __dependency4__.forEach; - var watchKey = __dependency5__.watchKey; - var unwatchKey = __dependency5__.unwatchKey; - - var metaFor = meta; - var warn = Ember.warn; - var FIRST_KEY = /^([^\.]+)/; - - function firstKey(path) { - return path.match(FIRST_KEY)[0]; - } - - var pendingQueue = []; - - // attempts to add the pendingQueue chains again. If some of them end up - // back in the queue and reschedule is true, schedules a timeout to try - // again. - function flushPendingChains() { - if (pendingQueue.length === 0) { return; } // nothing to do - - var queue = pendingQueue; - pendingQueue = []; - - forEach.call(queue, function(q) { q[0].add(q[1]); }); - - warn('Watching an undefined global, Ember expects watched globals to be setup by the time the run loop is flushed, check for typos', pendingQueue.length === 0); - } - - __exports__.flushPendingChains = flushPendingChains;function addChainWatcher(obj, keyName, node) { - if (!obj || ('object' !== typeof obj)) { return; } // nothing to do - - var m = metaFor(obj); - var nodes = m.chainWatchers; - - if (!m.hasOwnProperty('chainWatchers')) { - nodes = m.chainWatchers = {}; - } - - if (!nodes[keyName]) { nodes[keyName] = []; } - nodes[keyName].push(node); - watchKey(obj, keyName, m); - } - - function removeChainWatcher(obj, keyName, node) { - if (!obj || 'object' !== typeof obj) { return; } // nothing to do - - var m = obj['__ember_meta__']; - if (m && !m.hasOwnProperty('chainWatchers')) { return; } // nothing to do - - var nodes = m && m.chainWatchers; - - if (nodes && nodes[keyName]) { - nodes = nodes[keyName]; - for (var i = 0, l = nodes.length; i < l; i++) { - if (nodes[i] === node) { - nodes.splice(i, 1); - break; - } - } - } - unwatchKey(obj, keyName, m); - } - - // A ChainNode watches a single key on an object. If you provide a starting - // value for the key then the node won't actually watch it. For a root node - // pass null for parent and key and object for value. - function ChainNode(parent, key, value) { - this._parent = parent; - this._key = key; - - // _watching is true when calling get(this._parent, this._key) will - // return the value of this node. - // - // It is false for the root of a chain (because we have no parent) - // and for global paths (because the parent node is the object with - // the observer on it) - this._watching = value===undefined; - - this._value = value; - this._paths = {}; - if (this._watching) { - this._object = parent.value(); - if (this._object) { addChainWatcher(this._object, this._key, this); } - } - - // Special-case: the EachProxy relies on immediate evaluation to - // establish its observers. - // - // TODO: Replace this with an efficient callback that the EachProxy - // can implement. - if (this._parent && this._parent._key === '@each') { - this.value(); - } - } - - var ChainNodePrototype = ChainNode.prototype; - - function lazyGet(obj, key) { - if (!obj) return undefined; - - var meta = obj['__ember_meta__']; - // check if object meant only to be a prototype - if (meta && meta.proto === obj) return undefined; - - if (key === "@each") return get(obj, key); - - // if a CP only return cached value - var desc = meta && meta.descs[key]; - if (desc && desc._cacheable) { - if (key in meta.cache) { - return meta.cache[key]; - } else { - return undefined; - } - } - - return get(obj, key); - } - - ChainNodePrototype.value = function() { - if (this._value === undefined && this._watching) { - var obj = this._parent.value(); - this._value = lazyGet(obj, this._key); - } - return this._value; - }; - - ChainNodePrototype.destroy = function() { - if (this._watching) { - var obj = this._object; - if (obj) { removeChainWatcher(obj, this._key, this); } - this._watching = false; // so future calls do nothing - } - }; - - // copies a top level object only - ChainNodePrototype.copy = function(obj) { - var ret = new ChainNode(null, null, obj); - var paths = this._paths; - var path; - - for (path in paths) { - if (paths[path] <= 0) { continue; } // this check will also catch non-number vals. - ret.add(path); - } - return ret; - }; - - // called on the root node of a chain to setup watchers on the specified - // path. - ChainNodePrototype.add = function(path) { - var obj, tuple, key, src, paths; - - paths = this._paths; - paths[path] = (paths[path] || 0) + 1; - - obj = this.value(); - tuple = normalizeTuple(obj, path); - - // the path was a local path - if (tuple[0] && tuple[0] === obj) { - path = tuple[1]; - key = firstKey(path); - path = path.slice(key.length+1); - - // global path, but object does not exist yet. - // put into a queue and try to connect later. - } else if (!tuple[0]) { - pendingQueue.push([this, path]); - tuple.length = 0; - return; - - // global path, and object already exists - } else { - src = tuple[0]; - key = path.slice(0, 0-(tuple[1].length+1)); - path = tuple[1]; - } - - tuple.length = 0; - this.chain(key, path, src); - }; - - // called on the root node of a chain to teardown watcher on the specified - // path - ChainNodePrototype.remove = function(path) { - var obj, tuple, key, src, paths; - - paths = this._paths; - if (paths[path] > 0) { paths[path]--; } - - obj = this.value(); - tuple = normalizeTuple(obj, path); - if (tuple[0] === obj) { - path = tuple[1]; - key = firstKey(path); - path = path.slice(key.length+1); - } else { - src = tuple[0]; - key = path.slice(0, 0-(tuple[1].length+1)); - path = tuple[1]; - } - - tuple.length = 0; - this.unchain(key, path); - }; - - ChainNodePrototype.count = 0; - - ChainNodePrototype.chain = function(key, path, src) { - var chains = this._chains; - var node; - if (!chains) { chains = this._chains = {}; } - - node = chains[key]; - if (!node) { node = chains[key] = new ChainNode(this, key, src); } - node.count++; // count chains... - - // chain rest of path if there is one - if (path) { - key = firstKey(path); - path = path.slice(key.length+1); - node.chain(key, path); // NOTE: no src means it will observe changes... - } - }; - - ChainNodePrototype.unchain = function(key, path) { - var chains = this._chains; - var node = chains[key]; - - // unchain rest of path first... - if (path && path.length>1) { - key = firstKey(path); - path = path.slice(key.length+1); - node.unchain(key, path); - } - - // delete node if needed. - node.count--; - if (node.count<=0) { - delete chains[node._key]; - node.destroy(); - } - - }; - - ChainNodePrototype.willChange = function(events) { - var chains = this._chains; - if (chains) { - for(var key in chains) { - if (!chains.hasOwnProperty(key)) { continue; } - chains[key].willChange(events); - } - } - - if (this._parent) { this._parent.chainWillChange(this, this._key, 1, events); } - }; - - ChainNodePrototype.chainWillChange = function(chain, path, depth, events) { - if (this._key) { path = this._key + '.' + path; } - - if (this._parent) { - this._parent.chainWillChange(this, path, depth+1, events); - } else { - if (depth > 1) { - events.push(this.value(), path); - } - path = 'this.' + path; - if (this._paths[path] > 0) { - events.push(this.value(), path); - } - } - }; - - ChainNodePrototype.chainDidChange = function(chain, path, depth, events) { - if (this._key) { path = this._key + '.' + path; } - if (this._parent) { - this._parent.chainDidChange(this, path, depth+1, events); - } else { - if (depth > 1) { - events.push(this.value(), path); - } - path = 'this.' + path; - if (this._paths[path] > 0) { - events.push(this.value(), path); - } - } - }; - - ChainNodePrototype.didChange = function(events) { - // invalidate my own value first. - if (this._watching) { - var obj = this._parent.value(); - if (obj !== this._object) { - removeChainWatcher(this._object, this._key, this); - this._object = obj; - addChainWatcher(obj, this._key, this); - } - this._value = undefined; - - // Special-case: the EachProxy relies on immediate evaluation to - // establish its observers. - if (this._parent && this._parent._key === '@each') - this.value(); - } - - // then notify chains... - var chains = this._chains; - if (chains) { - for(var key in chains) { - if (!chains.hasOwnProperty(key)) { continue; } - chains[key].didChange(events); - } - } - - // if no events are passed in then we only care about the above wiring update - if (events === null) { return; } - - // and finally tell parent about my path changing... - if (this._parent) { this._parent.chainDidChange(this, this._key, 1, events); } - }; - - function finishChains(obj) { - // We only create meta if we really have to - var m = obj['__ember_meta__'], - chains, chainWatchers, chainNodes; - if (m) { - // finish any current chains node watchers that reference obj - chainWatchers = m.chainWatchers; - if (chainWatchers) { - for(var key in chainWatchers) { - if (!chainWatchers.hasOwnProperty(key)) { continue; } - chainNodes = chainWatchers[key]; - if (chainNodes) { - for (var i=0,l=chainNodes.length;i 1) { - args = a_slice.call(arguments); - func = args.pop(); - } - - if (typeof func !== "function") { - throw new EmberError("Computed Property declared without a property function"); - } - - var cp = new ComputedProperty(func); - - if (args) { - cp.property.apply(cp, args); - } - - return cp; - } - - /** - Returns the cached value for a property, if one exists. - This can be useful for peeking at the value of a computed - property that is generated lazily, without accidentally causing - it to be created. - - @method cacheFor - @for Ember - @param {Object} obj the object whose property you want to check - @param {String} key the name of the property whose cached value you want - to return - @return {Object} the cached value - */ - function cacheFor(obj, key) { - var meta = obj['__ember_meta__']; - var cache = meta && meta.cache; - var ret = cache && cache[key]; - - if (ret === UNDEFINED) { return undefined; } - return ret; - } - - cacheFor.set = function(cache, key, value) { - if (value === undefined) { - cache[key] = UNDEFINED; - } else { - cache[key] = value; - } - }; - - cacheFor.get = function(cache, key) { - var ret = cache[key]; - if (ret === UNDEFINED) { return undefined; } - return ret; - }; - - cacheFor.remove = function(cache, key) { - cache[key] = undefined; - }; - - __exports__.ComputedProperty = ComputedProperty; - __exports__.computed = computed; - __exports__.cacheFor = cacheFor; - }); -enifed("ember-metal/computed_macros", - ["ember-metal/core","ember-metal/property_get","ember-metal/property_set","ember-metal/computed","ember-metal/is_empty","ember-metal/is_none","ember-metal/alias"], - function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__) { - "use strict"; - var Ember = __dependency1__["default"]; - var get = __dependency2__.get; - var set = __dependency3__.set; - var computed = __dependency4__.computed; - var isEmpty = __dependency5__["default"]; - var isNone = __dependency6__.isNone; - var alias = __dependency7__.alias; - - /** - @module ember-metal - */ - - var a_slice = [].slice; - - function getProperties(self, propertyNames) { - var ret = {}; - for(var i = 0; i < propertyNames.length; i++) { - ret[propertyNames[i]] = get(self, propertyNames[i]); - } - return ret; - } - - function registerComputed(name, macro) { - computed[name] = function(dependentKey) { - var args = a_slice.call(arguments); - return computed(dependentKey, function() { - return macro.apply(this, args); - }); - }; - } - - function registerComputedWithProperties(name, macro) { - computed[name] = function() { - var properties = a_slice.call(arguments); - - var computedFunc = computed(function() { - return macro.apply(this, [getProperties(this, properties)]); - }); - - return computedFunc.property.apply(computedFunc, properties); - }; - } - - /** - A computed property that returns true if the value of the dependent - property is null, an empty string, empty array, or empty function. - - Example - - ```javascript - var ToDoList = Ember.Object.extend({ - done: Ember.computed.empty('todos') - }); - - var todoList = ToDoList.create({ - todos: ['Unit Test', 'Documentation', 'Release'] - }); - - todoList.get('done'); // false - todoList.get('todos').clear(); - todoList.get('done'); // true - ``` - - @since 1.6.0 - @method computed.empty - @for Ember - @param {String} dependentKey - @return {Ember.ComputedProperty} computed property which negate - the original value for property - */ - computed.empty = function (dependentKey) { - return computed(dependentKey + '.length', function () { - return isEmpty(get(this, dependentKey)); - }); - }; - - /** - A computed property that returns true if the value of the dependent - property is NOT null, an empty string, empty array, or empty function. - - Example - - ```javascript - var Hamster = Ember.Object.extend({ - hasStuff: Ember.computed.notEmpty('backpack') - }); - - var hamster = Hamster.create({ backpack: ['Food', 'Sleeping Bag', 'Tent'] }); - - hamster.get('hasStuff'); // true - hamster.get('backpack').clear(); // [] - hamster.get('hasStuff'); // false - ``` - - @method computed.notEmpty - @for Ember - @param {String} dependentKey - @return {Ember.ComputedProperty} computed property which returns true if - original value for property is not empty. - */ - computed.notEmpty = function(dependentKey) { - return computed(dependentKey + '.length', function () { - return !isEmpty(get(this, dependentKey)); - }); - }; - - /** - A computed property that returns true if the value of the dependent - property is null or undefined. This avoids errors from JSLint complaining - about use of ==, which can be technically confusing. - - Example - - ```javascript - var Hamster = Ember.Object.extend({ - isHungry: Ember.computed.none('food') - }); - - var hamster = Hamster.create(); - - hamster.get('isHungry'); // true - hamster.set('food', 'Banana'); - hamster.get('isHungry'); // false - hamster.set('food', null); - hamster.get('isHungry'); // true - ``` - - @method computed.none - @for Ember - @param {String} dependentKey - @return {Ember.ComputedProperty} computed property which - returns true if original value for property is null or undefined. - */ - registerComputed('none', function(dependentKey) { - return isNone(get(this, dependentKey)); - }); - - /** - A computed property that returns the inverse boolean value - of the original value for the dependent property. - - Example - - ```javascript - var User = Ember.Object.extend({ - isAnonymous: Ember.computed.not('loggedIn') - }); - - var user = User.create({loggedIn: false}); - - user.get('isAnonymous'); // true - user.set('loggedIn', true); - user.get('isAnonymous'); // false - ``` - - @method computed.not - @for Ember - @param {String} dependentKey - @return {Ember.ComputedProperty} computed property which returns - inverse of the original value for property - */ - registerComputed('not', function(dependentKey) { - return !get(this, dependentKey); - }); - - /** - A computed property that converts the provided dependent property - into a boolean value. - - ```javascript - var Hamster = Ember.Object.extend({ - hasBananas: Ember.computed.bool('numBananas') - }); - - var hamster = Hamster.create(); - - hamster.get('hasBananas'); // false - hamster.set('numBananas', 0); - hamster.get('hasBananas'); // false - hamster.set('numBananas', 1); - hamster.get('hasBananas'); // true - hamster.set('numBananas', null); - hamster.get('hasBananas'); // false - ``` - - @method computed.bool - @for Ember - @param {String} dependentKey - @return {Ember.ComputedProperty} computed property which converts - to boolean the original value for property - */ - registerComputed('bool', function(dependentKey) { - return !!get(this, dependentKey); - }); - - /** - A computed property which matches the original value for the - dependent property against a given RegExp, returning `true` - if they values matches the RegExp and `false` if it does not. - - Example - - ```javascript - var User = Ember.Object.extend({ - hasValidEmail: Ember.computed.match('email', /^.+@.+\..+$/) - }); - - var user = User.create({loggedIn: false}); - - user.get('hasValidEmail'); // false - user.set('email', ''); - user.get('hasValidEmail'); // false - user.set('email', 'ember_hamster@example.com'); - user.get('hasValidEmail'); // true - ``` - - @method computed.match - @for Ember - @param {String} dependentKey - @param {RegExp} regexp - @return {Ember.ComputedProperty} computed property which match - the original value for property against a given RegExp - */ - registerComputed('match', function(dependentKey, regexp) { - var value = get(this, dependentKey); - return typeof value === 'string' ? regexp.test(value) : false; - }); - - /** - A computed property that returns true if the provided dependent property - is equal to the given value. - - Example - - ```javascript - var Hamster = Ember.Object.extend({ - napTime: Ember.computed.equal('state', 'sleepy') - }); - - var hamster = Hamster.create(); - - hamster.get('napTime'); // false - hamster.set('state', 'sleepy'); - hamster.get('napTime'); // true - hamster.set('state', 'hungry'); - hamster.get('napTime'); // false - ``` - - @method computed.equal - @for Ember - @param {String} dependentKey - @param {String|Number|Object} value - @return {Ember.ComputedProperty} computed property which returns true if - the original value for property is equal to the given value. - */ - registerComputed('equal', function(dependentKey, value) { - return get(this, dependentKey) === value; - }); - - /** - A computed property that returns true if the provided dependent property - is greater than the provided value. - - Example - - ```javascript - var Hamster = Ember.Object.extend({ - hasTooManyBananas: Ember.computed.gt('numBananas', 10) - }); - - var hamster = Hamster.create(); - - hamster.get('hasTooManyBananas'); // false - hamster.set('numBananas', 3); - hamster.get('hasTooManyBananas'); // false - hamster.set('numBananas', 11); - hamster.get('hasTooManyBananas'); // true - ``` - - @method computed.gt - @for Ember - @param {String} dependentKey - @param {Number} value - @return {Ember.ComputedProperty} computed property which returns true if - the original value for property is greater than given value. - */ - registerComputed('gt', function(dependentKey, value) { - return get(this, dependentKey) > value; - }); - - /** - A computed property that returns true if the provided dependent property - is greater than or equal to the provided value. - - Example - - ```javascript - var Hamster = Ember.Object.extend({ - hasTooManyBananas: Ember.computed.gte('numBananas', 10) - }); - - var hamster = Hamster.create(); - - hamster.get('hasTooManyBananas'); // false - hamster.set('numBananas', 3); - hamster.get('hasTooManyBananas'); // false - hamster.set('numBananas', 10); - hamster.get('hasTooManyBananas'); // true - ``` - - @method computed.gte - @for Ember - @param {String} dependentKey - @param {Number} value - @return {Ember.ComputedProperty} computed property which returns true if - the original value for property is greater or equal then given value. - */ - registerComputed('gte', function(dependentKey, value) { - return get(this, dependentKey) >= value; - }); - - /** - A computed property that returns true if the provided dependent property - is less than the provided value. - - Example - - ```javascript - var Hamster = Ember.Object.extend({ - needsMoreBananas: Ember.computed.lt('numBananas', 3) - }); - - var hamster = Hamster.create(); - - hamster.get('needsMoreBananas'); // true - hamster.set('numBananas', 3); - hamster.get('needsMoreBananas'); // false - hamster.set('numBananas', 2); - hamster.get('needsMoreBananas'); // true - ``` - - @method computed.lt - @for Ember - @param {String} dependentKey - @param {Number} value - @return {Ember.ComputedProperty} computed property which returns true if - the original value for property is less then given value. - */ - registerComputed('lt', function(dependentKey, value) { - return get(this, dependentKey) < value; - }); - - /** - A computed property that returns true if the provided dependent property - is less than or equal to the provided value. - - Example - - ```javascript - var Hamster = Ember.Object.extend({ - needsMoreBananas: Ember.computed.lte('numBananas', 3) - }); - - var hamster = Hamster.create(); - - hamster.get('needsMoreBananas'); // true - hamster.set('numBananas', 5); - hamster.get('needsMoreBananas'); // false - hamster.set('numBananas', 3); - hamster.get('needsMoreBananas'); // true - ``` - - @method computed.lte - @for Ember - @param {String} dependentKey - @param {Number} value - @return {Ember.ComputedProperty} computed property which returns true if - the original value for property is less or equal than given value. - */ - registerComputed('lte', function(dependentKey, value) { - return get(this, dependentKey) <= value; - }); - - /** - A computed property that performs a logical `and` on the - original values for the provided dependent properties. - - Example - - ```javascript - var Hamster = Ember.Object.extend({ - readyForCamp: Ember.computed.and('hasTent', 'hasBackpack') - }); - - var hamster = Hamster.create(); - - hamster.get('readyForCamp'); // false - hamster.set('hasTent', true); - hamster.get('readyForCamp'); // false - hamster.set('hasBackpack', true); - hamster.get('readyForCamp'); // true - ``` - - @method computed.and - @for Ember - @param {String} dependentKey* - @return {Ember.ComputedProperty} computed property which performs - a logical `and` on the values of all the original values for properties. - */ - registerComputedWithProperties('and', function(properties) { - for (var key in properties) { - if (properties.hasOwnProperty(key) && !properties[key]) { - return false; - } - } - return true; - }); - - /** - A computed property which performs a logical `or` on the - original values for the provided dependent properties. - - Example - - ```javascript - var Hamster = Ember.Object.extend({ - readyForRain: Ember.computed.or('hasJacket', 'hasUmbrella') - }); - - var hamster = Hamster.create(); - - hamster.get('readyForRain'); // false - hamster.set('hasJacket', true); - hamster.get('readyForRain'); // true - ``` - - @method computed.or - @for Ember - @param {String} dependentKey* - @return {Ember.ComputedProperty} computed property which performs - a logical `or` on the values of all the original values for properties. - */ - registerComputedWithProperties('or', function(properties) { - for (var key in properties) { - if (properties.hasOwnProperty(key) && properties[key]) { - return true; - } - } - return false; - }); - - /** - A computed property that returns the first truthy value - from a list of dependent properties. - - Example - - ```javascript - var Hamster = Ember.Object.extend({ - hasClothes: Ember.computed.any('hat', 'shirt') - }); - - var hamster = Hamster.create(); - - hamster.get('hasClothes'); // null - hamster.set('shirt', 'Hawaiian Shirt'); - hamster.get('hasClothes'); // 'Hawaiian Shirt' - ``` - - @method computed.any - @for Ember - @param {String} dependentKey* - @return {Ember.ComputedProperty} computed property which returns - the first truthy value of given list of properties. - */ - registerComputedWithProperties('any', function(properties) { - for (var key in properties) { - if (properties.hasOwnProperty(key) && properties[key]) { - return properties[key]; - } - } - return null; - }); - - /** - A computed property that returns the array of values - for the provided dependent properties. - - Example - - ```javascript - var Hamster = Ember.Object.extend({ - clothes: Ember.computed.collect('hat', 'shirt') - }); - - var hamster = Hamster.create(); - - hamster.get('clothes'); // [null, null] - hamster.set('hat', 'Camp Hat'); - hamster.set('shirt', 'Camp Shirt'); - hamster.get('clothes'); // ['Camp Hat', 'Camp Shirt'] - ``` - - @method computed.collect - @for Ember - @param {String} dependentKey* - @return {Ember.ComputedProperty} computed property which maps - values of all passed in properties to an array. - */ - registerComputedWithProperties('collect', function(properties) { - var res = []; - for (var key in properties) { - if (properties.hasOwnProperty(key)) { - if (isNone(properties[key])) { - res.push(null); - } else { - res.push(properties[key]); - } - } - } - return res; - }); - - /** - Creates a new property that is an alias for another property - on an object. Calls to `get` or `set` this property behave as - though they were called on the original property. - - ```javascript - var Person = Ember.Object.extend({ - name: 'Alex Matchneer', - nomen: Ember.computed.alias('name') - }); - - var alex = Person.create(); - - alex.get('nomen'); // 'Alex Matchneer' - alex.get('name'); // 'Alex Matchneer' - - alex.set('nomen', '@machty'); - alex.get('name'); // '@machty' - ``` - - @method computed.alias - @for Ember - @param {String} dependentKey - @return {Ember.ComputedProperty} computed property which creates an - alias to the original value for property. - */ - computed.alias = alias; - - /** - Where `computed.alias` aliases `get` and `set`, and allows for bidirectional - data flow, `computed.oneWay` only provides an aliased `get`. The `set` will - not mutate the upstream property, rather causes the current property to - become the value set. This causes the downstream property to permanently - diverge from the upstream property. - - Example - - ```javascript - var User = Ember.Object.extend({ - firstName: null, - lastName: null, - nickName: Ember.computed.oneWay('firstName') - }); - - var teddy = User.create({ - firstName: 'Teddy', - lastName: 'Zeenny' - }); - - teddy.get('nickName'); // 'Teddy' - teddy.set('nickName', 'TeddyBear'); // 'TeddyBear' - teddy.get('firstName'); // 'Teddy' - ``` - - @method computed.oneWay - @for Ember - @param {String} dependentKey - @return {Ember.ComputedProperty} computed property which creates a - one way computed property to the original value for property. - */ - computed.oneWay = function(dependentKey) { - return alias(dependentKey).oneWay(); - }; - - /** - This is a more semantically meaningful alias of `computed.oneWay`, - whose name is somewhat ambiguous as to which direction the data flows. - - @method computed.reads - @for Ember - @param {String} dependentKey - @return {Ember.ComputedProperty} computed property which creates a - one way computed property to the original value for property. - */ - computed.reads = computed.oneWay; - - /** - Where `computed.oneWay` provides oneWay bindings, `computed.readOnly` provides - a readOnly one way binding. Very often when using `computed.oneWay` one does - not also want changes to propogate back up, as they will replace the value. - - This prevents the reverse flow, and also throws an exception when it occurs. - - Example - - ```javascript - var User = Ember.Object.extend({ - firstName: null, - lastName: null, - nickName: Ember.computed.readOnly('firstName') - }); - - var teddy = User.create({ - firstName: 'Teddy', - lastName: 'Zeenny' - }); - - teddy.get('nickName'); // 'Teddy' - teddy.set('nickName', 'TeddyBear'); // throws Exception - // throw new Ember.Error('Cannot Set: nickName on: ' );` - teddy.get('firstName'); // 'Teddy' - ``` - - @method computed.readOnly - @for Ember - @param {String} dependentKey - @return {Ember.ComputedProperty} computed property which creates a - one way computed property to the original value for property. - @since 1.5.0 - */ - computed.readOnly = function(dependentKey) { - return alias(dependentKey).readOnly(); - }; - /** - A computed property that acts like a standard getter and setter, - but returns the value at the provided `defaultPath` if the - property itself has not been set to a value - - Example - - ```javascript - var Hamster = Ember.Object.extend({ - wishList: Ember.computed.defaultTo('favoriteFood') - }); - - var hamster = Hamster.create({ favoriteFood: 'Banana' }); - - hamster.get('wishList'); // 'Banana' - hamster.set('wishList', 'More Unit Tests'); - hamster.get('wishList'); // 'More Unit Tests' - hamster.get('favoriteFood'); // 'Banana' - ``` - - @method computed.defaultTo - @for Ember - @param {String} defaultPath - @return {Ember.ComputedProperty} computed property which acts like - a standard getter and setter, but defaults to the value from `defaultPath`. - @deprecated Use `Ember.computed.oneWay` or custom CP with default instead. - */ - // ES6TODO: computed should have its own export path so you can do import {defaultTo} from computed - computed.defaultTo = function(defaultPath) { - return computed(function(key, newValue, cachedValue) { - Ember.deprecate('Usage of Ember.computed.defaultTo is deprecated, use `Ember.computed.oneWay` instead.'); - - if (arguments.length === 1) { - return get(this, defaultPath); - } - return newValue != null ? newValue : get(this, defaultPath); - }); - }; - - /** - Creates a new property that is an alias for another property - on an object. Calls to `get` or `set` this property behave as - though they were called on the original property, but also - print a deprecation warning. - - @method computed.deprecatingAlias - @for Ember - @param {String} dependentKey - @return {Ember.ComputedProperty} computed property which creates an - alias with a deprecation to the original value for property. - @since 1.7.0 - */ - computed.deprecatingAlias = function(dependentKey) { - return computed(dependentKey, function(key, value) { - Ember.deprecate('Usage of `' + key + '` is deprecated, use `' + dependentKey + '` instead.'); - - if (arguments.length > 1) { - set(this, dependentKey, value); - return value; - } else { - return get(this, dependentKey); - } - }); - }; - }); -enifed("ember-metal/core", - ["exports"], - function(__exports__) { - "use strict"; - /*globals Ember:true,Em:true,ENV,EmberENV,MetamorphENV:true */ - - /** - @module ember - @submodule ember-metal - */ - - /** - All Ember methods and functions are defined inside of this namespace. You - generally should not add new properties to this namespace as it may be - overwritten by future versions of Ember. - - You can also use the shorthand `Em` instead of `Ember`. - - Ember-Runtime is a framework that provides core functions for Ember including - cross-platform functions, support for property observing and objects. Its - focus is on small size and performance. You can use this in place of or - along-side other cross-platform libraries such as jQuery. - - The core Runtime framework is based on the jQuery API with a number of - performance optimizations. - - @class Ember - @static - @version 1.8.1 - */ - - if ('undefined' === typeof Ember) { - // Create core object. Make it act like an instance of Ember.Namespace so that - // objects assigned to it are given a sane string representation. - Ember = {}; - } - - // Default imports, exports and lookup to the global object; - var imports = Ember.imports = Ember.imports || this; - var exports = Ember.exports = Ember.exports || this; - var lookup = Ember.lookup = Ember.lookup || this; - - // aliases needed to keep minifiers from removing the global context - exports.Em = exports.Ember = Ember; - - // Make sure these are set whether Ember was already defined or not - - Ember.isNamespace = true; - - Ember.toString = function() { return "Ember"; }; - - - /** - @property VERSION - @type String - @default '1.8.1' - @static - */ - Ember.VERSION = '1.8.1'; - - /** - Standard environmental variables. You can define these in a global `EmberENV` - variable before loading Ember to control various configuration settings. - - For backwards compatibility with earlier versions of Ember the global `ENV` - variable will be used if `EmberENV` is not defined. - - @property ENV - @type Hash - */ - - if (Ember.ENV) { - // do nothing if Ember.ENV is already setup - } else if ('undefined' !== typeof EmberENV) { - Ember.ENV = EmberENV; - } else if('undefined' !== typeof ENV) { - Ember.ENV = ENV; - } else { - Ember.ENV = {}; - } - - Ember.config = Ember.config || {}; - - // We disable the RANGE API by default for performance reasons - if ('undefined' === typeof Ember.ENV.DISABLE_RANGE_API) { - Ember.ENV.DISABLE_RANGE_API = true; - } - - if ("undefined" === typeof MetamorphENV) { - exports.MetamorphENV = {}; - } - - MetamorphENV.DISABLE_RANGE_API = Ember.ENV.DISABLE_RANGE_API; - - /** - Hash of enabled Canary features. Add to this before creating your application. - - You can also define `ENV.FEATURES` if you need to enable features flagged at runtime. - - @class FEATURES - @namespace Ember - @static - @since 1.1.0 - */ - - Ember.FEATURES = Ember.ENV.FEATURES || {}; - - /** - Test that a feature is enabled. Parsed by Ember's build tools to leave - experimental features out of beta/stable builds. - - You can define the following configuration options: - - * `ENV.ENABLE_ALL_FEATURES` - force all features to be enabled. - * `ENV.ENABLE_OPTIONAL_FEATURES` - enable any features that have not been explicitly - enabled/disabled. - - @method isEnabled - @param {String} feature - @return {Boolean} - @for Ember.FEATURES - @since 1.1.0 - */ - - Ember.FEATURES.isEnabled = function(feature) { - var featureValue = Ember.FEATURES[feature]; - - if (Ember.ENV.ENABLE_ALL_FEATURES) { - return true; - } else if (featureValue === true || featureValue === false || featureValue === undefined) { - return featureValue; - } else if (Ember.ENV.ENABLE_OPTIONAL_FEATURES) { - return true; - } else { - return false; - } - }; - - // .......................................................... - // BOOTSTRAP - // - - /** - Determines whether Ember should enhance some built-in object prototypes to - provide a more friendly API. If enabled, a few methods will be added to - `Function`, `String`, and `Array`. `Object.prototype` will not be enhanced, - which is the one that causes most trouble for people. - - In general we recommend leaving this option set to true since it rarely - conflicts with other code. If you need to turn it off however, you can - define an `ENV.EXTEND_PROTOTYPES` config to disable it. - - @property EXTEND_PROTOTYPES - @type Boolean - @default true - @for Ember - */ - Ember.EXTEND_PROTOTYPES = Ember.ENV.EXTEND_PROTOTYPES; - - if (typeof Ember.EXTEND_PROTOTYPES === 'undefined') { - Ember.EXTEND_PROTOTYPES = true; - } - - /** - Determines whether Ember logs a full stack trace during deprecation warnings - - @property LOG_STACKTRACE_ON_DEPRECATION - @type Boolean - @default true - */ - Ember.LOG_STACKTRACE_ON_DEPRECATION = (Ember.ENV.LOG_STACKTRACE_ON_DEPRECATION !== false); - - /** - Determines whether Ember should add ECMAScript 5 shims to older browsers. - - @property SHIM_ES5 - @type Boolean - @default Ember.EXTEND_PROTOTYPES - */ - Ember.SHIM_ES5 = (Ember.ENV.SHIM_ES5 === false) ? false : Ember.EXTEND_PROTOTYPES; - - /** - Determines whether Ember logs info about version of used libraries - - @property LOG_VERSION - @type Boolean - @default true - */ - Ember.LOG_VERSION = (Ember.ENV.LOG_VERSION === false) ? false : true; - - /** - Empty function. Useful for some operations. Always returns `this`. - - @method K - @private - @return {Object} - */ - var K = function() { return this; }; - var K = K; - __exports__.K = K;Ember.K = K; - //TODO: ES6 GLOBL TODO - - // Stub out the methods defined by the ember-debug package in case it's not loaded - - if ('undefined' === typeof Ember.assert) { Ember.assert = Ember.K; } - if ('undefined' === typeof Ember.warn) { Ember.warn = Ember.K; } - if ('undefined' === typeof Ember.debug) { Ember.debug = Ember.K; } - if ('undefined' === typeof Ember.runInDebug) { Ember.runInDebug = Ember.K; } - if ('undefined' === typeof Ember.deprecate) { Ember.deprecate = Ember.K; } - if ('undefined' === typeof Ember.deprecateFunc) { - Ember.deprecateFunc = function(_, func) { return func; }; - } - - __exports__["default"] = Ember; - }); -enifed("ember-metal/dependent_keys", - ["ember-metal/platform","ember-metal/watching","exports"], - function(__dependency1__, __dependency2__, __exports__) { - // Remove "use strict"; from transpiled module until - // https://bugs.webkit.org/show_bug.cgi?id=138038 is fixed - // - // REMOVE_USE_STRICT: true - - var o_create = __dependency1__.create; - var watch = __dependency2__.watch; - var unwatch = __dependency2__.unwatch; - - /** - @module ember-metal - */ - - // .......................................................... - // DEPENDENT KEYS - // - - // data structure: - // meta.deps = { - // 'depKey': { - // 'keyName': count, - // } - // } - - /* - This function returns a map of unique dependencies for a - given object and key. - */ - function keysForDep(depsMeta, depKey) { - var keys = depsMeta[depKey]; - if (!keys) { - // if there are no dependencies yet for a the given key - // create a new empty list of dependencies for the key - keys = depsMeta[depKey] = {}; - } else if (!depsMeta.hasOwnProperty(depKey)) { - // otherwise if the dependency list is inherited from - // a superclass, clone the hash - keys = depsMeta[depKey] = o_create(keys); - } - return keys; - } - - function metaForDeps(meta) { - return keysForDep(meta, 'deps'); - } - - function addDependentKeys(desc, obj, keyName, meta) { - // the descriptor has a list of dependent keys, so - // add all of its dependent keys. - var depKeys = desc._dependentKeys, depsMeta, idx, len, depKey, keys; - if (!depKeys) return; - - depsMeta = metaForDeps(meta); - - for(idx = 0, len = depKeys.length; idx < len; idx++) { - depKey = depKeys[idx]; - // Lookup keys meta for depKey - keys = keysForDep(depsMeta, depKey); - // Increment the number of times depKey depends on keyName. - keys[keyName] = (keys[keyName] || 0) + 1; - // Watch the depKey - watch(obj, depKey, meta); - } - } - - __exports__.addDependentKeys = addDependentKeys;function removeDependentKeys(desc, obj, keyName, meta) { - // the descriptor has a list of dependent keys, so - // remove all of its dependent keys. - var depKeys = desc._dependentKeys, depsMeta, idx, len, depKey, keys; - if (!depKeys) return; - - depsMeta = metaForDeps(meta); - - for(idx = 0, len = depKeys.length; idx < len; idx++) { - depKey = depKeys[idx]; - // Lookup keys meta for depKey - keys = keysForDep(depsMeta, depKey); - // Decrement the number of times depKey depends on keyName. - keys[keyName] = (keys[keyName] || 0) - 1; - // Unwatch the depKey - unwatch(obj, depKey, meta); - } - } - - __exports__.removeDependentKeys = removeDependentKeys; - }); -enifed("ember-metal/deprecate_property", - ["ember-metal/core","ember-metal/platform","ember-metal/properties","ember-metal/property_get","ember-metal/property_set","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __exports__) { - "use strict"; - /** - @module ember-metal - */ - - var Ember = __dependency1__["default"]; - var hasPropertyAccessors = __dependency2__.hasPropertyAccessors; - var defineProperty = __dependency3__.defineProperty; - var get = __dependency4__.get; - var set = __dependency5__.set; - - - /** - Used internally to allow changing properties in a backwards compatible way, and print a helpful - deprecation warning. - - @method deprecateProperty - @param {Object} object The object to add the deprecated property to. - @param {String} deprecatedKey The property to add (and print deprecation warnings upon accessing). - @param {String} newKey The property that will be aliased. - @private - @since 1.7.0 - */ - - function deprecateProperty(object, deprecatedKey, newKey) { - function deprecate() { - Ember.deprecate('Usage of `' + deprecatedKey + '` is deprecated, use `' + newKey + '` instead.'); - } - - if (hasPropertyAccessors) { - defineProperty(object, deprecatedKey, { - configurable: true, - enumerable: false, - set: function(value) { deprecate(); set(this, newKey, value); }, - get: function() { deprecate(); return get(this, newKey); } - }); - } - } - - __exports__.deprecateProperty = deprecateProperty; - }); -enifed("ember-metal/dictionary", - ["ember-metal/platform","exports"], - function(__dependency1__, __exports__) { - "use strict"; - var create = __dependency1__.create; - - // the delete is meant to hint at runtimes that this object should remain in - // dictionary mode. This is clearly a runtime specific hack, but currently it - // appears worthwile in some usecases. Please note, these deletes do increase - // the cost of creation dramatically over a plain Object.create. And as this - // only makes sense for long-lived dictionaries that aren't instantiated often. - __exports__["default"] = function makeDictionary(parent) { - var dict = create(parent); - dict['_dict'] = null; - delete dict['_dict']; - return dict; - } - }); -enifed("ember-metal/enumerable_utils", - ["ember-metal/array","exports"], - function(__dependency1__, __exports__) { - "use strict"; - var _filter = __dependency1__.filter; - var a_forEach = __dependency1__.forEach; - var _indexOf = __dependency1__.indexOf; - var _map = __dependency1__.map; - - var splice = Array.prototype.splice; - - /** - * Defines some convenience methods for working with Enumerables. - * `Ember.EnumerableUtils` uses `Ember.ArrayPolyfills` when necessary. - * - * @class EnumerableUtils - * @namespace Ember - * @static - * */ - - /** - * Calls the map function on the passed object with a specified callback. This - * uses `Ember.ArrayPolyfill`'s-map method when necessary. - * - * @method map - * @param {Object} obj The object that should be mapped - * @param {Function} callback The callback to execute - * @param {Object} thisArg Value to use as this when executing *callback* - * - * @return {Array} An array of mapped values. - */ - function map(obj, callback, thisArg) { - return obj.map ? obj.map(callback, thisArg) : _map.call(obj, callback, thisArg); - } - - __exports__.map = map;/** - * Calls the forEach function on the passed object with a specified callback. This - * uses `Ember.ArrayPolyfill`'s-forEach method when necessary. - * - * @method forEach - * @param {Object} obj The object to call forEach on - * @param {Function} callback The callback to execute - * @param {Object} thisArg Value to use as this when executing *callback* - * - */ - function forEach(obj, callback, thisArg) { - return obj.forEach ? obj.forEach(callback, thisArg) : a_forEach.call(obj, callback, thisArg); - } - - __exports__.forEach = forEach;/** - * Calls the filter function on the passed object with a specified callback. This - * uses `Ember.ArrayPolyfill`'s-filter method when necessary. - * - * @method filter - * @param {Object} obj The object to call filter on - * @param {Function} callback The callback to execute - * @param {Object} thisArg Value to use as this when executing *callback* - * - * @return {Array} An array containing the filtered values - * @since 1.4.0 - */ - function filter(obj, callback, thisArg) { - return obj.filter ? obj.filter(callback, thisArg) : _filter.call(obj, callback, thisArg); - } - - __exports__.filter = filter;/** - * Calls the indexOf function on the passed object with a specified callback. This - * uses `Ember.ArrayPolyfill`'s-indexOf method when necessary. - * - * @method indexOf - * @param {Object} obj The object to call indexOn on - * @param {Function} callback The callback to execute - * @param {Object} index The index to start searching from - * - */ - function indexOf(obj, element, index) { - return obj.indexOf ? obj.indexOf(element, index) : _indexOf.call(obj, element, index); - } - - __exports__.indexOf = indexOf;/** - * Returns an array of indexes of the first occurrences of the passed elements - * on the passed object. - * - * ```javascript - * var array = [1, 2, 3, 4, 5]; - * Ember.EnumerableUtils.indexesOf(array, [2, 5]); // [1, 4] - * - * var fubar = "Fubarr"; - * Ember.EnumerableUtils.indexesOf(fubar, ['b', 'r']); // [2, 4] - * ``` - * - * @method indexesOf - * @param {Object} obj The object to check for element indexes - * @param {Array} elements The elements to search for on *obj* - * - * @return {Array} An array of indexes. - * - */ - function indexesOf(obj, elements) { - return elements === undefined ? [] : map(elements, function(item) { - return indexOf(obj, item); - }); - } - - __exports__.indexesOf = indexesOf;/** - * Adds an object to an array. If the array already includes the object this - * method has no effect. - * - * @method addObject - * @param {Array} array The array the passed item should be added to - * @param {Object} item The item to add to the passed array - * - * @return 'undefined' - */ - function addObject(array, item) { - var index = indexOf(array, item); - if (index === -1) { array.push(item); } - } - - __exports__.addObject = addObject;/** - * Removes an object from an array. If the array does not contain the passed - * object this method has no effect. - * - * @method removeObject - * @param {Array} array The array to remove the item from. - * @param {Object} item The item to remove from the passed array. - * - * @return 'undefined' - */ - function removeObject(array, item) { - var index = indexOf(array, item); - if (index !== -1) { array.splice(index, 1); } - } - - __exports__.removeObject = removeObject;function _replace(array, idx, amt, objects) { - var args = [].concat(objects); - var ret = []; - // https://code.google.com/p/chromium/issues/detail?id=56588 - var size = 60000; - var start = idx; - var ends = amt; - var count, chunk; - - while (args.length) { - count = ends > size ? size : ends; - if (count <= 0) { count = 0; } - - chunk = args.splice(0, size); - chunk = [start, count].concat(chunk); - - start += size; - ends -= count; - - ret = ret.concat(splice.apply(array, chunk)); - } - return ret; - } - - __exports__._replace = _replace;/** - * Replaces objects in an array with the passed objects. - * - * ```javascript - * var array = [1,2,3]; - * Ember.EnumerableUtils.replace(array, 1, 2, [4, 5]); // [1, 4, 5] - * - * var array = [1,2,3]; - * Ember.EnumerableUtils.replace(array, 1, 1, [4, 5]); // [1, 4, 5, 3] - * - * var array = [1,2,3]; - * Ember.EnumerableUtils.replace(array, 10, 1, [4, 5]); // [1, 2, 3, 4, 5] - * ``` - * - * @method replace - * @param {Array} array The array the objects should be inserted into. - * @param {Number} idx Starting index in the array to replace. If *idx* >= - * length, then append to the end of the array. - * @param {Number} amt Number of elements that should be removed from the array, - * starting at *idx* - * @param {Array} objects An array of zero or more objects that should be - * inserted into the array at *idx* - * - * @return {Array} The modified array. - */ - function replace(array, idx, amt, objects) { - if (array.replace) { - return array.replace(idx, amt, objects); - } else { - return _replace(array, idx, amt, objects); - } - } - - __exports__.replace = replace;/** - * Calculates the intersection of two arrays. This method returns a new array - * filled with the records that the two passed arrays share with each other. - * If there is no intersection, an empty array will be returned. - * - * ```javascript - * var array1 = [1, 2, 3, 4, 5]; - * var array2 = [1, 3, 5, 6, 7]; - * - * Ember.EnumerableUtils.intersection(array1, array2); // [1, 3, 5] - * - * var array1 = [1, 2, 3]; - * var array2 = [4, 5, 6]; - * - * Ember.EnumerableUtils.intersection(array1, array2); // [] - * ``` - * - * @method intersection - * @param {Array} array1 The first array - * @param {Array} array2 The second array - * - * @return {Array} The intersection of the two passed arrays. - */ - function intersection(array1, array2) { - var result = []; - forEach(array1, function(element) { - if (indexOf(array2, element) >= 0) { - result.push(element); - } - }); - - return result; - } - - __exports__.intersection = intersection;// TODO: this only exists to maintain the existing api, as we move forward it - // should only be part of the "global build" via some shim - __exports__["default"] = { - _replace: _replace, - addObject: addObject, - filter: filter, - forEach: forEach, - indexOf: indexOf, - indexesOf: indexesOf, - intersection: intersection, - map: map, - removeObject: removeObject, - replace: replace - }; - }); -enifed("ember-metal/error", - ["ember-metal/platform","exports"], - function(__dependency1__, __exports__) { - "use strict"; - var create = __dependency1__.create; - - var errorProps = [ - 'description', - 'fileName', - 'lineNumber', - 'message', - 'name', - 'number', - 'stack' - ]; - - /** - A subclass of the JavaScript Error object for use in Ember. - - @class Error - @namespace Ember - @extends Error - @constructor - */ - function EmberError() { - var tmp = Error.apply(this, arguments); - - // Adds a `stack` property to the given error object that will yield the - // stack trace at the time captureStackTrace was called. - // When collecting the stack trace all frames above the topmost call - // to this function, including that call, will be left out of the - // stack trace. - // This is useful because we can hide Ember implementation details - // that are not very helpful for the user. - if (Error.captureStackTrace) { - Error.captureStackTrace(this, Ember.Error); - } - // Unfortunately errors are not enumerable in Chrome (at least), so `for prop in tmp` doesn't work. - for (var idx = 0; idx < errorProps.length; idx++) { - this[errorProps[idx]] = tmp[errorProps[idx]]; - } - } - - EmberError.prototype = create(Error.prototype); - - __exports__["default"] = EmberError; - }); -enifed("ember-metal/events", - ["ember-metal/core","ember-metal/utils","ember-metal/platform","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __exports__) { - // Remove "use strict"; from transpiled module until - // https://bugs.webkit.org/show_bug.cgi?id=138038 is fixed - // - // REMOVE_USE_STRICT: true - - /** - @module ember-metal - */ - var Ember = __dependency1__["default"]; - var meta = __dependency2__.meta; - var tryFinally = __dependency2__.tryFinally; - var apply = __dependency2__.apply; - var applyStr = __dependency2__.applyStr; - var create = __dependency3__.create; - - var a_slice = [].slice; - var metaFor = meta; - - /* listener flags */ - var ONCE = 1; - var SUSPENDED = 2; - - - /* - The event system uses a series of nested hashes to store listeners on an - object. When a listener is registered, or when an event arrives, these - hashes are consulted to determine which target and action pair to invoke. - - The hashes are stored in the object's meta hash, and look like this: - - // Object's meta hash - { - listeners: { // variable name: `listenerSet` - "foo:changed": [ // variable name: `actions` - target, method, flags - ] - } - } - - */ - - function indexOf(array, target, method) { - var index = -1; - // hashes are added to the end of the event array - // so it makes sense to start searching at the end - // of the array and search in reverse - for (var i = array.length - 3 ; i >=0; i -= 3) { - if (target === array[i] && method === array[i + 1]) { - index = i; break; - } - } - return index; - } - - function actionsFor(obj, eventName) { - var meta = metaFor(obj, true); - var actions; - - if (!meta.listeners) { meta.listeners = {}; } - - if (!meta.hasOwnProperty('listeners')) { - // setup inherited copy of the listeners object - meta.listeners = create(meta.listeners); - } - - actions = meta.listeners[eventName]; - - // if there are actions, but the eventName doesn't exist in our listeners, then copy them from the prototype - if (actions && !meta.listeners.hasOwnProperty(eventName)) { - actions = meta.listeners[eventName] = meta.listeners[eventName].slice(); - } else if (!actions) { - actions = meta.listeners[eventName] = []; - } - - return actions; - } - - function listenersUnion(obj, eventName, otherActions) { - var meta = obj['__ember_meta__']; - var actions = meta && meta.listeners && meta.listeners[eventName]; - - if (!actions) { return; } - for (var i = actions.length - 3; i >= 0; i -= 3) { - var target = actions[i]; - var method = actions[i+1]; - var flags = actions[i+2]; - var actionIndex = indexOf(otherActions, target, method); - - if (actionIndex === -1) { - otherActions.push(target, method, flags); - } - } - } - - __exports__.listenersUnion = listenersUnion;function listenersDiff(obj, eventName, otherActions) { - var meta = obj['__ember_meta__']; - var actions = meta && meta.listeners && meta.listeners[eventName]; - var diffActions = []; - - if (!actions) { return; } - for (var i = actions.length - 3; i >= 0; i -= 3) { - var target = actions[i]; - var method = actions[i+1]; - var flags = actions[i+2]; - var actionIndex = indexOf(otherActions, target, method); - - if (actionIndex !== -1) { continue; } - - otherActions.push(target, method, flags); - diffActions.push(target, method, flags); - } - - return diffActions; - } - - __exports__.listenersDiff = listenersDiff;/** - Add an event listener - - @method addListener - @for Ember - @param obj - @param {String} eventName - @param {Object|Function} targetOrMethod A target object or a function - @param {Function|String} method A function or the name of a function to be called on `target` - @param {Boolean} once A flag whether a function should only be called once - */ - function addListener(obj, eventName, target, method, once) { - Ember.assert("You must pass at least an object and event name to Ember.addListener", !!obj && !!eventName); - - if (!method && 'function' === typeof target) { - method = target; - target = null; - } - - var actions = actionsFor(obj, eventName); - var actionIndex = indexOf(actions, target, method); - var flags = 0; - - if (once) flags |= ONCE; - - if (actionIndex !== -1) { return; } - - actions.push(target, method, flags); - - if ('function' === typeof obj.didAddListener) { - obj.didAddListener(eventName, target, method); - } - } - - __exports__.addListener = addListener;/** - Remove an event listener - - Arguments should match those passed to `Ember.addListener`. - - @method removeListener - @for Ember - @param obj - @param {String} eventName - @param {Object|Function} targetOrMethod A target object or a function - @param {Function|String} method A function or the name of a function to be called on `target` - */ - function removeListener(obj, eventName, target, method) { - Ember.assert("You must pass at least an object and event name to Ember.removeListener", !!obj && !!eventName); - - if (!method && 'function' === typeof target) { - method = target; - target = null; - } - - function _removeListener(target, method) { - var actions = actionsFor(obj, eventName); - var actionIndex = indexOf(actions, target, method); - - // action doesn't exist, give up silently - if (actionIndex === -1) { return; } - - actions.splice(actionIndex, 3); - - if ('function' === typeof obj.didRemoveListener) { - obj.didRemoveListener(eventName, target, method); - } - } - - if (method) { - _removeListener(target, method); - } else { - var meta = obj['__ember_meta__']; - var actions = meta && meta.listeners && meta.listeners[eventName]; - - if (!actions) { return; } - for (var i = actions.length - 3; i >= 0; i -= 3) { - _removeListener(actions[i], actions[i+1]); - } - } - } - - /** - Suspend listener during callback. - - This should only be used by the target of the event listener - when it is taking an action that would cause the event, e.g. - an object might suspend its property change listener while it is - setting that property. - - @method suspendListener - @for Ember - - @private - @param obj - @param {String} eventName - @param {Object|Function} targetOrMethod A target object or a function - @param {Function|String} method A function or the name of a function to be called on `target` - @param {Function} callback - */ - function suspendListener(obj, eventName, target, method, callback) { - if (!method && 'function' === typeof target) { - method = target; - target = null; - } - - var actions = actionsFor(obj, eventName); - var actionIndex = indexOf(actions, target, method); - - if (actionIndex !== -1) { - actions[actionIndex+2] |= SUSPENDED; // mark the action as suspended - } - - function tryable() { return callback.call(target); } - function finalizer() { if (actionIndex !== -1) { actions[actionIndex+2] &= ~SUSPENDED; } } - - return tryFinally(tryable, finalizer); - } - - __exports__.suspendListener = suspendListener;/** - Suspends multiple listeners during a callback. - - @method suspendListeners - @for Ember - - @private - @param obj - @param {Array} eventName Array of event names - @param {Object|Function} targetOrMethod A target object or a function - @param {Function|String} method A function or the name of a function to be called on `target` - @param {Function} callback - */ - function suspendListeners(obj, eventNames, target, method, callback) { - if (!method && 'function' === typeof target) { - method = target; - target = null; - } - - var suspendedActions = []; - var actionsList = []; - var eventName, actions, i, l; - - for (i=0, l=eventNames.length; i= 0; i -= 3) { // looping in reverse for once listeners - var target = actions[i], method = actions[i+1], flags = actions[i+2]; - if (!method) { continue; } - if (flags & SUSPENDED) { continue; } - if (flags & ONCE) { removeListener(obj, eventName, target, method); } - if (!target) { target = obj; } - if ('string' === typeof method) { - if (params) { - applyStr(target, method, params); - } else { - target[method](); - } - } else { - if (params) { - apply(target, method, params); - } else { - method.call(target); - } - } - } - return true; - } - - __exports__.sendEvent = sendEvent;/** - @private - @method hasListeners - @for Ember - @param obj - @param {String} eventName - */ - function hasListeners(obj, eventName) { - var meta = obj['__ember_meta__']; - var actions = meta && meta.listeners && meta.listeners[eventName]; - - return !!(actions && actions.length); - } - - __exports__.hasListeners = hasListeners;/** - @private - @method listenersFor - @for Ember - @param obj - @param {String} eventName - */ - function listenersFor(obj, eventName) { - var ret = []; - var meta = obj['__ember_meta__']; - var actions = meta && meta.listeners && meta.listeners[eventName]; - - if (!actions) { return ret; } - - for (var i = 0, l = actions.length; i < l; i += 3) { - var target = actions[i]; - var method = actions[i+1]; - ret.push([target, method]); - } - - return ret; - } - - __exports__.listenersFor = listenersFor;/** - Define a property as a function that should be executed when - a specified event or events are triggered. - - - ``` javascript - var Job = Ember.Object.extend({ - logCompleted: Ember.on('completed', function() { - console.log('Job completed!'); - }) - }); - - var job = Job.create(); - - Ember.sendEvent(job, 'completed'); // Logs 'Job completed!' - ``` - - @method on - @for Ember - @param {String} eventNames* - @param {Function} func - @return func - */ - function on(){ - var func = a_slice.call(arguments, -1)[0]; - var events = a_slice.call(arguments, 0, -1); - func.__ember_listens__ = events; - return func; - } - - __exports__.on = on;__exports__.removeListener = removeListener; - }); -enifed("ember-metal/expand_properties", - ["ember-metal/core","ember-metal/error","ember-metal/enumerable_utils","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __exports__) { - "use strict"; - var Ember = __dependency1__["default"]; - var EmberError = __dependency2__["default"]; - var forEach = __dependency3__.forEach; - - /** - @module ember-metal - */ - - var BRACE_EXPANSION = /^((?:[^\.]*\.)*)\{(.*)\}$/; - var SPLIT_REGEX = /\{|\}/; - - /** - Expands `pattern`, invoking `callback` for each expansion. - - The only pattern supported is brace-expansion, anything else will be passed - once to `callback` directly. - - Example - - ```js - function echo(arg){ console.log(arg); } - - Ember.expandProperties('foo.bar', echo); //=> 'foo.bar' - Ember.expandProperties('{foo,bar}', echo); //=> 'foo', 'bar' - Ember.expandProperties('foo.{bar,baz}', echo); //=> 'foo.bar', 'foo.baz' - Ember.expandProperties('{foo,bar}.baz', echo); //=> '{foo,bar}.baz' - Ember.expandProperties('foo.{bar,baz}.@each', echo) //=> 'foo.bar.@each', 'foo.baz.@each' - Ember.expandProperties('{foo,bar}.{spam,eggs}', echo) //=> 'foo.spam', 'foo.eggs', 'bar.spam', 'bar.eggs' - Ember.expandProperties('{foo}.bar.{baz}') //=> 'foo.bar.baz' - ``` - - @method - @private - @param {String} pattern The property pattern to expand. - @param {Function} callback The callback to invoke. It is invoked once per - expansion, and is passed the expansion. - */ - __exports__["default"] = function expandProperties(pattern, callback) { - if (pattern.indexOf(' ') > -1) { - throw new EmberError('Brace expanded properties cannot contain spaces, ' + - 'e.g. `user.{firstName, lastName}` should be `user.{firstName,lastName}`'); - } - - - return newExpandProperties(pattern, callback); - } - - function oldExpandProperties(pattern, callback) { - var match, prefix, list; - - if (match = BRACE_EXPANSION.exec(pattern)) { - prefix = match[1]; - list = match[2]; - - forEach(list.split(','), function (suffix) { - callback(prefix + suffix); - }); - } else { - callback(pattern); - } - } - - function newExpandProperties(pattern, callback) { - if ('string' === Ember.typeOf(pattern)) { - var parts = pattern.split(SPLIT_REGEX); - var properties = [parts]; - - forEach(parts, function(part, index) { - if (part.indexOf(',') >= 0) { - properties = duplicateAndReplace(properties, part.split(','), index); - } - }); - - forEach(properties, function(property) { - callback(property.join('')); - }); - } else { - callback(pattern); - } - } - - function duplicateAndReplace(properties, currentParts, index) { - var all = []; - - forEach(properties, function(property) { - forEach(currentParts, function(part) { - var current = property.slice(0); - current[index] = part; - all.push(current); - }); - }); - - return all; - } - }); -enifed("ember-metal/get_properties", - ["ember-metal/property_get","ember-metal/utils","exports"], - function(__dependency1__, __dependency2__, __exports__) { - "use strict"; - var get = __dependency1__.get; - var typeOf = __dependency2__.typeOf; - - /** - To get multiple properties at once, call `Ember.getProperties` - with an object followed by a list of strings or an array: - - ```javascript - Ember.getProperties(record, 'firstName', 'lastName', 'zipCode'); - // { firstName: 'John', lastName: 'Doe', zipCode: '10011' } - ``` - - is equivalent to: - - ```javascript - Ember.getProperties(record, ['firstName', 'lastName', 'zipCode']); - // { firstName: 'John', lastName: 'Doe', zipCode: '10011' } - ``` - - @method getProperties - @param obj - @param {String...|Array} list of keys to get - @return {Hash} - */ - __exports__["default"] = function getProperties(obj) { - var ret = {}; - var propertyNames = arguments; - var i = 1; - - if (arguments.length === 2 && typeOf(arguments[1]) === 'array') { - i = 0; - propertyNames = arguments[1]; - } - for(var len = propertyNames.length; i < len; i++) { - ret[propertyNames[i]] = get(obj, propertyNames[i]); - } - return ret; - } - }); -enifed("ember-metal/instrumentation", - ["ember-metal/core","ember-metal/utils","exports"], - function(__dependency1__, __dependency2__, __exports__) { - "use strict"; - var Ember = __dependency1__["default"]; - var tryCatchFinally = __dependency2__.tryCatchFinally; - - /** - The purpose of the Ember Instrumentation module is - to provide efficient, general-purpose instrumentation - for Ember. - - Subscribe to a listener by using `Ember.subscribe`: - - ```javascript - Ember.subscribe("render", { - before: function(name, timestamp, payload) { - - }, - - after: function(name, timestamp, payload) { - - } - }); - ``` - - If you return a value from the `before` callback, that same - value will be passed as a fourth parameter to the `after` - callback. - - Instrument a block of code by using `Ember.instrument`: - - ```javascript - Ember.instrument("render.handlebars", payload, function() { - // rendering logic - }, binding); - ``` - - Event names passed to `Ember.instrument` are namespaced - by periods, from more general to more specific. Subscribers - can listen for events by whatever level of granularity they - are interested in. - - In the above example, the event is `render.handlebars`, - and the subscriber listened for all events beginning with - `render`. It would receive callbacks for events named - `render`, `render.handlebars`, `render.container`, or - even `render.handlebars.layout`. - - @class Instrumentation - @namespace Ember - @static - */ - var subscribers = []; - __exports__.subscribers = subscribers;var cache = {}; - - var populateListeners = function(name) { - var listeners = []; - var subscriber; - - for (var i=0, l=subscribers.length; i -1) { - list.splice(index, 1); - } - this.size = list.length; - return true; - } else { - return false; - } - }, - - /** - @method isEmpty - @return {Boolean} - */ - isEmpty: function() { - return this.size === 0; - }, - - /** - @method has - @param obj - @return {Boolean} - */ - has: function(obj) { - if (this.size === 0) { return false; } - - var guid = guidFor(obj); - var presenceSet = this.presenceSet; - - return presenceSet[guid] === true; - }, - - /** - @method forEach - @param {Function} fn - @param self - */ - forEach: function(fn /*, thisArg*/) { - if (typeof fn !== 'function') { - missingFunction(fn); - } - - if (this.size === 0) { return; } - - var list = this.list; - var length = arguments.length; - var i; - - if (length === 2) { - for (i = 0; i < list.length; i++) { - fn.call(arguments[1], list[i]); - } - } else { - for (i = 0; i < list.length; i++) { - fn(list[i]); - } - } - }, - - /** - @method toArray - @return {Array} - */ - toArray: function() { - return this.list.slice(); - }, - - /** - @method copy - @return {Ember.OrderedSet} - */ - copy: function() { - var Constructor = this.constructor; - var set = new Constructor(); - - set._silenceRemoveDeprecation = this._silenceRemoveDeprecation; - set.presenceSet = copyNull(this.presenceSet); - set.list = this.toArray(); - set.size = this.size; - - return set; - } - }; - - deprecateProperty(OrderedSet.prototype, 'length', 'size'); - - /** - A Map stores values indexed by keys. Unlike JavaScript's - default Objects, the keys of a Map can be any JavaScript - object. - - Internally, a Map has two data structures: - - 1. `keys`: an OrderedSet of all of the existing keys - 2. `values`: a JavaScript Object indexed by the `Ember.guidFor(key)` - - When a key/value pair is added for the first time, we - add the key to the `keys` OrderedSet, and create or - replace an entry in `values`. When an entry is deleted, - we delete its entry in `keys` and `values`. - - @class Map - @namespace Ember - @private - @constructor - */ - function Map() { - if (this instanceof this.constructor) { - this.keys = OrderedSet.create(); - this.keys._silenceRemoveDeprecation = true; - this.values = create(null); - this.size = 0; - } else { - missingNew("OrderedSet"); - } - } - - Ember.Map = Map; - - /** - @method create - @static - */ - Map.create = function() { - var Constructor = this; - return new Constructor(); - }; - - Map.prototype = { - constructor: Map, - - /** - This property will change as the number of objects in the map changes. - - @property size - @type number - @default 0 - */ - size: 0, - - /** - Retrieve the value associated with a given key. - - @method get - @param {*} key - @return {*} the value associated with the key, or `undefined` - */ - get: function(key) { - if (this.size === 0) { return; } - - var values = this.values; - var guid = guidFor(key); - - return values[guid]; - }, - - /** - Adds a value to the map. If a value for the given key has already been - provided, the new value will replace the old value. - - @method set - @param {*} key - @param {*} value - @return {Ember.Map} - */ - set: function(key, value) { - var keys = this.keys; - var values = this.values; - var guid = guidFor(key); - - // ensure we don't store -0 - var k = key === -0 ? 0 : key; - - keys.add(k, guid); - - values[guid] = value; - - this.size = keys.size; - - return this; - }, - - /** - @deprecated see delete - Removes a value from the map for an associated key. - - @method remove - @param {*} key - @return {Boolean} true if an item was removed, false otherwise - */ - remove: function(key) { - Ember.deprecate('Calling `Map.prototype.remove` has been deprecated, please use `Map.prototype.delete` instead.'); - - return this["delete"](key); - }, - - /** - Removes a value from the map for an associated key. - - @method delete - @param {*} key - @return {Boolean} true if an item was removed, false otherwise - */ - "delete": function(key) { - if (this.size === 0) { return false; } - // don't use ES6 "delete" because it will be annoying - // to use in browsers that are not ES6 friendly; - var keys = this.keys; - var values = this.values; - var guid = guidFor(key); - - if (keys["delete"](key, guid)) { - delete values[guid]; - this.size = keys.size; - return true; - } else { - return false; - } - }, - - /** - Check whether a key is present. - - @method has - @param {*} key - @return {Boolean} true if the item was present, false otherwise - */ - has: function(key) { - return this.keys.has(key); - }, - - /** - Iterate over all the keys and values. Calls the function once - for each key, passing in the key and value, in that order. - - The keys are guaranteed to be iterated over in insertion order. - - @method forEach - @param {Function} callback - @param {*} self if passed, the `this` value inside the - callback. By default, `this` is the map. - */ - forEach: function(callback /*, thisArg*/) { - if (typeof callback !== 'function') { - missingFunction(callback); - } - - if (this.size === 0) { return; } - - var length = arguments.length; - var map = this; - var cb, thisArg; - - if (length === 2) { - thisArg = arguments[1]; - cb = function(key) { - callback.call(thisArg, map.get(key), key); - }; - } else { - cb = function(key) { - callback(map.get(key), key); - }; - } - - this.keys.forEach(cb); - }, - - /** - @method clear - */ - clear: function() { - this.keys.clear(); - this.values = create(null); - this.size = 0; - }, - - /** - @method copy - @return {Ember.Map} - */ - copy: function() { - return copyMap(this, new Map()); - } - }; - - deprecateProperty(Map.prototype, 'length', 'size'); - - /** - @class MapWithDefault - @namespace Ember - @extends Ember.Map - @private - @constructor - @param [options] - @param {*} [options.defaultValue] - */ - function MapWithDefault(options) { - this._super$constructor(); - this.defaultValue = options.defaultValue; - } - - /** - @method create - @static - @param [options] - @param {*} [options.defaultValue] - @return {Ember.MapWithDefault|Ember.Map} If options are passed, returns - `Ember.MapWithDefault` otherwise returns `Ember.Map` - */ - MapWithDefault.create = function(options) { - if (options) { - return new MapWithDefault(options); - } else { - return new Map(); - } - }; - - MapWithDefault.prototype = create(Map.prototype); - MapWithDefault.prototype.constructor = MapWithDefault; - MapWithDefault.prototype._super$constructor = Map; - MapWithDefault.prototype._super$get = Map.prototype.get; - - /** - Retrieve the value associated with a given key. - - @method get - @param {*} key - @return {*} the value associated with the key, or the default value - */ - MapWithDefault.prototype.get = function(key) { - var hasValue = this.has(key); - - if (hasValue) { - return this._super$get(key); - } else { - var defaultValue = this.defaultValue(key); - this.set(key, defaultValue); - return defaultValue; - } - }; - - /** - @method copy - @return {Ember.MapWithDefault} - */ - MapWithDefault.prototype.copy = function() { - var Constructor = this.constructor; - return copyMap(this, new Constructor({ - defaultValue: this.defaultValue - })); - }; - - __exports__["default"] = Map; - - __exports__.OrderedSet = OrderedSet; - __exports__.Map = Map; - __exports__.MapWithDefault = MapWithDefault; - }); -enifed("ember-metal/merge", - ["ember-metal/keys","exports"], - function(__dependency1__, __exports__) { - "use strict"; - var keys = __dependency1__["default"]; - - /** - Merge the contents of two objects together into the first object. - - ```javascript - Ember.merge({first: 'Tom'}, {last: 'Dale'}); // {first: 'Tom', last: 'Dale'} - var a = {first: 'Yehuda'}, b = {last: 'Katz'}; - Ember.merge(a, b); // a == {first: 'Yehuda', last: 'Katz'}, b == {last: 'Katz'} - ``` - - @method merge - @for Ember - @param {Object} original The object to merge into - @param {Object} updates The object to copy properties from - @return {Object} - */ - __exports__["default"] = function merge(original, updates) { - if (!updates || typeof updates !== 'object') { - return original; - } - - var props = keys(updates); - var prop; - var length = props.length; - - for (var i = 0; i < length; i++) { - prop = props[i]; - original[prop] = updates[prop]; - } - - return original; - } - }); -enifed("ember-metal/mixin", - ["ember-metal/core","ember-metal/merge","ember-metal/array","ember-metal/platform","ember-metal/utils","ember-metal/expand_properties","ember-metal/properties","ember-metal/computed","ember-metal/binding","ember-metal/observer","ember-metal/events","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __dependency11__, __exports__) { - // Remove "use strict"; from transpiled module until - // https://bugs.webkit.org/show_bug.cgi?id=138038 is fixed - // - // REMOVE_USE_STRICT: true - - /** - @module ember - @submodule ember-metal - */ - - var Ember = __dependency1__["default"]; - // warn, assert, wrap, et; - var merge = __dependency2__["default"]; - var map = __dependency3__.map; - var indexOf = __dependency3__.indexOf; - var forEach = __dependency3__.forEach; - var create = __dependency4__.create; - var guidFor = __dependency5__.guidFor; - var meta = __dependency5__.meta; - var wrap = __dependency5__.wrap; - var makeArray = __dependency5__.makeArray; - var apply = __dependency5__.apply; - var isArray = __dependency5__.isArray; - var expandProperties = __dependency6__["default"]; - var Descriptor = __dependency7__.Descriptor; - var defineProperty = __dependency7__.defineProperty; - var ComputedProperty = __dependency8__.ComputedProperty; - var Binding = __dependency9__.Binding; - var addObserver = __dependency10__.addObserver; - var removeObserver = __dependency10__.removeObserver; - var addBeforeObserver = __dependency10__.addBeforeObserver; - var removeBeforeObserver = __dependency10__.removeBeforeObserver; - var addListener = __dependency11__.addListener; - var removeListener = __dependency11__.removeListener; - - var REQUIRED; - var a_map = map; - var a_indexOf = indexOf; - var a_forEach = forEach; - var a_slice = [].slice; - var o_create = create; - var metaFor = meta; - - function superFunction(){ - var func = this.__nextSuper; - var ret; - if (func) { - var args = new Array(arguments.length); - for (var i = 0, l = args.length; i < l; i++) { - args[i] = arguments[i]; - } - this.__nextSuper = null; - ret = apply(this, func, args); - this.__nextSuper = func; - } - return ret; - } - - function mixinsMeta(obj) { - var m = metaFor(obj, true); - var ret = m.mixins; - if (!ret) { - ret = m.mixins = {}; - } else if (!m.hasOwnProperty('mixins')) { - ret = m.mixins = o_create(ret); - } - return ret; - } - - function initMixin(mixin, args) { - if (args && args.length > 0) { - mixin.mixins = a_map.call(args, function(x) { - if (x instanceof Mixin) { return x; } - - // Note: Manually setup a primitive mixin here. This is the only - // way to actually get a primitive mixin. This way normal creation - // of mixins will give you combined mixins... - var mixin = new Mixin(); - mixin.properties = x; - return mixin; - }); - } - return mixin; - } - - function isMethod(obj) { - return 'function' === typeof obj && - obj.isMethod !== false && - obj !== Boolean && obj !== Object && obj !== Number && obj !== Array && obj !== Date && obj !== String; - } - - var CONTINUE = {}; - - function mixinProperties(mixinsMeta, mixin) { - var guid; - - if (mixin instanceof Mixin) { - guid = guidFor(mixin); - if (mixinsMeta[guid]) { return CONTINUE; } - mixinsMeta[guid] = mixin; - return mixin.properties; - } else { - return mixin; // apply anonymous mixin properties - } - } - - function concatenatedMixinProperties(concatProp, props, values, base) { - var concats; - - // reset before adding each new mixin to pickup concats from previous - concats = values[concatProp] || base[concatProp]; - if (props[concatProp]) { - concats = concats ? concats.concat(props[concatProp]) : props[concatProp]; - } - - return concats; - } - - function giveDescriptorSuper(meta, key, property, values, descs) { - var superProperty; - - // Computed properties override methods, and do not call super to them - if (values[key] === undefined) { - // Find the original descriptor in a parent mixin - superProperty = descs[key]; - } - - // If we didn't find the original descriptor in a parent mixin, find - // it on the original object. - superProperty = superProperty || meta.descs[key]; - - if (superProperty === undefined || !(superProperty instanceof ComputedProperty)) { - return property; - } - - // Since multiple mixins may inherit from the same parent, we need - // to clone the computed property so that other mixins do not receive - // the wrapped version. - property = o_create(property); - property.func = wrap(property.func, superProperty.func); - - return property; - } - - function giveMethodSuper(obj, key, method, values, descs) { - var superMethod; - - // Methods overwrite computed properties, and do not call super to them. - if (descs[key] === undefined) { - // Find the original method in a parent mixin - superMethod = values[key]; - } - - // If we didn't find the original value in a parent mixin, find it in - // the original object - superMethod = superMethod || obj[key]; - - // Only wrap the new method if the original method was a function - if (superMethod === undefined || 'function' !== typeof superMethod) { - return method; - } - - return wrap(method, superMethod); - } - - function applyConcatenatedProperties(obj, key, value, values) { - var baseValue = values[key] || obj[key]; - - if (baseValue) { - if ('function' === typeof baseValue.concat) { - return baseValue.concat(value); - } else { - return makeArray(baseValue).concat(value); - } - } else { - return makeArray(value); - } - } - - function applyMergedProperties(obj, key, value, values) { - var baseValue = values[key] || obj[key]; - - Ember.assert("You passed in `" + JSON.stringify(value) + "` as the value for `" + key + - "` but `" + key + "` cannot be an Array", !isArray(value)); - - if (!baseValue) { return value; } - - var newBase = merge({}, baseValue); - var hasFunction = false; - - for (var prop in value) { - if (!value.hasOwnProperty(prop)) { continue; } - - var propValue = value[prop]; - if (isMethod(propValue)) { - // TODO: support for Computed Properties, etc? - hasFunction = true; - newBase[prop] = giveMethodSuper(obj, prop, propValue, baseValue, {}); - } else { - newBase[prop] = propValue; - } - } - - if (hasFunction) { - newBase._super = superFunction; - } - - return newBase; - } - - function addNormalizedProperty(base, key, value, meta, descs, values, concats, mergings) { - if (value instanceof Descriptor) { - if (value === REQUIRED && descs[key]) { return CONTINUE; } - - // Wrap descriptor function to implement - // __nextSuper() if needed - if (value.func) { - value = giveDescriptorSuper(meta, key, value, values, descs); - } - - descs[key] = value; - values[key] = undefined; - } else { - if ((concats && a_indexOf.call(concats, key) >= 0) || - key === 'concatenatedProperties' || - key === 'mergedProperties') { - value = applyConcatenatedProperties(base, key, value, values); - } else if ((mergings && a_indexOf.call(mergings, key) >= 0)) { - value = applyMergedProperties(base, key, value, values); - } else if (isMethod(value)) { - value = giveMethodSuper(base, key, value, values, descs); - } - - descs[key] = undefined; - values[key] = value; - } - } - - function mergeMixins(mixins, m, descs, values, base, keys) { - var mixin, props, key, concats, mergings, meta; - - function removeKeys(keyName) { - delete descs[keyName]; - delete values[keyName]; - } - - for(var i=0, l=mixins.length; i= 0) { - if (_detect(mixins[loc], targetMixin, seen)) { return true; } - } - return false; - } - - /** - @method detect - @param obj - @return {Boolean} - */ - MixinPrototype.detect = function(obj) { - if (!obj) { return false; } - if (obj instanceof Mixin) { return _detect(obj, this, {}); } - var m = obj['__ember_meta__']; - var mixins = m && m.mixins; - if (mixins) { - return !!mixins[guidFor(this)]; - } - return false; - }; - - MixinPrototype.without = function() { - var ret = new Mixin(this); - ret._without = a_slice.call(arguments); - return ret; - }; - - function _keys(ret, mixin, seen) { - if (seen[guidFor(mixin)]) { return; } - seen[guidFor(mixin)] = true; - - if (mixin.properties) { - var props = mixin.properties; - for (var key in props) { - if (props.hasOwnProperty(key)) { ret[key] = true; } - } - } else if (mixin.mixins) { - a_forEach.call(mixin.mixins, function(x) { _keys(ret, x, seen); }); - } - } - - MixinPrototype.keys = function() { - var keys = {}; - var seen = {}; - var ret = []; - _keys(keys, this, seen); - for(var key in keys) { - if (keys.hasOwnProperty(key)) { ret.push(key); } - } - return ret; - }; - - // returns the mixins currently applied to the specified object - // TODO: Make Ember.mixin - Mixin.mixins = function(obj) { - var m = obj['__ember_meta__']; - var mixins = m && m.mixins; - var ret = []; - - if (!mixins) { return ret; } - - for (var key in mixins) { - var mixin = mixins[key]; - - // skip primitive mixins since these are always anonymous - if (!mixin.properties) { ret.push(mixin); } - } - - return ret; - }; - - REQUIRED = new Descriptor(); - REQUIRED.toString = function() { return '(Required Property)'; }; - - /** - Denotes a required property for a mixin - - @method required - @for Ember - */ - function required() { - return REQUIRED; - } - - __exports__.required = required;function Alias(methodName) { - this.methodName = methodName; - } - - Alias.prototype = new Descriptor(); - - /** - Makes a method available via an additional name. - - ```javascript - App.Person = Ember.Object.extend({ - name: function() { - return 'Tomhuda Katzdale'; - }, - moniker: Ember.aliasMethod('name') - }); - - var goodGuy = App.Person.create(); - - goodGuy.name(); // 'Tomhuda Katzdale' - goodGuy.moniker(); // 'Tomhuda Katzdale' - ``` - - @method aliasMethod - @for Ember - @param {String} methodName name of the method to alias - @return {Ember.Descriptor} - */ - function aliasMethod(methodName) { - return new Alias(methodName); - } - - __exports__.aliasMethod = aliasMethod;// .......................................................... - // OBSERVER HELPER - // - - /** - Specify a method that observes property changes. - - ```javascript - Ember.Object.extend({ - valueObserver: Ember.observer('value', function() { - // Executes whenever the "value" property changes - }) - }); - ``` - - In the future this method may become asynchronous. If you want to ensure - synchronous behavior, use `immediateObserver`. - - Also available as `Function.prototype.observes` if prototype extensions are - enabled. - - @method observer - @for Ember - @param {String} propertyNames* - @param {Function} func - @return func - */ - function observer() { - var func = a_slice.call(arguments, -1)[0]; - var paths; - - var addWatchedProperty = function (path) { paths.push(path); }; - var _paths = a_slice.call(arguments, 0, -1); - - if (typeof func !== "function") { - // revert to old, soft-deprecated argument ordering - - func = arguments[0]; - _paths = a_slice.call(arguments, 1); - } - - paths = []; - - for (var i=0; i<_paths.length; ++i) { - expandProperties(_paths[i], addWatchedProperty); - } - - if (typeof func !== "function") { - throw new Ember.Error("Ember.observer called without a function"); - } - - func.__ember_observes__ = paths; - return func; - } - - __exports__.observer = observer;/** - Specify a method that observes property changes. - - ```javascript - Ember.Object.extend({ - valueObserver: Ember.immediateObserver('value', function() { - // Executes whenever the "value" property changes - }) - }); - ``` - - In the future, `Ember.observer` may become asynchronous. In this event, - `Ember.immediateObserver` will maintain the synchronous behavior. - - Also available as `Function.prototype.observesImmediately` if prototype extensions are - enabled. - - @method immediateObserver - @for Ember - @param {String} propertyNames* - @param {Function} func - @return func - */ - function immediateObserver() { - for (var i=0, l=arguments.length; i this.changingFrom ? 'green' : 'red'; - // logic - } - }), - - friendsDidChange: Ember.observer('friends.@each.name', function(obj, keyName) { - // some logic - // obj.get(keyName) returns friends array - }) - }); - ``` - - Also available as `Function.prototype.observesBefore` if prototype extensions are - enabled. - - @method beforeObserver - @for Ember - @param {String} propertyNames* - @param {Function} func - @return func - */ - function beforeObserver() { - var func = a_slice.call(arguments, -1)[0]; - var paths; - - var addWatchedProperty = function(path) { paths.push(path); }; - - var _paths = a_slice.call(arguments, 0, -1); - - if (typeof func !== "function") { - // revert to old, soft-deprecated argument ordering - - func = arguments[0]; - _paths = a_slice.call(arguments, 1); - } - - paths = []; - - for (var i=0; i<_paths.length; ++i) { - expandProperties(_paths[i], addWatchedProperty); - } - - if (typeof func !== "function") { - throw new Ember.Error("Ember.beforeObserver called without a function"); - } - - func.__ember_observesBefore__ = paths; - return func; - } - - __exports__.beforeObserver = beforeObserver;__exports__.IS_BINDING = IS_BINDING; - __exports__.Mixin = Mixin; - }); -enifed("ember-metal/observer", - ["ember-metal/watching","ember-metal/array","ember-metal/events","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __exports__) { - "use strict"; - var watch = __dependency1__.watch; - var unwatch = __dependency1__.unwatch; - var map = __dependency2__.map; - var listenersFor = __dependency3__.listenersFor; - var addListener = __dependency3__.addListener; - var removeListener = __dependency3__.removeListener; - var suspendListeners = __dependency3__.suspendListeners; - var suspendListener = __dependency3__.suspendListener; - /** - @module ember-metal - */ - - var AFTER_OBSERVERS = ':change'; - var BEFORE_OBSERVERS = ':before'; - - function changeEvent(keyName) { - return keyName + AFTER_OBSERVERS; - } - - function beforeEvent(keyName) { - return keyName + BEFORE_OBSERVERS; - } - - /** - @method addObserver - @for Ember - @param obj - @param {String} path - @param {Object|Function} targetOrMethod - @param {Function|String} [method] - */ - function addObserver(obj, _path, target, method) { - addListener(obj, changeEvent(_path), target, method); - watch(obj, _path); - - return this; - } - - __exports__.addObserver = addObserver;function observersFor(obj, path) { - return listenersFor(obj, changeEvent(path)); - } - - __exports__.observersFor = observersFor;/** - @method removeObserver - @for Ember - @param obj - @param {String} path - @param {Object|Function} targetOrMethod - @param {Function|String} [method] - */ - function removeObserver(obj, _path, target, method) { - unwatch(obj, _path); - removeListener(obj, changeEvent(_path), target, method); - - return this; - } - - __exports__.removeObserver = removeObserver;/** - @method addBeforeObserver - @for Ember - @param obj - @param {String} path - @param {Object|Function} targetOrMethod - @param {Function|String} [method] - */ - function addBeforeObserver(obj, _path, target, method) { - addListener(obj, beforeEvent(_path), target, method); - watch(obj, _path); - - return this; - } - - __exports__.addBeforeObserver = addBeforeObserver;// Suspend observer during callback. - // - // This should only be used by the target of the observer - // while it is setting the observed path. - function _suspendBeforeObserver(obj, path, target, method, callback) { - return suspendListener(obj, beforeEvent(path), target, method, callback); - } - - __exports__._suspendBeforeObserver = _suspendBeforeObserver;function _suspendObserver(obj, path, target, method, callback) { - return suspendListener(obj, changeEvent(path), target, method, callback); - } - - __exports__._suspendObserver = _suspendObserver;function _suspendBeforeObservers(obj, paths, target, method, callback) { - var events = map.call(paths, beforeEvent); - return suspendListeners(obj, events, target, method, callback); - } - - __exports__._suspendBeforeObservers = _suspendBeforeObservers;function _suspendObservers(obj, paths, target, method, callback) { - var events = map.call(paths, changeEvent); - return suspendListeners(obj, events, target, method, callback); - } - - __exports__._suspendObservers = _suspendObservers;function beforeObserversFor(obj, path) { - return listenersFor(obj, beforeEvent(path)); - } - - __exports__.beforeObserversFor = beforeObserversFor;/** - @method removeBeforeObserver - @for Ember - @param obj - @param {String} path - @param {Object|Function} targetOrMethod - @param {Function|String} [method] - */ - function removeBeforeObserver(obj, _path, target, method) { - unwatch(obj, _path); - removeListener(obj, beforeEvent(_path), target, method); - - return this; - } - - __exports__.removeBeforeObserver = removeBeforeObserver; - }); -enifed("ember-metal/observer_set", - ["ember-metal/utils","ember-metal/events","exports"], - function(__dependency1__, __dependency2__, __exports__) { - "use strict"; - var guidFor = __dependency1__.guidFor; - var sendEvent = __dependency2__.sendEvent; - - /* - this.observerSet = { - [senderGuid]: { // variable name: `keySet` - [keyName]: listIndex - } - }, - this.observers = [ - { - sender: obj, - keyName: keyName, - eventName: eventName, - listeners: [ - [target, method, flags] - ] - }, - ... - ] - */ - __exports__["default"] = ObserverSet; - function ObserverSet() { - this.clear(); - } - - - ObserverSet.prototype.add = function(sender, keyName, eventName) { - var observerSet = this.observerSet; - var observers = this.observers; - var senderGuid = guidFor(sender); - var keySet = observerSet[senderGuid]; - var index; - - if (!keySet) { - observerSet[senderGuid] = keySet = {}; - } - index = keySet[keyName]; - if (index === undefined) { - index = observers.push({ - sender: sender, - keyName: keyName, - eventName: eventName, - listeners: [] - }) - 1; - keySet[keyName] = index; - } - return observers[index].listeners; - }; - - ObserverSet.prototype.flush = function() { - var observers = this.observers; - var i, len, observer, sender; - this.clear(); - for (i=0, len=observers.length; i < len; ++i) { - observer = observers[i]; - sender = observer.sender; - if (sender.isDestroying || sender.isDestroyed) { continue; } - sendEvent(sender, observer.eventName, [sender, observer.keyName], observer.listeners); - } - }; - - ObserverSet.prototype.clear = function() { - this.observerSet = {}; - this.observers = []; - }; - }); -enifed("ember-metal/path_cache", - ["ember-metal/cache","exports"], - function(__dependency1__, __exports__) { - "use strict"; - var Cache = __dependency1__["default"]; - - var IS_GLOBAL = /^([A-Z$]|([0-9][A-Z$]))/; - var IS_GLOBAL_PATH = /^([A-Z$]|([0-9][A-Z$])).*[\.]/; - var HAS_THIS = 'this.'; - - var isGlobalCache = new Cache(1000, function(key) { return IS_GLOBAL.test(key); }); - var isGlobalPathCache = new Cache(1000, function(key) { return IS_GLOBAL_PATH.test(key); }); - var hasThisCache = new Cache(1000, function(key) { return key.indexOf(HAS_THIS) !== -1; }); - var isPathCache = new Cache(1000, function(key) { return key.indexOf('.') !== -1; }); - - var caches = { - isGlobalCache: isGlobalCache, - isGlobalPathCache: isGlobalPathCache, - hasThisCache: hasThisCache, - isPathCache: isPathCache - }; - __exports__.caches = caches; - function isGlobal(path) { - return isGlobalCache.get(path); - } - - __exports__.isGlobal = isGlobal;function isGlobalPath(path) { - return isGlobalPathCache.get(path); - } - - __exports__.isGlobalPath = isGlobalPath;function hasThis(path) { - return hasThisCache.get(path); - } - - __exports__.hasThis = hasThis;function isPath(path) { - return isPathCache.get(path); - } - - __exports__.isPath = isPath; - }); -enifed("ember-metal/platform", - ["ember-metal/platform/define_property","ember-metal/platform/define_properties","ember-metal/platform/create","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __exports__) { - "use strict"; - var hasES5CompliantDefineProperty = __dependency1__.hasES5CompliantDefineProperty; - var defineProperty = __dependency1__.defineProperty; - var defineProperties = __dependency2__["default"]; - var create = __dependency3__["default"]; - - /** - @module ember-metal - */ - - var hasPropertyAccessors = hasES5CompliantDefineProperty; - var canDefineNonEnumerableProperties = hasES5CompliantDefineProperty; - - /** - Platform specific methods and feature detectors needed by the framework. - - @class platform - @namespace Ember - @static - */ - - __exports__.create = create; - __exports__.defineProperty = defineProperty; - __exports__.defineProperties = defineProperties; - __exports__.hasPropertyAccessors = hasPropertyAccessors; - __exports__.canDefineNonEnumerableProperties = canDefineNonEnumerableProperties; - }); -enifed("ember-metal/platform/create", - ["exports"], - function(__exports__) { - // Remove "use strict"; from transpiled module until - // https://bugs.webkit.org/show_bug.cgi?id=138038 is fixed - // - // REMOVE_USE_STRICT: true - - /** - @class platform - @namespace Ember - @static - */ - - /** - Identical to `Object.create()`. Implements if not available natively. - - @method create - @for Ember - */ - var create; - // ES5 15.2.3.5 - // http://es5.github.com/#x15.2.3.5 - if (!(Object.create && !Object.create(null).hasOwnProperty)) { - /* jshint scripturl:true, proto:true */ - // Contributed by Brandon Benvie, October, 2012 - var createEmpty; - var supportsProto = !({'__proto__':null} instanceof Object); - // the following produces false positives - // in Opera Mini => not a reliable check - // Object.prototype.__proto__ === null - if (supportsProto || typeof document === 'undefined') { - createEmpty = function () { - return { "__proto__": null }; - }; - } else { - // In old IE __proto__ can't be used to manually set `null`, nor does - // any other method exist to make an object that inherits from nothing, - // aside from Object.prototype itself. Instead, create a new global - // object and *steal* its Object.prototype and strip it bare. This is - // used as the prototype to create nullary objects. - createEmpty = function () { - var iframe = document.createElement('iframe'); - var parent = document.body || document.documentElement; - iframe.style.display = 'none'; - parent.appendChild(iframe); - iframe.src = 'javascript:'; - var empty = iframe.contentWindow.Object.prototype; - parent.removeChild(iframe); - iframe = null; - delete empty.constructor; - delete empty.hasOwnProperty; - delete empty.propertyIsEnumerable; - delete empty.isPrototypeOf; - delete empty.toLocaleString; - delete empty.toString; - delete empty.valueOf; - - function Empty() {} - Empty.prototype = empty; - // short-circuit future calls - createEmpty = function () { - return new Empty(); - }; - return new Empty(); - }; - } - - create = Object.create = function create(prototype, properties) { - - var object; - function Type() {} // An empty constructor. - - if (prototype === null) { - object = createEmpty(); - } else { - if (typeof prototype !== "object" && typeof prototype !== "function") { - // In the native implementation `parent` can be `null` - // OR *any* `instanceof Object` (Object|Function|Array|RegExp|etc) - // Use `typeof` tho, b/c in old IE, DOM elements are not `instanceof Object` - // like they are in modern browsers. Using `Object.create` on DOM elements - // is...err...probably inappropriate, but the native version allows for it. - throw new TypeError("Object prototype may only be an Object or null"); // same msg as Chrome - } - - Type.prototype = prototype; - - object = new Type(); - } - - if (properties !== undefined) { - Object.defineProperties(object, properties); - } - - return object; - }; - } else { - create = Object.create; - } - - __exports__["default"] = create; - }); -enifed("ember-metal/platform/define_properties", - ["ember-metal/platform/define_property","exports"], - function(__dependency1__, __exports__) { - "use strict"; - var defineProperty = __dependency1__.defineProperty; - - var defineProperties = Object.defineProperties; - - // ES5 15.2.3.7 - // http://es5.github.com/#x15.2.3.7 - if (!defineProperties) { - defineProperties = function defineProperties(object, properties) { - for (var property in properties) { - if (properties.hasOwnProperty(property) && property !== "__proto__") { - defineProperty(object, property, properties[property]); - } - } - return object; - }; - - Object.defineProperties = defineProperties; - } - - __exports__["default"] = defineProperties; - }); -enifed("ember-metal/platform/define_property", - ["exports"], - function(__exports__) { - "use strict"; - /*globals Node */ - - /** - @class platform - @namespace Ember - @static - */ - - /** - Set to true if the platform supports native getters and setters. - - @property hasPropertyAccessors - @final - */ - - /** - Identical to `Object.defineProperty()`. Implements as much functionality - as possible if not available natively. - - @method defineProperty - @param {Object} obj The object to modify - @param {String} keyName property name to modify - @param {Object} desc descriptor hash - @return {void} - */ - var defineProperty = (function checkCompliance(defineProperty) { - if (!defineProperty) return; - try { - var a = 5; - var obj = {}; - defineProperty(obj, 'a', { - configurable: true, - enumerable: true, - get: function () { - return a; - }, - set: function (v) { - a = v; - } - }); - if (obj.a !== 5) return; - obj.a = 10; - if (a !== 10) return; - - // check non-enumerability - defineProperty(obj, 'a', { - configurable: true, - enumerable: false, - writable: true, - value: true - }); - for (var key in obj) { - if (key === 'a') return; - } - - // Detects a bug in Android <3.2 where you cannot redefine a property using - // Object.defineProperty once accessors have already been set. - if (obj.a !== true) return; - - // defineProperty is compliant - return defineProperty; - } catch (e) { - // IE8 defines Object.defineProperty but calling it on an Object throws - return; - } - })(Object.defineProperty); - - var hasES5CompliantDefineProperty = !!defineProperty; - - if (hasES5CompliantDefineProperty && typeof document !== 'undefined') { - // This is for Safari 5.0, which supports Object.defineProperty, but not - // on DOM nodes. - var canDefinePropertyOnDOM = (function() { - try { - defineProperty(document.createElement('div'), 'definePropertyOnDOM', {}); - return true; - } catch(e) { } - - return false; - })(); - - if (!canDefinePropertyOnDOM) { - defineProperty = function(obj, keyName, desc) { - var isNode; - - if (typeof Node === "object") { - isNode = obj instanceof Node; - } else { - isNode = typeof obj === "object" && typeof obj.nodeType === "number" && typeof obj.nodeName === "string"; - } - - if (isNode) { - // TODO: Should we have a warning here? - return (obj[keyName] = desc.value); - } else { - return Object.defineProperty(obj, keyName, desc); - } - }; - } - } - - if (!hasES5CompliantDefineProperty) { - defineProperty = function defineProperty(obj, keyName, desc) { - if (!desc.get) { obj[keyName] = desc.value; } - }; - } - - __exports__.hasES5CompliantDefineProperty = hasES5CompliantDefineProperty; - __exports__.defineProperty = defineProperty; - }); -enifed("ember-metal/properties", - ["ember-metal/core","ember-metal/utils","ember-metal/platform","ember-metal/property_events","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __exports__) { - "use strict"; - /** - @module ember-metal - */ - - var Ember = __dependency1__["default"]; - var metaFor = __dependency2__.meta; - var objectDefineProperty = __dependency3__.defineProperty; - var hasPropertyAccessors = __dependency3__.hasPropertyAccessors; - var overrideChains = __dependency4__.overrideChains; - // .......................................................... - // DESCRIPTOR - // - - /** - Objects of this type can implement an interface to respond to requests to - get and set. The default implementation handles simple properties. - - You generally won't need to create or subclass this directly. - - @class Descriptor - @namespace Ember - @private - @constructor - */ - function Descriptor() {} - - __exports__.Descriptor = Descriptor;// .......................................................... - // DEFINING PROPERTIES API - // - - function MANDATORY_SETTER_FUNCTION(name) { - return function SETTER_FUNCTION(value) { - Ember.assert("You must use Ember.set() to set the `" + name + "` property (of " + this + ") to `" + value + "`.", false); - }; - } - - __exports__.MANDATORY_SETTER_FUNCTION = MANDATORY_SETTER_FUNCTION;function DEFAULT_GETTER_FUNCTION(name) { - return function GETTER_FUNCTION() { - var meta = this['__ember_meta__']; - return meta && meta.values[name]; - }; - } - - __exports__.DEFAULT_GETTER_FUNCTION = DEFAULT_GETTER_FUNCTION;/** - NOTE: This is a low-level method used by other parts of the API. You almost - never want to call this method directly. Instead you should use - `Ember.mixin()` to define new properties. - - Defines a property on an object. This method works much like the ES5 - `Object.defineProperty()` method except that it can also accept computed - properties and other special descriptors. - - Normally this method takes only three parameters. However if you pass an - instance of `Ember.Descriptor` as the third param then you can pass an - optional value as the fourth parameter. This is often more efficient than - creating new descriptor hashes for each property. - - ## Examples - - ```javascript - // ES5 compatible mode - Ember.defineProperty(contact, 'firstName', { - writable: true, - configurable: false, - enumerable: true, - value: 'Charles' - }); - - // define a simple property - Ember.defineProperty(contact, 'lastName', undefined, 'Jolley'); - - // define a computed property - Ember.defineProperty(contact, 'fullName', Ember.computed(function() { - return this.firstName+' '+this.lastName; - }).property('firstName', 'lastName')); - ``` - - @private - @method defineProperty - @for Ember - @param {Object} obj the object to define this property on. This may be a prototype. - @param {String} keyName the name of the property - @param {Ember.Descriptor} [desc] an instance of `Ember.Descriptor` (typically a - computed property) or an ES5 descriptor. - You must provide this or `data` but not both. - @param {*} [data] something other than a descriptor, that will - become the explicit value of this property. - */ - function defineProperty(obj, keyName, desc, data, meta) { - var descs, existingDesc, watching, value; - - if (!meta) meta = metaFor(obj); - descs = meta.descs; - existingDesc = meta.descs[keyName]; - var watchEntry = meta.watching[keyName]; - - watching = watchEntry !== undefined && watchEntry > 0; - - if (existingDesc instanceof Descriptor) { - existingDesc.teardown(obj, keyName); - } - - if (desc instanceof Descriptor) { - value = desc; - - descs[keyName] = desc; - - if (watching && hasPropertyAccessors) { - objectDefineProperty(obj, keyName, { - configurable: true, - enumerable: true, - writable: true, - value: undefined // make enumerable - }); - } else { - obj[keyName] = undefined; // make enumerable - } - if (desc.setup) { desc.setup(obj, keyName); } - } else { - descs[keyName] = undefined; // shadow descriptor in proto - if (desc == null) { - value = data; - - - if (watching && hasPropertyAccessors) { - meta.values[keyName] = data; - objectDefineProperty(obj, keyName, { - configurable: true, - enumerable: true, - set: MANDATORY_SETTER_FUNCTION(keyName), - get: DEFAULT_GETTER_FUNCTION(keyName) - }); - } else { - obj[keyName] = data; - } - } else { - value = desc; - - // compatibility with ES5 - objectDefineProperty(obj, keyName, desc); - } - } - - // if key is being watched, override chains that - // were initialized with the prototype - if (watching) { overrideChains(obj, keyName, meta); } - - // The `value` passed to the `didDefineProperty` hook is - // either the descriptor or data, whichever was passed. - if (obj.didDefineProperty) { obj.didDefineProperty(obj, keyName, value); } - - return this; - } - __exports__.defineProperty = defineProperty; - }); -enifed("ember-metal/property_events", - ["ember-metal/utils","ember-metal/events","ember-metal/observer_set","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __exports__) { - "use strict"; - var guidFor = __dependency1__.guidFor; - var tryFinally = __dependency1__.tryFinally; - var sendEvent = __dependency2__.sendEvent; - var listenersUnion = __dependency2__.listenersUnion; - var listenersDiff = __dependency2__.listenersDiff; - var ObserverSet = __dependency3__["default"]; - - var beforeObserverSet = new ObserverSet(); - var observerSet = new ObserverSet(); - var deferred = 0; - - // .......................................................... - // PROPERTY CHANGES - // - - /** - This function is called just before an object property is about to change. - It will notify any before observers and prepare caches among other things. - - Normally you will not need to call this method directly but if for some - reason you can't directly watch a property you can invoke this method - manually along with `Ember.propertyDidChange()` which you should call just - after the property value changes. - - @method propertyWillChange - @for Ember - @param {Object} obj The object with the property that will change - @param {String} keyName The property key (or path) that will change. - @return {void} - */ - function propertyWillChange(obj, keyName) { - var m = obj['__ember_meta__']; - var watching = (m && m.watching[keyName] > 0) || keyName === 'length'; - var proto = m && m.proto; - var desc = m && m.descs[keyName]; - - if (!watching) { return; } - if (proto === obj) { return; } - if (desc && desc.willChange) { desc.willChange(obj, keyName); } - dependentKeysWillChange(obj, keyName, m); - chainsWillChange(obj, keyName, m); - notifyBeforeObservers(obj, keyName); - } - - /** - This function is called just after an object property has changed. - It will notify any observers and clear caches among other things. - - Normally you will not need to call this method directly but if for some - reason you can't directly watch a property you can invoke this method - manually along with `Ember.propertyWillChange()` which you should call just - before the property value changes. - - @method propertyDidChange - @for Ember - @param {Object} obj The object with the property that will change - @param {String} keyName The property key (or path) that will change. - @return {void} - */ - function propertyDidChange(obj, keyName) { - var m = obj['__ember_meta__']; - var watching = (m && m.watching[keyName] > 0) || keyName === 'length'; - var proto = m && m.proto; - var desc = m && m.descs[keyName]; - - if (proto === obj) { return; } - - // shouldn't this mean that we're watching this key? - if (desc && desc.didChange) { desc.didChange(obj, keyName); } - if (!watching && keyName !== 'length') { return; } - - if (m && m.deps && m.deps[keyName]) { - dependentKeysDidChange(obj, keyName, m); - } - - chainsDidChange(obj, keyName, m, false); - notifyObservers(obj, keyName); - } - - var WILL_SEEN, DID_SEEN; - // called whenever a property is about to change to clear the cache of any dependent keys (and notify those properties of changes, etc...) - function dependentKeysWillChange(obj, depKey, meta) { - if (obj.isDestroying) { return; } - - var deps; - if (meta && meta.deps && (deps = meta.deps[depKey])) { - var seen = WILL_SEEN; - var top = !seen; - if (top) { seen = WILL_SEEN = {}; } - iterDeps(propertyWillChange, obj, deps, depKey, seen, meta); - if (top) { WILL_SEEN = null; } - } - } - - // called whenever a property has just changed to update dependent keys - function dependentKeysDidChange(obj, depKey, meta) { - if (obj.isDestroying) { return; } - - var deps; - if (meta && meta.deps && (deps = meta.deps[depKey])) { - var seen = DID_SEEN; - var top = !seen; - if (top) { seen = DID_SEEN = {}; } - iterDeps(propertyDidChange, obj, deps, depKey, seen, meta); - if (top) { DID_SEEN = null; } - } - } - - function keysOf(obj) { - var keys = []; - for (var key in obj) keys.push(key); - return keys; - } - - function iterDeps(method, obj, deps, depKey, seen, meta) { - var keys, key, i, desc; - var guid = guidFor(obj); - var current = seen[guid]; - if (!current) current = seen[guid] = {}; - if (current[depKey]) return; - current[depKey] = true; - - if (deps) { - keys = keysOf(deps); - var descs = meta.descs; - for (i=0; i 0) { - ret = meta.values[keyName]; - } else { - ret = obj[keyName]; - } - - if (ret === undefined && - 'object' === typeof obj && !(keyName in obj) && 'function' === typeof obj.unknownProperty) { - return obj.unknownProperty(keyName); - } - - return ret; - } - }; - - // Currently used only by Ember Data tests - if (Ember.config.overrideAccessors) { - Ember.get = get; - Ember.config.overrideAccessors(); - get = Ember.get; - } - - /** - Normalizes a target/path pair to reflect that actual target/path that should - be observed, etc. This takes into account passing in global property - paths (i.e. a path beginning with a captial letter not defined on the - target). - - @private - @method normalizeTuple - @for Ember - @param {Object} target The current target. May be `null`. - @param {String} path A path on the target or a global property path. - @return {Array} a temporary array with the normalized target/path pair. - */ - function normalizeTuple(target, path) { - var hasThis = pathHasThis(path); - var isGlobal = !hasThis && isGlobalPath(path); - var key; - - if (!target || isGlobal) target = Ember.lookup; - if (hasThis) path = path.slice(5); - - Ember.deprecate( - "normalizeTuple will return '"+path+"' as a non-global. This behavior will change in the future (issue #3852)", - target === Ember.lookup || !target || hasThis || isGlobal || !isGlobalPath(path+'.') - ); - - if (target === Ember.lookup) { - key = path.match(FIRST_KEY)[0]; - target = get(target, key); - path = path.slice(key.length+1); - } - - // must return some kind of path to be valid else other things will break. - if (!path || path.length===0) throw new EmberError('Path cannot be empty'); - - return [ target, path ]; - } - - function _getPath(root, path) { - var hasThis, parts, tuple, idx, len; - - // If there is no root and path is a key name, return that - // property from the global object. - // E.g. get('Ember') -> Ember - if (root === null && !isPath(path)) { - return get(Ember.lookup, path); - } - - // detect complicated paths and normalize them - hasThis = pathHasThis(path); - - if (!root || hasThis) { - tuple = normalizeTuple(root, path); - root = tuple[0]; - path = tuple[1]; - tuple.length = 0; - } - - parts = path.split("."); - len = parts.length; - for (idx = 0; root != null && idx < len; idx++) { - root = get(root, parts[idx], true); - if (root && root.isDestroyed) { return undefined; } - } - return root; - } - - function getWithDefault(root, key, defaultValue) { - var value = get(root, key); - - if (value === undefined) { return defaultValue; } - return value; - } - - __exports__.getWithDefault = getWithDefault;__exports__["default"] = get; - __exports__.get = get; - __exports__.normalizeTuple = normalizeTuple; - __exports__._getPath = _getPath; - }); -enifed("ember-metal/property_set", - ["ember-metal/core","ember-metal/property_get","ember-metal/property_events","ember-metal/properties","ember-metal/error","ember-metal/path_cache","ember-metal/platform","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __exports__) { - "use strict"; - var Ember = __dependency1__["default"]; - var getPath = __dependency2__._getPath; - var propertyWillChange = __dependency3__.propertyWillChange; - var propertyDidChange = __dependency3__.propertyDidChange; - var defineProperty = __dependency4__.defineProperty; - var EmberError = __dependency5__["default"]; - var isPath = __dependency6__.isPath; - var hasPropertyAccessors = __dependency7__.hasPropertyAccessors; - - var IS_GLOBAL = /^([A-Z$]|([0-9][A-Z$]))/; - - /** - Sets the value of a property on an object, respecting computed properties - and notifying observers and other listeners of the change. If the - property is not defined but the object implements the `setUnknownProperty` - method then that will be invoked as well. - - @method set - @for Ember - @param {Object} obj The object to modify. - @param {String} keyName The property key to set - @param {Object} value The value to set - @return {Object} the passed value. - */ - var set = function set(obj, keyName, value, tolerant) { - if (typeof obj === 'string') { - Ember.assert("Path '" + obj + "' must be global if no obj is given.", IS_GLOBAL.test(obj)); - value = keyName; - keyName = obj; - obj = null; - } - - Ember.assert("Cannot call set with "+ keyName +" key.", !!keyName); - - if (!obj) { - return setPath(obj, keyName, value, tolerant); - } - - var meta = obj['__ember_meta__']; - var desc = meta && meta.descs[keyName]; - var isUnknown, currentValue; - - if (desc === undefined && isPath(keyName)) { - return setPath(obj, keyName, value, tolerant); - } - - Ember.assert("You need to provide an object and key to `set`.", !!obj && keyName !== undefined); - Ember.assert('calling set on destroyed object', !obj.isDestroyed); - - if (desc !== undefined) { - desc.set(obj, keyName, value); - } else { - - if (typeof obj === 'object' && obj !== null && value !== undefined && obj[keyName] === value) { - return value; - } - - isUnknown = 'object' === typeof obj && !(keyName in obj); - - // setUnknownProperty is called if `obj` is an object, - // the property does not already exist, and the - // `setUnknownProperty` method exists on the object - if (isUnknown && 'function' === typeof obj.setUnknownProperty) { - obj.setUnknownProperty(keyName, value); - } else if (meta && meta.watching[keyName] > 0) { - - if (hasPropertyAccessors) { - currentValue = meta.values[keyName]; - } else { - currentValue = obj[keyName]; - } - // only trigger a change if the value has changed - if (value !== currentValue) { - propertyWillChange(obj, keyName); - - if (hasPropertyAccessors) { - if ( - (currentValue === undefined && !(keyName in obj)) || - !Object.prototype.propertyIsEnumerable.call(obj, keyName) - ) { - defineProperty(obj, keyName, null, value); // setup mandatory setter - } else { - meta.values[keyName] = value; - } - } else { - obj[keyName] = value; - } - propertyDidChange(obj, keyName); - } - } else { - obj[keyName] = value; - } - } - return value; - }; - - // Currently used only by Ember Data tests - // ES6TODO: Verify still true - if (Ember.config.overrideAccessors) { - Ember.set = set; - Ember.config.overrideAccessors(); - set = Ember.set; - } - - function setPath(root, path, value, tolerant) { - var keyName; - - // get the last part of the path - keyName = path.slice(path.lastIndexOf('.') + 1); - - // get the first part of the part - path = (path === keyName) ? keyName : path.slice(0, path.length-(keyName.length+1)); - - // unless the path is this, look up the first part to - // get the root - if (path !== 'this') { - root = getPath(root, path); - } - - if (!keyName || keyName.length === 0) { - throw new EmberError('Property set failed: You passed an empty path'); - } - - if (!root) { - if (tolerant) { return; } - else { throw new EmberError('Property set failed: object in path "'+path+'" could not be found or was destroyed.'); } - } - - return set(root, keyName, value); - } - - /** - Error-tolerant form of `Ember.set`. Will not blow up if any part of the - chain is `undefined`, `null`, or destroyed. - - This is primarily used when syncing bindings, which may try to update after - an object has been destroyed. - - @method trySet - @for Ember - @param {Object} obj The object to modify. - @param {String} path The property path to set - @param {Object} value The value to set - */ - function trySet(root, path, value) { - return set(root, path, value, true); - } - - __exports__.trySet = trySet;__exports__.set = set; - }); -enifed("ember-metal/run_loop", - ["ember-metal/core","ember-metal/utils","ember-metal/array","ember-metal/property_events","backburner","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __exports__) { - "use strict"; - var Ember = __dependency1__["default"]; - var apply = __dependency2__.apply; - var GUID_KEY = __dependency2__.GUID_KEY; - var indexOf = __dependency3__.indexOf; - var beginPropertyChanges = __dependency4__.beginPropertyChanges; - var endPropertyChanges = __dependency4__.endPropertyChanges; - var Backburner = __dependency5__["default"]; - - function onBegin(current) { - run.currentRunLoop = current; - } - - function onEnd(current, next) { - run.currentRunLoop = next; - } - - // ES6TODO: should Backburner become es6? - var backburner = new Backburner(['sync', 'actions', 'destroy'], { - GUID_KEY: GUID_KEY, - sync: { - before: beginPropertyChanges, - after: endPropertyChanges - }, - defaultQueue: 'actions', - onBegin: onBegin, - onEnd: onEnd, - onErrorTarget: Ember, - onErrorMethod: 'onerror' - }); - var slice = [].slice; - var concat = [].concat; - - // .......................................................... - // run - this is ideally the only public API the dev sees - // - - /** - Runs the passed target and method inside of a RunLoop, ensuring any - deferred actions including bindings and views updates are flushed at the - end. - - Normally you should not need to invoke this method yourself. However if - you are implementing raw event handlers when interfacing with other - libraries or plugins, you should probably wrap all of your code inside this - call. - - ```javascript - run(function() { - // code to be execute within a RunLoop - }); - ``` - - @class run - @namespace Ember - @static - @constructor - @param {Object} [target] target of method to call - @param {Function|String} method Method to invoke. - May be a function or a string. If you pass a string - then it will be looked up on the passed target. - @param {Object} [args*] Any additional arguments you wish to pass to the method. - @return {Object} return value from invoking the passed function. - */ - __exports__["default"] = run; - function run() { - return backburner.run.apply(backburner, arguments); - } - - /** - If no run-loop is present, it creates a new one. If a run loop is - present it will queue itself to run on the existing run-loops action - queue. - - Please note: This is not for normal usage, and should be used sparingly. - - If invoked when not within a run loop: - - ```javascript - run.join(function() { - // creates a new run-loop - }); - ``` - - Alternatively, if called within an existing run loop: - - ```javascript - run(function() { - // creates a new run-loop - run.join(function() { - // joins with the existing run-loop, and queues for invocation on - // the existing run-loops action queue. - }); - }); - ``` - - @method join - @namespace Ember - @param {Object} [target] target of method to call - @param {Function|String} method Method to invoke. - May be a function or a string. If you pass a string - then it will be looked up on the passed target. - @param {Object} [args*] Any additional arguments you wish to pass to the method. - @return {Object} Return value from invoking the passed function. Please note, - when called within an existing loop, no return value is possible. - */ - run.join = function(target, method /* args */) { - if (!run.currentRunLoop) { - return Ember.run.apply(Ember, arguments); - } - - var args = slice.call(arguments); - args.unshift('actions'); - run.schedule.apply(run, args); - }; - - /** - Provides a useful utility for when integrating with non-Ember libraries - that provide asynchronous callbacks. - - Ember utilizes a run-loop to batch and coalesce changes. This works by - marking the start and end of Ember-related Javascript execution. - - When using events such as a View's click handler, Ember wraps the event - handler in a run-loop, but when integrating with non-Ember libraries this - can be tedious. - - For example, the following is rather verbose but is the correct way to combine - third-party events and Ember code. - - ```javascript - var that = this; - jQuery(window).on('resize', function(){ - run(function(){ - that.handleResize(); - }); - }); - ``` - - To reduce the boilerplate, the following can be used to construct a - run-loop-wrapped callback handler. - - ```javascript - jQuery(window).on('resize', run.bind(this, this.handleResize)); - ``` - - @method bind - @namespace Ember - @param {Object} [target] target of method to call - @param {Function|String} method Method to invoke. - May be a function or a string. If you pass a string - then it will be looked up on the passed target. - @param {Object} [args*] Any additional arguments you wish to pass to the method. - @return {Object} return value from invoking the passed function. Please note, - when called within an existing loop, no return value is possible. - @since 1.4.0 - */ - run.bind = function(target, method /* args*/) { - var args = slice.call(arguments); - return function() { - return run.join.apply(run, args.concat(slice.call(arguments))); - }; - }; - - run.backburner = backburner; - run.currentRunLoop = null; - run.queues = backburner.queueNames; - - /** - Begins a new RunLoop. Any deferred actions invoked after the begin will - be buffered until you invoke a matching call to `run.end()`. This is - a lower-level way to use a RunLoop instead of using `run()`. - - ```javascript - run.begin(); - // code to be execute within a RunLoop - run.end(); - ``` - - @method begin - @return {void} - */ - run.begin = function() { - backburner.begin(); - }; - - /** - Ends a RunLoop. This must be called sometime after you call - `run.begin()` to flush any deferred actions. This is a lower-level way - to use a RunLoop instead of using `run()`. - - ```javascript - run.begin(); - // code to be execute within a RunLoop - run.end(); - ``` - - @method end - @return {void} - */ - run.end = function() { - backburner.end(); - }; - - /** - Array of named queues. This array determines the order in which queues - are flushed at the end of the RunLoop. You can define your own queues by - simply adding the queue name to this array. Normally you should not need - to inspect or modify this property. - - @property queues - @type Array - @default ['sync', 'actions', 'destroy'] - */ - - /** - Adds the passed target/method and any optional arguments to the named - queue to be executed at the end of the RunLoop. If you have not already - started a RunLoop when calling this method one will be started for you - automatically. - - At the end of a RunLoop, any methods scheduled in this way will be invoked. - Methods will be invoked in an order matching the named queues defined in - the `run.queues` property. - - ```javascript - run.schedule('sync', this, function() { - // this will be executed in the first RunLoop queue, when bindings are synced - console.log("scheduled on sync queue"); - }); - - run.schedule('actions', this, function() { - // this will be executed in the 'actions' queue, after bindings have synced. - console.log("scheduled on actions queue"); - }); - - // Note the functions will be run in order based on the run queues order. - // Output would be: - // scheduled on sync queue - // scheduled on actions queue - ``` - - @method schedule - @param {String} queue The name of the queue to schedule against. - Default queues are 'sync' and 'actions' - @param {Object} [target] target object to use as the context when invoking a method. - @param {String|Function} method The method to invoke. If you pass a string it - will be resolved on the target object at the time the scheduled item is - invoked allowing you to change the target function. - @param {Object} [arguments*] Optional arguments to be passed to the queued method. - @return {void} - */ - run.schedule = function(queue, target, method) { - checkAutoRun(); - backburner.schedule.apply(backburner, arguments); - }; - - // Used by global test teardown - run.hasScheduledTimers = function() { - return backburner.hasTimers(); - }; - - // Used by global test teardown - run.cancelTimers = function () { - backburner.cancelTimers(); - }; - - /** - Immediately flushes any events scheduled in the 'sync' queue. Bindings - use this queue so this method is a useful way to immediately force all - bindings in the application to sync. - - You should call this method anytime you need any changed state to propagate - throughout the app immediately without repainting the UI (which happens - in the later 'render' queue added by the `ember-views` package). - - ```javascript - run.sync(); - ``` - - @method sync - @return {void} - */ - run.sync = function() { - if (backburner.currentInstance) { - backburner.currentInstance.queues.sync.flush(); - } - }; - - /** - Invokes the passed target/method and optional arguments after a specified - period of time. The last parameter of this method must always be a number - of milliseconds. - - You should use this method whenever you need to run some action after a - period of time instead of using `setTimeout()`. This method will ensure that - items that expire during the same script execution cycle all execute - together, which is often more efficient than using a real setTimeout. - - ```javascript - run.later(myContext, function() { - // code here will execute within a RunLoop in about 500ms with this == myContext - }, 500); - ``` - - @method later - @param {Object} [target] target of method to invoke - @param {Function|String} method The method to invoke. - If you pass a string it will be resolved on the - target at the time the method is invoked. - @param {Object} [args*] Optional arguments to pass to the timeout. - @param {Number} wait Number of milliseconds to wait. - @return {Object} Timer information for use in cancelling, see `run.cancel`. - */ - run.later = function(/*target, method*/) { - return backburner.later.apply(backburner, arguments); - }; - - /** - Schedule a function to run one time during the current RunLoop. This is equivalent - to calling `scheduleOnce` with the "actions" queue. - - @method once - @param {Object} [target] The target of the method to invoke. - @param {Function|String} method The method to invoke. - If you pass a string it will be resolved on the - target at the time the method is invoked. - @param {Object} [args*] Optional arguments to pass to the timeout. - @return {Object} Timer information for use in cancelling, see `run.cancel`. - */ - run.once = function(target, method) { - checkAutoRun(); - var args = slice.call(arguments); - args.unshift('actions'); - return apply(backburner, backburner.scheduleOnce, args); - }; - - /** - Schedules a function to run one time in a given queue of the current RunLoop. - Calling this method with the same queue/target/method combination will have - no effect (past the initial call). - - Note that although you can pass optional arguments these will not be - considered when looking for duplicates. New arguments will replace previous - calls. - - ```javascript - run(function() { - var sayHi = function() { console.log('hi'); } - run.scheduleOnce('afterRender', myContext, sayHi); - run.scheduleOnce('afterRender', myContext, sayHi); - // sayHi will only be executed once, in the afterRender queue of the RunLoop - }); - ``` - - Also note that passing an anonymous function to `run.scheduleOnce` will - not prevent additional calls with an identical anonymous function from - scheduling the items multiple times, e.g.: - - ```javascript - function scheduleIt() { - run.scheduleOnce('actions', myContext, function() { console.log("Closure"); }); - } - scheduleIt(); - scheduleIt(); - // "Closure" will print twice, even though we're using `run.scheduleOnce`, - // because the function we pass to it is anonymous and won't match the - // previously scheduled operation. - ``` - - Available queues, and their order, can be found at `run.queues` - - @method scheduleOnce - @param {String} [queue] The name of the queue to schedule against. Default queues are 'sync' and 'actions'. - @param {Object} [target] The target of the method to invoke. - @param {Function|String} method The method to invoke. - If you pass a string it will be resolved on the - target at the time the method is invoked. - @param {Object} [args*] Optional arguments to pass to the timeout. - @return {Object} Timer information for use in cancelling, see `run.cancel`. - */ - run.scheduleOnce = function(/*queue, target, method*/) { - checkAutoRun(); - return backburner.scheduleOnce.apply(backburner, arguments); - }; - - /** - Schedules an item to run from within a separate run loop, after - control has been returned to the system. This is equivalent to calling - `run.later` with a wait time of 1ms. - - ```javascript - run.next(myContext, function() { - // code to be executed in the next run loop, - // which will be scheduled after the current one - }); - ``` - - Multiple operations scheduled with `run.next` will coalesce - into the same later run loop, along with any other operations - scheduled by `run.later` that expire right around the same - time that `run.next` operations will fire. - - Note that there are often alternatives to using `run.next`. - For instance, if you'd like to schedule an operation to happen - after all DOM element operations have completed within the current - run loop, you can make use of the `afterRender` run loop queue (added - by the `ember-views` package, along with the preceding `render` queue - where all the DOM element operations happen). Example: - - ```javascript - App.MyCollectionView = Ember.CollectionView.extend({ - didInsertElement: function() { - run.scheduleOnce('afterRender', this, 'processChildElements'); - }, - processChildElements: function() { - // ... do something with collectionView's child view - // elements after they've finished rendering, which - // can't be done within the CollectionView's - // `didInsertElement` hook because that gets run - // before the child elements have been added to the DOM. - } - }); - ``` - - One benefit of the above approach compared to using `run.next` is - that you will be able to perform DOM/CSS operations before unprocessed - elements are rendered to the screen, which may prevent flickering or - other artifacts caused by delaying processing until after rendering. - - The other major benefit to the above approach is that `run.next` - introduces an element of non-determinism, which can make things much - harder to test, due to its reliance on `setTimeout`; it's much harder - to guarantee the order of scheduled operations when they are scheduled - outside of the current run loop, i.e. with `run.next`. - - @method next - @param {Object} [target] target of method to invoke - @param {Function|String} method The method to invoke. - If you pass a string it will be resolved on the - target at the time the method is invoked. - @param {Object} [args*] Optional arguments to pass to the timeout. - @return {Object} Timer information for use in cancelling, see `run.cancel`. - */ - run.next = function() { - var args = slice.call(arguments); - args.push(1); - return apply(backburner, backburner.later, args); - }; - - /** - Cancels a scheduled item. Must be a value returned by `run.later()`, - `run.once()`, `run.next()`, `run.debounce()`, or - `run.throttle()`. - - ```javascript - var runNext = run.next(myContext, function() { - // will not be executed - }); - run.cancel(runNext); - - var runLater = run.later(myContext, function() { - // will not be executed - }, 500); - run.cancel(runLater); - - var runOnce = run.once(myContext, function() { - // will not be executed - }); - run.cancel(runOnce); - - var throttle = run.throttle(myContext, function() { - // will not be executed - }, 1, false); - run.cancel(throttle); - - var debounce = run.debounce(myContext, function() { - // will not be executed - }, 1); - run.cancel(debounce); - - var debounceImmediate = run.debounce(myContext, function() { - // will be executed since we passed in true (immediate) - }, 100, true); - // the 100ms delay until this method can be called again will be cancelled - run.cancel(debounceImmediate); - ``` - - @method cancel - @param {Object} timer Timer object to cancel - @return {Boolean} true if cancelled or false/undefined if it wasn't found - */ - run.cancel = function(timer) { - return backburner.cancel(timer); - }; - - /** - Delay calling the target method until the debounce period has elapsed - with no additional debounce calls. If `debounce` is called again before - the specified time has elapsed, the timer is reset and the entire period - must pass again before the target method is called. - - This method should be used when an event may be called multiple times - but the action should only be called once when the event is done firing. - A common example is for scroll events where you only want updates to - happen once scrolling has ceased. - - ```javascript - var myFunc = function() { console.log(this.name + ' ran.'); }; - var myContext = {name: 'debounce'}; - - run.debounce(myContext, myFunc, 150); - - // less than 150ms passes - - run.debounce(myContext, myFunc, 150); - - // 150ms passes - // myFunc is invoked with context myContext - // console logs 'debounce ran.' one time. - ``` - - Immediate allows you to run the function immediately, but debounce - other calls for this function until the wait time has elapsed. If - `debounce` is called again before the specified time has elapsed, - the timer is reset and the entire period must pass again before - the method can be called again. - - ```javascript - var myFunc = function() { console.log(this.name + ' ran.'); }; - var myContext = {name: 'debounce'}; - - run.debounce(myContext, myFunc, 150, true); - - // console logs 'debounce ran.' one time immediately. - // 100ms passes - - run.debounce(myContext, myFunc, 150, true); - - // 150ms passes and nothing else is logged to the console and - // the debouncee is no longer being watched - - run.debounce(myContext, myFunc, 150, true); - - // console logs 'debounce ran.' one time immediately. - // 150ms passes and nothing else is logged to the console and - // the debouncee is no longer being watched - - ``` - - @method debounce - @param {Object} [target] target of method to invoke - @param {Function|String} method The method to invoke. - May be a function or a string. If you pass a string - then it will be looked up on the passed target. - @param {Object} [args*] Optional arguments to pass to the timeout. - @param {Number} wait Number of milliseconds to wait. - @param {Boolean} immediate Trigger the function on the leading instead - of the trailing edge of the wait interval. Defaults to false. - @return {Array} Timer information for use in cancelling, see `run.cancel`. - */ - run.debounce = function() { - return backburner.debounce.apply(backburner, arguments); - }; - - /** - Ensure that the target method is never called more frequently than - the specified spacing period. The target method is called immediately. - - ```javascript - var myFunc = function() { console.log(this.name + ' ran.'); }; - var myContext = {name: 'throttle'}; - - run.throttle(myContext, myFunc, 150); - // myFunc is invoked with context myContext - // console logs 'throttle ran.' - - // 50ms passes - run.throttle(myContext, myFunc, 150); - - // 50ms passes - run.throttle(myContext, myFunc, 150); - - // 150ms passes - run.throttle(myContext, myFunc, 150); - // myFunc is invoked with context myContext - // console logs 'throttle ran.' - ``` - - @method throttle - @param {Object} [target] target of method to invoke - @param {Function|String} method The method to invoke. - May be a function or a string. If you pass a string - then it will be looked up on the passed target. - @param {Object} [args*] Optional arguments to pass to the timeout. - @param {Number} spacing Number of milliseconds to space out requests. - @param {Boolean} immediate Trigger the function on the leading instead - of the trailing edge of the wait interval. Defaults to true. - @return {Array} Timer information for use in cancelling, see `run.cancel`. - */ - run.throttle = function() { - return backburner.throttle.apply(backburner, arguments); - }; - - // Make sure it's not an autorun during testing - function checkAutoRun() { - if (!run.currentRunLoop) { - Ember.assert("You have turned on testing mode, which disabled the run-loop's autorun. You will need to wrap any code with asynchronous side-effects in an run", !Ember.testing); - } - } - - /** - Add a new named queue after the specified queue. - - The queue to add will only be added once. - - @method _addQueue - @param {String} name the name of the queue to add. - @param {String} after the name of the queue to add after. - @private - */ - run._addQueue = function(name, after) { - if (indexOf.call(run.queues, name) === -1) { - run.queues.splice(indexOf.call(run.queues, after)+1, 0, name); - } - }; - }); -enifed("ember-metal/set_properties", - ["ember-metal/property_events","ember-metal/property_set","ember-metal/keys","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __exports__) { - "use strict"; - var changeProperties = __dependency1__.changeProperties; - var set = __dependency2__.set; - var keys = __dependency3__["default"]; - - /** - Set a list of properties on an object. These properties are set inside - a single `beginPropertyChanges` and `endPropertyChanges` batch, so - observers will be buffered. - - ```javascript - var anObject = Ember.Object.create(); - - anObject.setProperties({ - firstName: 'Stanley', - lastName: 'Stuart', - age: 21 - }); - ``` - - @method setProperties - @param obj - @param {Object} properties - @return obj - */ - __exports__["default"] = function setProperties(obj, properties) { - if (!properties || typeof properties !== "object") { return obj; } - changeProperties(function() { - var props = keys(properties); - var propertyName; - - for (var i = 0, l = props.length; i < l; i++) { - propertyName = props[i]; - - set(obj, propertyName, properties[propertyName]); - } - }); - return obj; - } - }); -enifed("ember-metal/utils", - ["ember-metal/core","ember-metal/platform","ember-metal/array","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __exports__) { - // Remove "use strict"; from transpiled module until - // https://bugs.webkit.org/show_bug.cgi?id=138038 is fixed - // - // REMOVE_USE_STRICT: true - - var Ember = __dependency1__["default"]; - var o_defineProperty = __dependency2__.defineProperty; - var canDefineNonEnumerableProperties = __dependency2__.canDefineNonEnumerableProperties; - var hasPropertyAccessors = __dependency2__.hasPropertyAccessors; - var create = __dependency2__.create; - - var forEach = __dependency3__.forEach; - - /** - @module ember-metal - */ - - /** - Previously we used `Ember.$.uuid`, however `$.uuid` has been removed from - jQuery master. We'll just bootstrap our own uuid now. - - @private - @return {Number} the uuid - */ - var _uuid = 0; - - /** - Generates a universally unique identifier. This method - is used internally by Ember for assisting with - the generation of GUID's and other unique identifiers - such as `bind-attr` data attributes. - - @public - @return {Number} [description] - */ - function uuid() { - return ++_uuid; - } - - __exports__.uuid = uuid;/** - Prefix used for guids through out Ember. - @private - @property GUID_PREFIX - @for Ember - @type String - @final - */ - var GUID_PREFIX = 'ember'; - - var o_create = create; - // Used for guid generation... - var numberCache = []; - var stringCache = {}; - - /** - Strongly hint runtimes to intern the provided string. - - When do I need to use this function? - - For the most part, never. Pre-mature optimization is bad, and often the - runtime does exactly what you need it to, and more often the trade-off isn't - worth it. - - Why? - - Runtimes store strings in at least 2 different representations: - Ropes and Symbols (interned strings). The Rope provides a memory efficient - data-structure for strings created from concatenation or some other string - manipulation like splitting. - - Unfortunately checking equality of different ropes can be quite costly as - runtimes must resort to clever string comparison algorithims. These - algorithims typically cost in proportion to the length of the string. - Luckily, this is where the Symbols (interned strings) shine. As Symbols are - unique by their string content, equality checks can be done by pointer - comparision. - - How do I know if my string is a rope or symbol? - - Typically (warning general sweeping statement, but truthy in runtimes at - present) static strings created as part of the JS source are interned. - Strings often used for comparisions can be interned at runtime if some - criteria are met. One of these criteria can be the size of the entire rope. - For example, in chrome 38 a rope longer then 12 characters will not - intern, nor will segments of that rope. - - Some numbers: http://jsperf.com/eval-vs-keys/8 - - Known Trick™ - - @private - @return {String} interned version of the provided string - */ - function intern(str) { - var obj = {}; - obj[str] = 1; - for (var key in obj) { - if (key === str) return key; - } - return str; - } - - /** - A unique key used to assign guids and other private metadata to objects. - If you inspect an object in your browser debugger you will often see these. - They can be safely ignored. - - On browsers that support it, these properties are added with enumeration - disabled so they won't show up when you iterate over your properties. - - @private - @property GUID_KEY - @for Ember - @type String - @final - */ - var GUID_KEY = intern('__ember' + (+ new Date())); - - var GUID_DESC = { - writable: false, - configurable: false, - enumerable: false, - value: null - }; - - /** - Generates a new guid, optionally saving the guid to the object that you - pass in. You will rarely need to use this method. Instead you should - call `Ember.guidFor(obj)`, which return an existing guid if available. - - @private - @method generateGuid - @for Ember - @param {Object} [obj] Object the guid will be used for. If passed in, the guid will - be saved on the object and reused whenever you pass the same object - again. - - If no object is passed, just generate a new guid. - @param {String} [prefix] Prefix to place in front of the guid. Useful when you want to - separate the guid into separate namespaces. - @return {String} the guid - */ - function generateGuid(obj, prefix) { - if (!prefix) prefix = GUID_PREFIX; - var ret = (prefix + uuid()); - if (obj) { - if (obj[GUID_KEY] === null) { - obj[GUID_KEY] = ret; - } else { - GUID_DESC.value = ret; - o_defineProperty(obj, GUID_KEY, GUID_DESC); - } - } - return ret; - } - - __exports__.generateGuid = generateGuid;/** - Returns a unique id for the object. If the object does not yet have a guid, - one will be assigned to it. You can call this on any object, - `Ember.Object`-based or not, but be aware that it will add a `_guid` - property. - - You can also use this method on DOM Element objects. - - @private - @method guidFor - @for Ember - @param {Object} obj any object, string, number, Element, or primitive - @return {String} the unique guid for this instance. - */ - function guidFor(obj) { - - // special cases where we don't want to add a key to object - if (obj === undefined) return "(undefined)"; - if (obj === null) return "(null)"; - - var ret; - var type = typeof obj; - - // Don't allow prototype changes to String etc. to change the guidFor - switch(type) { - case 'number': - ret = numberCache[obj]; - if (!ret) ret = numberCache[obj] = 'nu'+obj; - return ret; - - case 'string': - ret = stringCache[obj]; - if (!ret) ret = stringCache[obj] = 'st' + uuid(); - return ret; - - case 'boolean': - return obj ? '(true)' : '(false)'; - - default: - if (obj[GUID_KEY]) return obj[GUID_KEY]; - if (obj === Object) return '(Object)'; - if (obj === Array) return '(Array)'; - ret = GUID_PREFIX + uuid(); - - if (obj[GUID_KEY] === null) { - obj[GUID_KEY] = ret; - } else { - GUID_DESC.value = ret; - o_defineProperty(obj, GUID_KEY, GUID_DESC); - } - return ret; - } - } - - __exports__.guidFor = guidFor;// .......................................................... - // META - // - - var META_DESC = { - writable: true, - configurable: false, - enumerable: false, - value: null - }; - - function Meta(obj) { - this.descs = {}; - this.watching = {}; - this.cache = {}; - this.cacheMeta = {}; - this.source = obj; - } - - Meta.prototype = { - descs: null, - deps: null, - watching: null, - listeners: null, - cache: null, - cacheMeta: null, - source: null, - mixins: null, - bindings: null, - chains: null, - chainWatchers: null, - values: null, - proto: null - }; - - if (!canDefineNonEnumerableProperties) { - // on platforms that don't support enumerable false - // make meta fail jQuery.isPlainObject() to hide from - // jQuery.extend() by having a property that fails - // hasOwnProperty check. - Meta.prototype.__preventPlainObject__ = true; - - // Without non-enumerable properties, meta objects will be output in JSON - // unless explicitly suppressed - Meta.prototype.toJSON = function () { }; - } - - // Placeholder for non-writable metas. - var EMPTY_META = new Meta(null); - - - if (hasPropertyAccessors) { - EMPTY_META.values = {}; - } - - - /** - Retrieves the meta hash for an object. If `writable` is true ensures the - hash is writable for this object as well. - - The meta object contains information about computed property descriptors as - well as any watched properties and other information. You generally will - not access this information directly but instead work with higher level - methods that manipulate this hash indirectly. - - @method meta - @for Ember - @private - - @param {Object} obj The object to retrieve meta for - @param {Boolean} [writable=true] Pass `false` if you do not intend to modify - the meta hash, allowing the method to avoid making an unnecessary copy. - @return {Object} the meta hash for an object - */ - function meta(obj, writable) { - - var ret = obj['__ember_meta__']; - if (writable===false) return ret || EMPTY_META; - - if (!ret) { - if (canDefineNonEnumerableProperties) o_defineProperty(obj, '__ember_meta__', META_DESC); - - ret = new Meta(obj); - - - if (hasPropertyAccessors) { - ret.values = {}; - } - - - obj['__ember_meta__'] = ret; - - // make sure we don't accidentally try to create constructor like desc - ret.descs.constructor = null; - - } else if (ret.source !== obj) { - if (canDefineNonEnumerableProperties) o_defineProperty(obj, '__ember_meta__', META_DESC); - - ret = o_create(ret); - ret.descs = o_create(ret.descs); - ret.watching = o_create(ret.watching); - ret.cache = {}; - ret.cacheMeta = {}; - ret.source = obj; - - - if (hasPropertyAccessors) { - ret.values = o_create(ret.values); - } - - - obj['__ember_meta__'] = ret; - } - return ret; - } - - function getMeta(obj, property) { - var _meta = meta(obj, false); - return _meta[property]; - } - - __exports__.getMeta = getMeta;function setMeta(obj, property, value) { - var _meta = meta(obj, true); - _meta[property] = value; - return value; - } - - __exports__.setMeta = setMeta;/** - @deprecated - @private - - In order to store defaults for a class, a prototype may need to create - a default meta object, which will be inherited by any objects instantiated - from the class's constructor. - - However, the properties of that meta object are only shallow-cloned, - so if a property is a hash (like the event system's `listeners` hash), - it will by default be shared across all instances of that class. - - This method allows extensions to deeply clone a series of nested hashes or - other complex objects. For instance, the event system might pass - `['listeners', 'foo:change', 'ember157']` to `prepareMetaPath`, which will - walk down the keys provided. - - For each key, if the key does not exist, it is created. If it already - exists and it was inherited from its constructor, the constructor's - key is cloned. - - You can also pass false for `writable`, which will simply return - undefined if `prepareMetaPath` discovers any part of the path that - shared or undefined. - - @method metaPath - @for Ember - @param {Object} obj The object whose meta we are examining - @param {Array} path An array of keys to walk down - @param {Boolean} writable whether or not to create a new meta - (or meta property) if one does not already exist or if it's - shared with its constructor - */ - function metaPath(obj, path, writable) { - Ember.deprecate("Ember.metaPath is deprecated and will be removed from future releases."); - var _meta = meta(obj, writable); - var keyName, value; - - for (var i=0, l=path.length; i 1) { - watching[keyName]--; - } - } - - __exports__.unwatchKey = unwatchKey; - }); -enifed("ember-metal/watch_path", - ["ember-metal/utils","ember-metal/chains","exports"], - function(__dependency1__, __dependency2__, __exports__) { - "use strict"; - var meta = __dependency1__.meta; - var typeOf = __dependency1__.typeOf; - var ChainNode = __dependency2__.ChainNode; - - var metaFor = meta; - - // get the chains for the current object. If the current object has - // chains inherited from the proto they will be cloned and reconfigured for - // the current object. - function chainsFor(obj, meta) { - var m = meta || metaFor(obj); - var ret = m.chains; - if (!ret) { - ret = m.chains = new ChainNode(null, null, obj); - } else if (ret.value() !== obj) { - ret = m.chains = ret.copy(obj); - } - return ret; - } - - function watchPath(obj, keyPath, meta) { - // can't watch length on Array - it is special... - if (keyPath === 'length' && typeOf(obj) === 'array') { return; } - - var m = meta || metaFor(obj); - var watching = m.watching; - - if (!watching[keyPath]) { // activate watching first time - watching[keyPath] = 1; - chainsFor(obj, m).add(keyPath); - } else { - watching[keyPath] = (watching[keyPath] || 0) + 1; - } - } - - __exports__.watchPath = watchPath;function unwatchPath(obj, keyPath, meta) { - var m = meta || metaFor(obj); - var watching = m.watching; - - if (watching[keyPath] === 1) { - watching[keyPath] = 0; - chainsFor(obj, m).remove(keyPath); - } else if (watching[keyPath] > 1) { - watching[keyPath]--; - } - } - - __exports__.unwatchPath = unwatchPath; - }); -enifed("ember-metal/watching", - ["ember-metal/utils","ember-metal/chains","ember-metal/watch_key","ember-metal/watch_path","ember-metal/path_cache","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __exports__) { - "use strict"; - /** - @module ember-metal - */ - - var meta = __dependency1__.meta; - var GUID_KEY = __dependency1__.GUID_KEY; - var typeOf = __dependency1__.typeOf; - var generateGuid = __dependency1__.generateGuid; - var removeChainWatcher = __dependency2__.removeChainWatcher; - var flushPendingChains = __dependency2__.flushPendingChains; - var watchKey = __dependency3__.watchKey; - var unwatchKey = __dependency3__.unwatchKey; - var watchPath = __dependency4__.watchPath; - var unwatchPath = __dependency4__.unwatchPath; - - var metaFor = meta; // utils.js - var isPath = __dependency5__.isPath; - - /** - Starts watching a property on an object. Whenever the property changes, - invokes `Ember.propertyWillChange` and `Ember.propertyDidChange`. This is the - primitive used by observers and dependent keys; usually you will never call - this method directly but instead use higher level methods like - `Ember.addObserver()` - - @private - @method watch - @for Ember - @param obj - @param {String} keyName - */ - function watch(obj, _keyPath, m) { - // can't watch length on Array - it is special... - if (_keyPath === 'length' && typeOf(obj) === 'array') { return; } - - if (!isPath(_keyPath)) { - watchKey(obj, _keyPath, m); - } else { - watchPath(obj, _keyPath, m); - } - } - - __exports__.watch = watch; - - function isWatching(obj, key) { - var meta = obj['__ember_meta__']; - return (meta && meta.watching[key]) > 0; - } - - __exports__.isWatching = isWatching;watch.flushPending = flushPendingChains; - - function unwatch(obj, _keyPath, m) { - // can't watch length on Array - it is special... - if (_keyPath === 'length' && typeOf(obj) === 'array') { return; } - - if (!isPath(_keyPath)) { - unwatchKey(obj, _keyPath, m); - } else { - unwatchPath(obj, _keyPath, m); - } - } - - __exports__.unwatch = unwatch;/** - Call on an object when you first beget it from another object. This will - setup any chained watchers on the object instance as needed. This method is - safe to call multiple times. - - @private - @method rewatch - @for Ember - @param obj - */ - function rewatch(obj) { - var m = obj['__ember_meta__'], chains = m && m.chains; - - // make sure the object has its own guid. - if (GUID_KEY in obj && !obj.hasOwnProperty(GUID_KEY)) { - generateGuid(obj); - } - - // make sure any chained watchers update. - if (chains && chains.value() !== obj) { - m.chains = chains.copy(obj); - } - } - - __exports__.rewatch = rewatch;var NODE_STACK = []; - - /** - Tears down the meta on an object so that it can be garbage collected. - Multiple calls will have no effect. - - @method destroy - @for Ember - @param {Object} obj the object to destroy - @return {void} - */ - function destroy(obj) { - var meta = obj['__ember_meta__'], node, nodes, key, nodeObject; - if (meta) { - obj['__ember_meta__'] = null; - // remove chainWatchers to remove circular references that would prevent GC - node = meta.chains; - if (node) { - NODE_STACK.push(node); - // process tree - while (NODE_STACK.length > 0) { - node = NODE_STACK.pop(); - // push children - nodes = node._chains; - if (nodes) { - for (key in nodes) { - if (nodes.hasOwnProperty(key)) { - NODE_STACK.push(nodes[key]); - } - } - } - // remove chainWatcher in node object - if (node._watching) { - nodeObject = node._object; - if (nodeObject) { - removeChainWatcher(nodeObject, node._key, node); - } - } - } - } - } - } - - __exports__.destroy = destroy; - }); -enifed("ember-routing-handlebars", - ["ember-metal/core","ember-handlebars","ember-routing/system/router","ember-routing-handlebars/helpers/shared","ember-routing-handlebars/helpers/link_to","ember-routing-handlebars/helpers/outlet","ember-routing-handlebars/helpers/render","ember-routing-handlebars/helpers/action","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __exports__) { - "use strict"; - /** - Ember Routing Handlebars - - @module ember - @submodule ember-routing-handlebars - @requires ember-views - */ - - var Ember = __dependency1__["default"]; - var EmberHandlebars = __dependency2__["default"]; - var Router = __dependency3__["default"]; - - var resolvePaths = __dependency4__.resolvePaths; - var resolveParams = __dependency4__.resolveParams; - - var deprecatedLinkToHelper = __dependency5__.deprecatedLinkToHelper; - var linkToHelper = __dependency5__.linkToHelper; - var LinkView = __dependency5__.LinkView; - var queryParamsHelper = __dependency5__.queryParamsHelper; - - var outletHelper = __dependency6__.outletHelper; - var OutletView = __dependency6__.OutletView; - - var renderHelper = __dependency7__["default"]; - - var ActionHelper = __dependency8__.ActionHelper; - var actionHelper = __dependency8__.actionHelper; - - Router.resolveParams = resolveParams; - Router.resolvePaths = resolvePaths; - - Ember.LinkView = LinkView; - EmberHandlebars.ActionHelper = ActionHelper; - EmberHandlebars.OutletView = OutletView; - - EmberHandlebars.registerHelper('render', renderHelper); - EmberHandlebars.registerHelper('action', actionHelper); - EmberHandlebars.registerHelper('outlet', outletHelper); - EmberHandlebars.registerHelper('link-to', linkToHelper); - EmberHandlebars.registerHelper('linkTo', deprecatedLinkToHelper); - EmberHandlebars.registerHelper('query-params', queryParamsHelper); - - __exports__["default"] = Ember; - }); -enifed("ember-routing-handlebars/helpers/action", - ["ember-metal/core","ember-metal/property_get","ember-metal/array","ember-metal/utils","ember-metal/run_loop","ember-views/system/utils","ember-views/system/action_manager","ember-routing/system/router","ember-handlebars","ember-handlebars/ext","ember-handlebars/helpers/view","ember-routing-handlebars/helpers/shared","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __dependency11__, __dependency12__, __exports__) { - "use strict"; - var Ember = __dependency1__["default"]; - // Handlebars, uuid, FEATURES, assert, deprecate - var get = __dependency2__.get; - var forEach = __dependency3__.forEach; - var uuid = __dependency4__.uuid; - var run = __dependency5__["default"]; - - var isSimpleClick = __dependency6__.isSimpleClick; - var ActionManager = __dependency7__["default"]; - var EmberRouter = __dependency8__["default"]; - - var EmberHandlebars = __dependency9__["default"]; - var handlebarsGet = __dependency10__.handlebarsGet; - var viewHelper = __dependency11__.viewHelper; - var resolveParams = __dependency12__.resolveParams; - var resolvePath = __dependency12__.resolvePath; - - /** - @module ember - @submodule ember-routing - */ - - var SafeString = EmberHandlebars.SafeString; - var a_slice = Array.prototype.slice; - - function args(options, actionName) { - var ret = []; - if (actionName) { ret.push(actionName); } - - var types = options.options.types.slice(1); - var data = options.options.data; - - return ret.concat(resolveParams(options.context, options.params, { types: types, data: data })); - } - - var ActionHelper = {}; - - // registeredActions is re-exported for compatibility with older plugins - // that were using this undocumented API. - ActionHelper.registeredActions = ActionManager.registeredActions; - - __exports__.ActionHelper = ActionHelper; - - var keys = ["alt", "shift", "meta", "ctrl"]; - - var POINTER_EVENT_TYPE_REGEX = /^click|mouse|touch/; - - var isAllowedEvent = function(event, allowedKeys) { - if (typeof allowedKeys === "undefined") { - if (POINTER_EVENT_TYPE_REGEX.test(event.type)) { - return isSimpleClick(event); - } else { - allowedKeys = ''; - } - } - - if (allowedKeys.indexOf("any") >= 0) { - return true; - } - - var allowed = true; - - forEach.call(keys, function(key) { - if (event[key + "Key"] && allowedKeys.indexOf(key) === -1) { - allowed = false; - } - }); - - return allowed; - }; - - function isKeyEvent(eventName) { - return ['keyUp', 'keyPress', 'keyDown'].indexOf(eventName) !== -1; - } - - function ignoreKeyEvent(eventName, event, keyCode) { - var any = 'any'; - keyCode = keyCode || any; - return isKeyEvent(eventName) && keyCode !== any && keyCode !== event.which.toString(); - } - - ActionHelper.registerAction = function(actionNameOrPath, options, allowedKeys) { - var actionId = uuid(); - - ActionManager.registeredActions[actionId] = { - eventName: options.eventName, - handler: function handleRegisteredAction(event) { - if (!isAllowedEvent(event, allowedKeys)) { return true; } - - if (options.preventDefault !== false) { - event.preventDefault(); - } - - if (options.bubbles === false) { - event.stopPropagation(); - } - - var target = options.target; - var parameters = options.parameters; - var eventName = options.eventName; - var actionName; - - - if (target.target) { - target = handlebarsGet(target.root, target.target, target.options); - } else { - target = target.root; - } - - if (options.boundProperty) { - actionName = resolveParams(parameters.context, [actionNameOrPath], { types: ['ID'], data: parameters.options.data })[0]; - - if (typeof actionName === 'undefined' || typeof actionName === 'function') { - Ember.deprecate("You specified a quoteless path to the {{action}} helper '" + actionNameOrPath + "' which did not resolve to an actionName. Perhaps you meant to use a quoted actionName? (e.g. {{action '" + actionNameOrPath + "'}})."); - actionName = actionNameOrPath; - } - } - - if (!actionName) { - actionName = actionNameOrPath; - } - - run(function runRegisteredAction() { - if (target.send) { - target.send.apply(target, args(parameters, actionName)); - } else { - Ember.assert("The action '" + actionName + "' did not exist on " + target, typeof target[actionName] === 'function'); - target[actionName].apply(target, args(parameters)); - } - }); - } - }; - - options.view.on('willClearRender', function() { - delete ActionManager.registeredActions[actionId]; - }); - - return actionId; - }; - - /** - - The `{{action}}` helper provides a useful shortcut for registering an HTML - element within a template for a single DOM event and forwarding that - interaction to the template's controller or specified `target` option. - - If the controller does not implement the specified action, the event is sent - to the current route, and it bubbles up the route hierarchy from there. - - For more advanced event handling see [Ember.Component](/api/classes/Ember.Component.html) - - - ### Use - Given the following application Handlebars template on the page - - ```handlebars -
    - click me -
    - ``` - - And application code - - ```javascript - App.ApplicationController = Ember.Controller.extend({ - actions: { - anActionName: function() { - } - } - }); - ``` - - Will result in the following rendered HTML - - ```html -
    -
    - click me -
    -
    - ``` - - Clicking "click me" will trigger the `anActionName` action of the - `App.ApplicationController`. In this case, no additional parameters will be passed. - - If you provide additional parameters to the helper: - - ```handlebars - - ``` - - Those parameters will be passed along as arguments to the JavaScript - function implementing the action. - - ### Event Propagation - - Events triggered through the action helper will automatically have - `.preventDefault()` called on them. You do not need to do so in your event - handlers. If you need to allow event propagation (to handle file inputs for - example) you can supply the `preventDefault=false` option to the `{{action}}` helper: - - ```handlebars -
    - - -
    - ``` - - To disable bubbling, pass `bubbles=false` to the helper: - - ```handlebars - - ``` - - If you need the default handler to trigger you should either register your - own event handler, or use event methods on your view class. See [Ember.View](/api/classes/Ember.View.html) - 'Responding to Browser Events' for more information. - - ### Specifying DOM event type - - By default the `{{action}}` helper registers for DOM `click` events. You can - supply an `on` option to the helper to specify a different DOM event name: - - ```handlebars -
    - click me -
    - ``` - - See `Ember.View` 'Responding to Browser Events' for a list of - acceptable DOM event names. - - ### Specifying whitelisted modifier keys - - By default the `{{action}}` helper will ignore click event with pressed modifier - keys. You can supply an `allowedKeys` option to specify which keys should not be ignored. - - ```handlebars -
    - click me -
    - ``` - - This way the `{{action}}` will fire when clicking with the alt key pressed down. - - Alternatively, supply "any" to the `allowedKeys` option to accept any combination of modifier keys. - - ```handlebars -
    - click me with any key pressed -
    - ``` - - ### Specifying a Target - - There are several possible target objects for `{{action}}` helpers: - - In a typical Ember application, where templates are managed through use of the - `{{outlet}}` helper, actions will bubble to the current controller, then - to the current route, and then up the route hierarchy. - - Alternatively, a `target` option can be provided to the helper to change - which object will receive the method call. This option must be a path - to an object, accessible in the current context: - - ```handlebars - {{! the application template }} -
    - click me -
    - ``` - - ```javascript - App.ApplicationView = Ember.View.extend({ - actions: { - anActionName: function(){} - } - }); - - ``` - - ### Additional Parameters - - You may specify additional parameters to the `{{action}}` helper. These - parameters are passed along as the arguments to the JavaScript function - implementing the action. - - ```handlebars - {{#each person in people}} -
    - click me -
    - {{/each}} - ``` - - Clicking "click me" will trigger the `edit` method on the current controller - with the value of `person` as a parameter. - - @method action - @for Ember.Handlebars.helpers - @param {String} actionName - @param {Object} [context]* - @param {Hash} options - */ - function actionHelper(actionName) { - var options = arguments[arguments.length - 1]; - var contexts = a_slice.call(arguments, 1, -1); - var hash = options.hash; - var controller = options.data.keywords.controller; - - // create a hash to pass along to registerAction - var action = { - eventName: hash.on || "click", - parameters: { - context: this, - options: options, - params: contexts - }, - view: options.data.view, - bubbles: hash.bubbles, - preventDefault: hash.preventDefault, - target: { options: options }, - withKeyCode: hash.withKeyCode, - boundProperty: options.types[0] === "ID" - }; - - if (hash.target) { - action.target.root = this; - action.target.target = hash.target; - } else if (controller) { - action.target.root = controller; - } - - var actionId = ActionHelper.registerAction(actionName, action, hash.allowedKeys); - return new SafeString('data-ember-action="' + actionId + '"'); - } - - __exports__.actionHelper = actionHelper; - }); -enifed("ember-routing-handlebars/helpers/link_to", - ["ember-metal/core","ember-metal/property_get","ember-metal/property_set","ember-metal/merge","ember-metal/run_loop","ember-metal/computed","ember-runtime/system/lazy_load","ember-runtime/system/string","ember-runtime/system/object","ember-metal/keys","ember-views/system/utils","ember-views/views/component","ember-handlebars","ember-handlebars/helpers/view","ember-routing/system/router","ember-routing-handlebars/helpers/shared","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __dependency11__, __dependency12__, __dependency13__, __dependency14__, __dependency15__, __dependency16__, __exports__) { - "use strict"; - var Ember = __dependency1__["default"]; - // FEATURES, Logger, Handlebars, warn, assert - var get = __dependency2__.get; - var set = __dependency3__.set; - var merge = __dependency4__["default"]; - var run = __dependency5__["default"]; - var computed = __dependency6__.computed; - - var onLoad = __dependency7__.onLoad; - var fmt = __dependency8__.fmt; - var EmberObject = __dependency9__["default"]; - var keys = __dependency10__["default"]; - var isSimpleClick = __dependency11__.isSimpleClick; - var EmberComponent = __dependency12__["default"]; - var EmberHandlebars = __dependency13__["default"]; - var viewHelper = __dependency14__.viewHelper; - var EmberRouter = __dependency15__["default"]; - var resolveParams = __dependency16__.resolveParams; - var resolvePaths = __dependency16__.resolvePaths; - var routeArgs = __dependency16__.routeArgs; - - /** - @module ember - @submodule ember-routing - */ - - var slice = [].slice; - - requireModule('ember-handlebars'); - - var numberOfContextsAcceptedByHandler = function(handler, handlerInfos) { - var req = 0; - for (var i = 0, l = handlerInfos.length; i < l; i++) { - req = req + handlerInfos[i].names.length; - if (handlerInfos[i].handler === handler) - break; - } - - return req; - }; - - var QueryParams = EmberObject.extend({ - values: null - }); - - function getResolvedPaths(options) { - - var types = options.options.types; - var data = options.options.data; - - return resolvePaths(options.context, options.params, { types: types, data: data }); - } - - /** - `Ember.LinkView` renders an element whose `click` event triggers a - transition of the application's instance of `Ember.Router` to - a supplied route by name. - - Instances of `LinkView` will most likely be created through - the `link-to` Handlebars helper, but properties of this class - can be overridden to customize application-wide behavior. - - @class LinkView - @namespace Ember - @extends Ember.View - @see {Handlebars.helpers.link-to} - **/ - var LinkView = Ember.LinkView = EmberComponent.extend({ - tagName: 'a', - - /** - @deprecated Use current-when instead. - @property currentWhen - */ - currentWhen: null, - - /** - Used to determine when this LinkView is active. - - @property currentWhen - */ - 'current-when': null, - - /** - Sets the `title` attribute of the `LinkView`'s HTML element. - - @property title - @default null - **/ - title: null, - - /** - Sets the `rel` attribute of the `LinkView`'s HTML element. - - @property rel - @default null - **/ - rel: null, - - /** - The CSS class to apply to `LinkView`'s element when its `active` - property is `true`. - - @property activeClass - @type String - @default active - **/ - activeClass: 'active', - - /** - The CSS class to apply to `LinkView`'s element when its `loading` - property is `true`. - - @property loadingClass - @type String - @default loading - **/ - loadingClass: 'loading', - - /** - The CSS class to apply to a `LinkView`'s element when its `disabled` - property is `true`. - - @property disabledClass - @type String - @default disabled - **/ - disabledClass: 'disabled', - _isDisabled: false, - - /** - Determines whether the `LinkView` will trigger routing via - the `replaceWith` routing strategy. - - @property replace - @type Boolean - @default false - **/ - replace: false, - - /** - By default the `{{link-to}}` helper will bind to the `href` and - `title` attributes. It's discourage that you override these defaults, - however you can push onto the array if needed. - - @property attributeBindings - @type Array | String - @default ['href', 'title', 'rel'] - **/ - attributeBindings: ['href', 'title', 'rel', 'tabindex'], - - /** - By default the `{{link-to}}` helper will bind to the `active`, `loading`, and - `disabled` classes. It is discouraged to override these directly. - - @property classNameBindings - @type Array - @default ['active', 'loading', 'disabled'] - **/ - classNameBindings: ['active', 'loading', 'disabled'], - - /** - By default the `{{link-to}}` helper responds to the `click` event. You - can override this globally by setting this property to your custom - event name. - - This is particularly useful on mobile when one wants to avoid the 300ms - click delay using some sort of custom `tap` event. - - @property eventName - @type String - @default click - */ - eventName: 'click', - - // this is doc'ed here so it shows up in the events - // section of the API documentation, which is where - // people will likely go looking for it. - /** - Triggers the `LinkView`'s routing behavior. If - `eventName` is changed to a value other than `click` - the routing behavior will trigger on that custom event - instead. - - @event click - **/ - - /** - An overridable method called when LinkView objects are instantiated. - - Example: - - ```javascript - App.MyLinkView = Ember.LinkView.extend({ - init: function() { - this._super(); - Ember.Logger.log('Event is ' + this.get('eventName')); - } - }); - ``` - - NOTE: If you do override `init` for a framework class like `Ember.View` or - `Ember.ArrayController`, be sure to call `this._super()` in your - `init` declaration! If you don't, Ember may not have an opportunity to - do important setup work, and you'll see strange behavior in your - application. - - @method init - */ - init: function() { - this._super.apply(this, arguments); - - Ember.deprecate('Using currentWhen with {{link-to}} is deprecated in favor of `current-when`.', !this.currentWhen); - - // Map desired event name to invoke function - var eventName = get(this, 'eventName'); - this.on(eventName, this, this._invoke); - }, - - /** - This method is invoked by observers installed during `init` that fire - whenever the params change - - @private - @method _paramsChanged - @since 1.3.0 - */ - _paramsChanged: function() { - this.notifyPropertyChange('resolvedParams'); - }, - - /** - This is called to setup observers that will trigger a rerender. - - @private - @method _setupPathObservers - @since 1.3.0 - **/ - _setupPathObservers: function(){ - var helperParameters = this.parameters; - var linkTextPath = helperParameters.options.linkTextPath; - var paths = getResolvedPaths(helperParameters); - var length = paths.length; - var path, i, normalizedPath; - - if (linkTextPath) { - normalizedPath = getNormalizedPath(linkTextPath, helperParameters); - this.registerObserver(normalizedPath.root, normalizedPath.path, this, this.rerender); - } - - for(i=0; i < length; i++) { - path = paths[i]; - if (null === path) { - // A literal value was provided, not a path, so nothing to observe. - continue; - } - - normalizedPath = getNormalizedPath(path, helperParameters); - this.registerObserver(normalizedPath.root, normalizedPath.path, this, this._paramsChanged); - } - - var queryParamsObject = this.queryParamsObject; - if (queryParamsObject) { - var values = queryParamsObject.values; - - // Install observers for all of the hash options - // provided in the (query-params) subexpression. - for (var k in values) { - if (!values.hasOwnProperty(k)) { continue; } - - if (queryParamsObject.types[k] === 'ID') { - normalizedPath = getNormalizedPath(values[k], helperParameters); - this.registerObserver(normalizedPath.root, normalizedPath.path, this, this._paramsChanged); - } - } - } - }, - - afterRender: function(){ - this._super.apply(this, arguments); - this._setupPathObservers(); - }, - - /** - - Accessed as a classname binding to apply the `LinkView`'s `disabledClass` - CSS `class` to the element when the link is disabled. - - When `true` interactions with the element will not trigger route changes. - @property disabled - */ - disabled: computed(function computeLinkViewDisabled(key, value) { - if (value !== undefined) { this.set('_isDisabled', value); } - - return value ? get(this, 'disabledClass') : false; - }), - - /** - Accessed as a classname binding to apply the `LinkView`'s `activeClass` - CSS `class` to the element when the link is active. - - A `LinkView` is considered active when its `currentWhen` property is `true` - or the application's current route is the route the `LinkView` would trigger - transitions into. - - The `currentWhen` property can match against multiple routes by separating - route names using the ` ` (space) character. - - @property active - **/ - active: computed('loadedParams', function computeLinkViewActive() { - if (get(this, 'loading')) { return false; } - - var router = get(this, 'router'); - var loadedParams = get(this, 'loadedParams'); - var contexts = loadedParams.models; - var currentWhen = this['current-when'] || this.currentWhen; - var isCurrentWhenSpecified = Boolean(currentWhen); - currentWhen = currentWhen || loadedParams.targetRouteName; - - function isActiveForRoute(routeName) { - var handlers = router.router.recognizer.handlersFor(routeName); - var leafName = handlers[handlers.length-1].handler; - var maximumContexts = numberOfContextsAcceptedByHandler(routeName, handlers); - - // NOTE: any ugliness in the calculation of activeness is largely - // due to the fact that we support automatic normalizing of - // `resource` -> `resource.index`, even though there might be - // dynamic segments / query params defined on `resource.index` - // which complicates (and makes somewhat ambiguous) the calculation - // of activeness for links that link to `resource` instead of - // directly to `resource.index`. - - // if we don't have enough contexts revert back to full route name - // this is because the leaf route will use one of the contexts - if (contexts.length > maximumContexts) { - routeName = leafName; - } - - var args = routeArgs(routeName, contexts, null); - var isActive = router.isActive.apply(router, args); - if (!isActive) { return false; } - - var emptyQueryParams = Ember.isEmpty(Ember.keys(loadedParams.queryParams)); - - if (!isCurrentWhenSpecified && !emptyQueryParams && isActive) { - var visibleQueryParams = {}; - merge(visibleQueryParams, loadedParams.queryParams); - router._prepareQueryParams(loadedParams.targetRouteName, loadedParams.models, visibleQueryParams); - isActive = shallowEqual(visibleQueryParams, router.router.state.queryParams); - } - - return isActive; - } - - - currentWhen = currentWhen.split(' '); - for (var i = 0, len = currentWhen.length; i < len; i++) { - if (isActiveForRoute(currentWhen[i])) { - return get(this, 'activeClass'); - } - } - }), - - /** - Accessed as a classname binding to apply the `LinkView`'s `loadingClass` - CSS `class` to the element when the link is loading. - - A `LinkView` is considered loading when it has at least one - parameter whose value is currently null or undefined. During - this time, clicking the link will perform no transition and - emit a warning that the link is still in a loading state. - - @property loading - **/ - loading: computed('loadedParams', function computeLinkViewLoading() { - if (!get(this, 'loadedParams')) { return get(this, 'loadingClass'); } - }), - - /** - Returns the application's main router from the container. - - @private - @property router - **/ - router: computed(function() { - var controller = get(this, 'controller'); - if (controller && controller.container) { - return controller.container.lookup('router:main'); - } - }), - - /** - Event handler that invokes the link, activating the associated route. - - @private - @method _invoke - @param {Event} event - */ - _invoke: function(event) { - if (!isSimpleClick(event)) { return true; } - - if (this.preventDefault !== false) { - - var targetAttribute = get(this, 'target'); - if (!targetAttribute || targetAttribute === '_self') { - event.preventDefault(); - } - } - - if (this.bubbles === false) { event.stopPropagation(); } - - if (get(this, '_isDisabled')) { return false; } - - if (get(this, 'loading')) { - Ember.Logger.warn("This link-to is in an inactive loading state because at least one of its parameters presently has a null/undefined value, or the provided route name is invalid."); - return false; - } - - - var targetAttribute2 = get(this, 'target'); - if (targetAttribute2 && targetAttribute2 !== '_self') { - return false; - } - - - var router = get(this, 'router'); - var loadedParams = get(this, 'loadedParams'); - - var transition = router._doTransition(loadedParams.targetRouteName, loadedParams.models, loadedParams.queryParams); - if (get(this, 'replace')) { - transition.method('replace'); - } - - // Schedule eager URL update, but after we've given the transition - // a chance to synchronously redirect. - // We need to always generate the URL instead of using the href because - // the href will include any rootURL set, but the router expects a URL - // without it! Note that we don't use the first level router because it - // calls location.formatURL(), which also would add the rootURL! - var args = routeArgs(loadedParams.targetRouteName, loadedParams.models, transition.state.queryParams); - var url = router.router.generate.apply(router.router, args); - - run.scheduleOnce('routerTransitions', this, this._eagerUpdateUrl, transition, url); - }, - - /** - @private - @method _eagerUpdateUrl - @param transition - @param href - */ - _eagerUpdateUrl: function(transition, href) { - if (!transition.isActive || !transition.urlMethod) { - // transition was aborted, already ran to completion, - // or it has a null url-updated method. - return; - } - - if (href.indexOf('#') === 0) { - href = href.slice(1); - } - - // Re-use the routerjs hooks set up by the Ember router. - var routerjs = get(this, 'router.router'); - if (transition.urlMethod === 'update') { - routerjs.updateURL(href); - } else if (transition.urlMethod === 'replace') { - routerjs.replaceURL(href); - } - - // Prevent later update url refire. - transition.method(null); - }, - - /** - Computed property that returns an array of the - resolved parameters passed to the `link-to` helper, - e.g.: - - ```hbs - {{link-to a b '123' c}} - ``` - - will generate a `resolvedParams` of: - - ```js - [aObject, bObject, '123', cObject] - ``` - - @private - @property - @return {Array} - */ - resolvedParams: computed('router.url', function() { - var parameters = this.parameters; - var options = parameters.options; - var types = options.types; - var data = options.data; - var targetRouteName, models; - var onlyQueryParamsSupplied = (parameters.params.length === 0); - - if (onlyQueryParamsSupplied) { - var appController = this.container.lookup('controller:application'); - targetRouteName = get(appController, 'currentRouteName'); - models = []; - } else { - models = resolveParams(parameters.context, parameters.params, { types: types, data: data }); - targetRouteName = models.shift(); - } - - var suppliedQueryParams = getResolvedQueryParams(this, targetRouteName); - - return { - targetRouteName: targetRouteName, - models: models, - queryParams: suppliedQueryParams - }; - }), - - /** - Computed property that returns the current route name, - dynamic segments, and query params. Returns falsy if - for null/undefined params to indicate that the link view - is still in a loading state. - - @private - @property - @return {Array} An array with the route name and any dynamic segments - **/ - loadedParams: computed('resolvedParams', function computeLinkViewRouteArgs() { - var router = get(this, 'router'); - if (!router) { return; } - - var resolvedParams = get(this, 'resolvedParams'); - var namedRoute = resolvedParams.targetRouteName; - - if (!namedRoute) { return; } - - Ember.assert(fmt("The attempt to link-to route '%@' failed. " + - "The router did not find '%@' in its possible routes: '%@'", - [namedRoute, namedRoute, keys(router.router.recognizer.names).join("', '")]), - router.hasRoute(namedRoute)); - - if (!paramsAreLoaded(resolvedParams.models)) { return; } - - return resolvedParams; - }), - - queryParamsObject: null, - - /** - Sets the element's `href` attribute to the url for - the `LinkView`'s targeted route. - - If the `LinkView`'s `tagName` is changed to a value other - than `a`, this property will be ignored. - - @property href - **/ - href: computed('loadedParams', function computeLinkViewHref() { - if (get(this, 'tagName') !== 'a') { return; } - - var router = get(this, 'router'); - var loadedParams = get(this, 'loadedParams'); - - if (!loadedParams) { - return get(this, 'loadingHref'); - } - - var visibleQueryParams = {}; - merge(visibleQueryParams, loadedParams.queryParams); - router._prepareQueryParams(loadedParams.targetRouteName, loadedParams.models, visibleQueryParams); - - var args = routeArgs(loadedParams.targetRouteName, loadedParams.models, visibleQueryParams); - var result = router.generate.apply(router, args); - return result; - }), - - /** - The default href value to use while a link-to is loading. - Only applies when tagName is 'a' - - @property loadingHref - @type String - @default # - */ - loadingHref: '#' - }); - - LinkView.toString = function() { return "LinkView"; }; - - - LinkView.reopen({ - attributeBindings: ['target'], - - /** - Sets the `target` attribute of the `LinkView`'s anchor element. - - @property target - @default null - **/ - target: null - }); - - - /** - The `{{link-to}}` helper renders a link to the supplied - `routeName` passing an optionally supplied model to the - route as its `model` context of the route. The block - for `{{link-to}}` becomes the innerHTML of the rendered - element: - - ```handlebars - {{#link-to 'photoGallery'}} - Great Hamster Photos - {{/link-to}} - ``` - - ```html - - Great Hamster Photos - - ``` - - ### Supplying a tagName - By default `{{link-to}}` renders an `` element. This can - be overridden for a single use of `{{link-to}}` by supplying - a `tagName` option: - - ```handlebars - {{#link-to 'photoGallery' tagName="li"}} - Great Hamster Photos - {{/link-to}} - ``` - - ```html -
  • - Great Hamster Photos -
  • - ``` - - To override this option for your entire application, see - "Overriding Application-wide Defaults". - - ### Disabling the `link-to` helper - By default `{{link-to}}` is enabled. - any passed value to `disabled` helper property will disable the `link-to` helper. - - static use: the `disabled` option: - - ```handlebars - {{#link-to 'photoGallery' disabled=true}} - Great Hamster Photos - {{/link-to}} - ``` - - dynamic use: the `disabledWhen` option: - - ```handlebars - {{#link-to 'photoGallery' disabledWhen=controller.someProperty}} - Great Hamster Photos - {{/link-to}} - ``` - - any passed value to `disabled` will disable it except `undefined`. - to ensure that only `true` disable the `link-to` helper you can - override the global behaviour of `Ember.LinkView`. - - ```javascript - Ember.LinkView.reopen({ - disabled: Ember.computed(function(key, value) { - if (value !== undefined) { - this.set('_isDisabled', value === true); - } - return value === true ? get(this, 'disabledClass') : false; - }) - }); - ``` - - see "Overriding Application-wide Defaults" for more. - - ### Handling `href` - `{{link-to}}` will use your application's Router to - fill the element's `href` property with a url that - matches the path to the supplied `routeName` for your - routers's configured `Location` scheme, which defaults - to Ember.HashLocation. - - ### Handling current route - `{{link-to}}` will apply a CSS class name of 'active' - when the application's current route matches - the supplied routeName. For example, if the application's - current route is 'photoGallery.recent' the following - use of `{{link-to}}`: - - ```handlebars - {{#link-to 'photoGallery.recent'}} - Great Hamster Photos from the last week - {{/link-to}} - ``` - - will result in - - ```html -
    - Great Hamster Photos - - ``` - - The CSS class name used for active classes can be customized - for a single use of `{{link-to}}` by passing an `activeClass` - option: - - ```handlebars - {{#link-to 'photoGallery.recent' activeClass="current-url"}} - Great Hamster Photos from the last week - {{/link-to}} - ``` - - ```html - - Great Hamster Photos - - ``` - - To override this option for your entire application, see - "Overriding Application-wide Defaults". - - ### Supplying a model - An optional model argument can be used for routes whose - paths contain dynamic segments. This argument will become - the model context of the linked route: - - ```javascript - App.Router.map(function() { - this.resource("photoGallery", {path: "hamster-photos/:photo_id"}); - }); - ``` - - ```handlebars - {{#link-to 'photoGallery' aPhoto}} - {{aPhoto.title}} - {{/link-to}} - ``` - - ```html - - Tomster - - ``` - - ### Supplying multiple models - For deep-linking to route paths that contain multiple - dynamic segments, multiple model arguments can be used. - As the router transitions through the route path, each - supplied model argument will become the context for the - route with the dynamic segments: - - ```javascript - App.Router.map(function() { - this.resource("photoGallery", {path: "hamster-photos/:photo_id"}, function() { - this.route("comment", {path: "comments/:comment_id"}); - }); - }); - ``` - This argument will become the model context of the linked route: - - ```handlebars - {{#link-to 'photoGallery.comment' aPhoto comment}} - {{comment.body}} - {{/link-to}} - ``` - - ```html - - A+++ would snuggle again. - - ``` - - ### Supplying an explicit dynamic segment value - If you don't have a model object available to pass to `{{link-to}}`, - an optional string or integer argument can be passed for routes whose - paths contain dynamic segments. This argument will become the value - of the dynamic segment: - - ```javascript - App.Router.map(function() { - this.resource("photoGallery", {path: "hamster-photos/:photo_id"}); - }); - ``` - - ```handlebars - {{#link-to 'photoGallery' aPhotoId}} - {{aPhoto.title}} - {{/link-to}} - ``` - - ```html - - Tomster - - ``` - - When transitioning into the linked route, the `model` hook will - be triggered with parameters including this passed identifier. - - ### Allowing Default Action - - By default the `{{link-to}}` helper prevents the default browser action - by calling `preventDefault()` as this sort of action bubbling is normally - handled internally and we do not want to take the browser to a new URL (for - example). - - If you need to override this behavior specify `preventDefault=false` in - your template: - - ```handlebars - {{#link-to 'photoGallery' aPhotoId preventDefault=false}} - {{aPhotoId.title}} - {{/link-to}} - ``` - - ### Overriding attributes - You can override any given property of the Ember.LinkView - that is generated by the `{{link-to}}` helper by passing - key/value pairs, like so: - - ```handlebars - {{#link-to aPhoto tagName='li' title='Following this link will change your life' classNames='pic sweet'}} - Uh-mazing! - {{/link-to}} - ``` - - See [Ember.LinkView](/api/classes/Ember.LinkView.html) for a - complete list of overrideable properties. Be sure to also - check out inherited properties of `LinkView`. - - ### Overriding Application-wide Defaults - ``{{link-to}}`` creates an instance of Ember.LinkView - for rendering. To override options for your entire - application, reopen Ember.LinkView and supply the - desired values: - - ``` javascript - Ember.LinkView.reopen({ - activeClass: "is-active", - tagName: 'li' - }) - ``` - - It is also possible to override the default event in - this manner: - - ``` javascript - Ember.LinkView.reopen({ - eventName: 'customEventName' - }); - ``` - - @method link-to - @for Ember.Handlebars.helpers - @param {String} routeName - @param {Object} [context]* - @param [options] {Object} Handlebars key/value pairs of options, you can override any property of Ember.LinkView - @return {String} HTML string - @see {Ember.LinkView} - */ - function linkToHelper(name) { - var options = slice.call(arguments, -1)[0]; - var params = slice.call(arguments, 0, -1); - var hash = options.hash; - - Ember.assert("You must provide one or more parameters to the link-to helper.", params.length); - - if (params[params.length - 1] instanceof QueryParams) { - hash.queryParamsObject = params.pop(); - } - - hash.disabledBinding = hash.disabledWhen; - - if (!options.fn) { - var linkTitle = params.shift(); - var linkType = options.types.shift(); - var context = this; - if (linkType === 'ID') { - options.linkTextPath = linkTitle; - options.fn = function() { - return EmberHandlebars.getEscaped(context, linkTitle, options); - }; - } else { - options.fn = function() { - return linkTitle; - }; - } - } - - hash.parameters = { - context: this, - options: options, - params: params - }; - - options.helperName = options.helperName || 'link-to'; - - return viewHelper.call(this, LinkView, options); - } - - /** - @method query-params - @for Ember.Handlebars.helpers - @param {Object} hash takes a hash of query parameters - @return {String} HTML string - */ - function queryParamsHelper(options) { - Ember.assert(fmt("The `query-params` helper only accepts hash parameters, e.g. (query-params queryParamPropertyName='%@') as opposed to just (query-params '%@')", [options, options]), arguments.length === 1); - - return QueryParams.create({ - values: options.hash, - types: options.hashTypes - }); - } - - __exports__.queryParamsHelper = queryParamsHelper;/** - See [link-to](/api/classes/Ember.Handlebars.helpers.html#method_link-to) - - @method linkTo - @for Ember.Handlebars.helpers - @deprecated - @param {String} routeName - @param {Object} [context]* - @return {String} HTML string - */ - function deprecatedLinkToHelper() { - Ember.warn("The 'linkTo' view helper is deprecated in favor of 'link-to'"); - return linkToHelper.apply(this, arguments); - } - - function getResolvedQueryParams(linkView, targetRouteName) { - var helperParameters = linkView.parameters; - var queryParamsObject = linkView.queryParamsObject; - var resolvedQueryParams = {}; - - if (!queryParamsObject) { return resolvedQueryParams; } - var rawParams = queryParamsObject.values; - - for (var key in rawParams) { - if (!rawParams.hasOwnProperty(key)) { continue; } - - var value = rawParams[key]; - var type = queryParamsObject.types[key]; - - if (type === 'ID') { - var normalizedPath = getNormalizedPath(value, helperParameters); - value = EmberHandlebars.get(normalizedPath.root, normalizedPath.path, helperParameters.options); - } - resolvedQueryParams[key] = value; - } - return resolvedQueryParams; - } - - function getNormalizedPath(path, helperParameters) { - return EmberHandlebars.normalizePath(helperParameters.context, path, helperParameters.options.data); - } - - function paramsAreLoaded(params) { - for (var i = 0, len = params.length; i < len; ++i) { - var param = params[i]; - if (param === null || typeof param === 'undefined') { - return false; - } - } - return true; - } - - function shallowEqual(a, b) { - var k; - for (k in a) { - if (a.hasOwnProperty(k) && a[k] !== b[k]) { return false; } - } - for (k in b) { - if (b.hasOwnProperty(k) && a[k] !== b[k]) { return false; } - } - return true; - } - - __exports__.LinkView = LinkView; - __exports__.deprecatedLinkToHelper = deprecatedLinkToHelper; - __exports__.linkToHelper = linkToHelper; - }); -enifed("ember-routing-handlebars/helpers/outlet", - ["ember-metal/core","ember-metal/property_get","ember-metal/property_set","ember-runtime/system/lazy_load","ember-views/views/container_view","ember-handlebars/views/metamorph_view","ember-handlebars/helpers/view","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __exports__) { - "use strict"; - var Ember = __dependency1__["default"]; - // assert - var get = __dependency2__.get; - var set = __dependency3__.set; - var onLoad = __dependency4__.onLoad; - var ContainerView = __dependency5__["default"]; - var _Metamorph = __dependency6__._Metamorph; - var viewHelper = __dependency7__.viewHelper; - - /** - @module ember - @submodule ember-routing - */ - - /** - @module ember - @submodule ember-routing - */ - - var OutletView = ContainerView.extend(_Metamorph); - __exports__.OutletView = OutletView; - /** - The `outlet` helper is a placeholder that the router will fill in with - the appropriate template based on the current state of the application. - - ``` handlebars - {{outlet}} - ``` - - By default, a template based on Ember's naming conventions will be rendered - into the `outlet` (e.g. `App.PostsRoute` will render the `posts` template). - - You can render a different template by using the `render()` method in the - route's `renderTemplate` hook. The following will render the `favoritePost` - template into the `outlet`. - - ``` javascript - App.PostsRoute = Ember.Route.extend({ - renderTemplate: function() { - this.render('favoritePost'); - } - }); - ``` - - You can create custom named outlets for more control. - - ``` handlebars - {{outlet 'favoritePost'}} - {{outlet 'posts'}} - ``` - - Then you can define what template is rendered into each outlet in your - route. - - - ``` javascript - App.PostsRoute = Ember.Route.extend({ - renderTemplate: function() { - this.render('favoritePost', { outlet: 'favoritePost' }); - this.render('posts', { outlet: 'posts' }); - } - }); - ``` - - You can specify the view that the outlet uses to contain and manage the - templates rendered into it. - - ``` handlebars - {{outlet view='sectionContainer'}} - ``` - - ``` javascript - App.SectionContainer = Ember.ContainerView.extend({ - tagName: 'section', - classNames: ['special'] - }); - ``` - - @method outlet - @for Ember.Handlebars.helpers - @param {String} property the property on the controller - that holds the view for this outlet - @return {String} HTML string - */ - function outletHelper(property, options) { - var outletSource; - var container; - var viewName; - var viewClass; - var viewFullName; - - if (property && property.data && property.data.isRenderData) { - options = property; - property = 'main'; - } - - container = options.data.view.container; - - outletSource = options.data.view; - while (!outletSource.get('template.isTop')) { - outletSource = outletSource.get('_parentView'); - } - - // provide controller override - viewName = options.hash.view; - - if (viewName) { - viewFullName = 'view:' + viewName; - Ember.assert("Using a quoteless view parameter with {{outlet}} is not supported. Please update to quoted usage '{{outlet \"" + viewName + "\"}}.", options.hashTypes.view !== 'ID'); - Ember.assert("The view name you supplied '" + viewName + "' did not resolve to a view.", container.has(viewFullName)); - } - - viewClass = viewName ? container.lookupFactory(viewFullName) : options.hash.viewClass || OutletView; - - options.data.view.set('outletSource', outletSource); - options.hash.currentViewBinding = '_view.outletSource._outlets.' + property; - - options.helperName = options.helperName || 'outlet'; - - return viewHelper.call(this, viewClass, options); - } - - __exports__.outletHelper = outletHelper; - }); -enifed("ember-routing-handlebars/helpers/render", - ["ember-metal/core","ember-metal/error","ember-metal/property_get","ember-metal/property_set","ember-runtime/system/string","ember-routing/system/generate_controller","ember-handlebars/ext","ember-handlebars/helpers/view","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __exports__) { - "use strict"; - var Ember = __dependency1__["default"]; - // assert, deprecate - var EmberError = __dependency2__["default"]; - var get = __dependency3__.get; - var set = __dependency4__.set; - var camelize = __dependency5__.camelize; - var generateControllerFactory = __dependency6__.generateControllerFactory; - var generateController = __dependency6__["default"]; - var handlebarsGet = __dependency7__.handlebarsGet; - var ViewHelper = __dependency8__.ViewHelper; - - - /** - @module ember - @submodule ember-routing - */ - - /** - Calling ``{{render}}`` from within a template will insert another - template that matches the provided name. The inserted template will - access its properties on its own controller (rather than the controller - of the parent template). - - If a view class with the same name exists, the view class also will be used. - - Note: A given controller may only be used *once* in your app in this manner. - A singleton instance of the controller will be created for you. - - Example: - - ```javascript - App.NavigationController = Ember.Controller.extend({ - who: "world" - }); - ``` - - ```handlebars - - Hello, {{who}}. - ``` - - ```handelbars - -

    My great app

    - {{render "navigation"}} - ``` - - ```html -

    My great app

    -
    - Hello, world. -
    - ``` - - Optionally you may provide a second argument: a property path - that will be bound to the `model` property of the controller. - - If a `model` property path is specified, then a new instance of the - controller will be created and `{{render}}` can be used multiple times - with the same name. - - For example if you had this `author` template. - - ```handlebars -
    - Written by {{firstName}} {{lastName}}. - Total Posts: {{postCount}} -
    - ``` - - You could render it inside the `post` template using the `render` helper. - - ```handlebars -
    -

    {{title}}

    -
    {{body}}
    - {{render "author" author}} -
    - ``` - - @method render - @for Ember.Handlebars.helpers - @param {String} name - @param {Object?} contextString - @param {Hash} options - @return {String} HTML string - */ - __exports__["default"] = function renderHelper(name, contextString, options) { - var length = arguments.length; - var contextProvided = length === 3; - var container, router, controller, view, context, lookupOptions; - - container = (options || contextString).data.keywords.controller.container; - router = container.lookup('router:main'); - - if (length === 2) { - // use the singleton controller - options = contextString; - contextString = undefined; - Ember.assert("You can only use the {{render}} helper once without a model object as its second argument, as in {{render \"post\" post}}.", !router || !router._lookupActiveView(name)); - } else if (length === 3) { - // create a new controller - context = handlebarsGet(options.contexts[1], contextString, options); - } else { - throw new EmberError("You must pass a templateName to render"); - } - - Ember.deprecate("Using a quoteless parameter with {{render}} is deprecated. Please update to quoted usage '{{render \"" + name + "\"}}.", options.types[0] !== 'ID'); - - // # legacy namespace - name = name.replace(/\//g, '.'); - // \ legacy slash as namespace support - - - view = container.lookup('view:' + name) || container.lookup('view:default'); - - // provide controller override - var controllerName = options.hash.controller || name; - var controllerFullName = 'controller:' + controllerName; - - if (options.hash.controller) { - Ember.assert("The controller name you supplied '" + controllerName + "' did not resolve to a controller.", container.has(controllerFullName)); - } - - var parentController = options.data.keywords.controller; - - // choose name - if (length > 2) { - var factory = container.lookupFactory(controllerFullName) || - generateControllerFactory(container, controllerName, context); - - controller = factory.create({ - model: context, - parentController: parentController, - target: parentController - }); - - view.one('willDestroyElement', function() { - controller.destroy(); - }); - } else { - controller = container.lookup(controllerFullName) || - generateController(container, controllerName); - - controller.setProperties({ - target: parentController, - parentController: parentController - }); - } - - var root = options.contexts[1]; - - if (root) { - view.registerObserver(root, contextString, function() { - controller.set('model', handlebarsGet(root, contextString, options)); - }); - } - - options.hash.viewName = camelize(name); - - var templateName = 'template:' + name; - Ember.assert("You used `{{render '" + name + "'}}`, but '" + name + "' can not be found as either a template or a view.", container.has("view:" + name) || container.has(templateName) || options.fn); - options.hash.template = container.lookup(templateName); - - options.hash.controller = controller; - - if (router && !context) { - router._connectActiveView(name, view); - } - - options.helperName = options.helperName || ('render "' + name + '"'); - - ViewHelper.instanceHelper(this, view, options); - } - }); -enifed("ember-routing-handlebars/helpers/shared", - ["ember-metal/property_get","ember-metal/array","ember-runtime/mixins/controller","ember-handlebars/ext","ember-metal/utils","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __exports__) { - "use strict"; - var get = __dependency1__.get; - var map = __dependency2__.map; - var ControllerMixin = __dependency3__["default"]; - var handlebarsResolve = __dependency4__.resolveParams; - var handlebarsGet = __dependency4__.handlebarsGet; - var typeOf = __dependency5__.typeOf; - var get = __dependency1__.get; - - function routeArgs(targetRouteName, models, queryParams) { - var args = []; - if (typeOf(targetRouteName) === 'string') { - args.push('' + targetRouteName); - } - args.push.apply(args, models); - args.push({ queryParams: queryParams }); - return args; - } - - __exports__.routeArgs = routeArgs;function getActiveTargetName(router) { - var handlerInfos = router.activeTransition ? - router.activeTransition.state.handlerInfos : - router.state.handlerInfos; - return handlerInfos[handlerInfos.length - 1].name; - } - - __exports__.getActiveTargetName = getActiveTargetName;function resolveParams(context, params, options) { - return map.call(resolvePaths(context, params, options), function(path, i) { - if (null === path) { - // Param was string/number, not a path, so just return raw string/number. - return params[i]; - } else { - return handlebarsGet(context, path, options); - } - }); - } - - __exports__.resolveParams = resolveParams;function stashParamNames(router, handlerInfos) { - if (handlerInfos._namesStashed) { return; } - - // This helper exists because router.js/route-recognizer.js awkwardly - // keeps separate a handlerInfo's list of parameter names depending - // on whether a URL transition or named transition is happening. - // Hopefully we can remove this in the future. - var targetRouteName = handlerInfos[handlerInfos.length-1].name; - var recogHandlers = router.router.recognizer.handlersFor(targetRouteName); - var dynamicParent = null; - - for (var i = 0, len = handlerInfos.length; i < len; ++i) { - var handlerInfo = handlerInfos[i]; - var names = recogHandlers[i].names; - - if (names.length) { - dynamicParent = handlerInfo; - } - - handlerInfo._names = names; - - var route = handlerInfo.handler; - route._stashNames(handlerInfo, dynamicParent); - } - - handlerInfos._namesStashed = true; - } - - __exports__.stashParamNames = stashParamNames;function resolvePaths(context, params, options) { - var resolved = handlebarsResolve(context, params, options); - var types = options.types; - - return map.call(resolved, function(object, i) { - if (types[i] === 'ID') { - return unwrap(object, params[i]); - } else { - return null; - } - }); - - function unwrap(object, path) { - if (path === 'controller') { return path; } - - if (ControllerMixin.detect(object)) { - return unwrap(get(object, 'model'), path ? path + '.model' : 'model'); - } else { - return path; - } - } - } - - __exports__.resolvePaths = resolvePaths; - }); -enifed("ember-routing", - ["ember-handlebars","ember-metal/core","ember-routing/ext/run_loop","ember-routing/ext/controller","ember-routing/ext/view","ember-routing/location/api","ember-routing/location/none_location","ember-routing/location/hash_location","ember-routing/location/history_location","ember-routing/location/auto_location","ember-routing/system/generate_controller","ember-routing/system/controller_for","ember-routing/system/dsl","ember-routing/system/router","ember-routing/system/route","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __dependency11__, __dependency12__, __dependency13__, __dependency14__, __dependency15__, __exports__) { - "use strict"; - /** - Ember Routing - - @module ember - @submodule ember-routing - @requires ember-views - */ - - var EmberHandlebars = __dependency1__["default"]; - var Ember = __dependency2__["default"]; - - // ES6TODO: Cleanup modules with side-effects below - - var EmberLocation = __dependency6__["default"]; - var NoneLocation = __dependency7__["default"]; - var HashLocation = __dependency8__["default"]; - var HistoryLocation = __dependency9__["default"]; - var AutoLocation = __dependency10__["default"]; - - var generateControllerFactory = __dependency11__.generateControllerFactory; - var generateController = __dependency11__["default"]; - var controllerFor = __dependency12__["default"]; - var RouterDSL = __dependency13__["default"]; - var Router = __dependency14__["default"]; - var Route = __dependency15__["default"]; - - Ember.Location = EmberLocation; - Ember.AutoLocation = AutoLocation; - Ember.HashLocation = HashLocation; - Ember.HistoryLocation = HistoryLocation; - Ember.NoneLocation = NoneLocation; - - Ember.controllerFor = controllerFor; - Ember.generateControllerFactory = generateControllerFactory; - Ember.generateController = generateController; - Ember.RouterDSL = RouterDSL; - Ember.Router = Router; - Ember.Route = Route; - - __exports__["default"] = Ember; - }); -enifed("ember-routing/ext/controller", - ["ember-metal/core","ember-metal/property_get","ember-metal/property_set","ember-metal/computed","ember-metal/utils","ember-metal/merge","ember-metal/enumerable_utils","ember-runtime/mixins/controller","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __exports__) { - "use strict"; - var Ember = __dependency1__["default"]; - // FEATURES, deprecate - var get = __dependency2__.get; - var set = __dependency3__.set; - var computed = __dependency4__.computed; - var typeOf = __dependency5__.typeOf; - var meta = __dependency5__.meta; - var merge = __dependency6__["default"]; - var map = __dependency7__.map; - - var ControllerMixin = __dependency8__["default"]; - - /** - @module ember - @submodule ember-routing - */ - - ControllerMixin.reopen({ - concatenatedProperties: ['queryParams', '_pCacheMeta'], - - init: function() { - this._super.apply(this, arguments); - listenForQueryParamChanges(this); - }, - - /** - @property queryParams - @public - */ - queryParams: null, - - /** - @property _qpDelegate - @private - */ - _qpDelegate: null, - - /** - @property _normalizedQueryParams - @private - */ - _normalizedQueryParams: computed(function() { - var m = meta(this); - if (m.proto !== this) { - return get(m.proto, '_normalizedQueryParams'); - } - - var queryParams = get(this, 'queryParams'); - if (queryParams._qpMap) { - return queryParams._qpMap; - } - - var qpMap = queryParams._qpMap = {}; - - for (var i = 0, len = queryParams.length; i < len; ++i) { - accumulateQueryParamDescriptors(queryParams[i], qpMap); - } - - return qpMap; - }), - - /** - @property _cacheMeta - @private - */ - _cacheMeta: computed(function() { - var m = meta(this); - if (m.proto !== this) { - return get(m.proto, '_cacheMeta'); - } - - var cacheMeta = {}; - var qpMap = get(this, '_normalizedQueryParams'); - for (var prop in qpMap) { - if (!qpMap.hasOwnProperty(prop)) { continue; } - - var qp = qpMap[prop]; - var scope = qp.scope; - var parts; - - if (scope === 'controller') { - parts = []; - } - - cacheMeta[prop] = { - parts: parts, // provided by route if 'model' scope - values: null, // provided by route - scope: scope, - prefix: "", - def: get(this, prop) - }; - } - - return cacheMeta; - }), - - /** - @method _updateCacheParams - @private - */ - _updateCacheParams: function(params) { - var cacheMeta = get(this, '_cacheMeta'); - for (var prop in cacheMeta) { - if (!cacheMeta.hasOwnProperty(prop)) { continue; } - var propMeta = cacheMeta[prop]; - propMeta.values = params; - - var cacheKey = this._calculateCacheKey(propMeta.prefix, propMeta.parts, propMeta.values); - var cache = this._bucketCache; - - if (cache) { - var value = cache.lookup(cacheKey, prop, propMeta.def); - set(this, prop, value); - } - } - }, - - /** - @method _qpChanged - @private - */ - _qpChanged: function(controller, _prop) { - var prop = _prop.substr(0, _prop.length-3); - var cacheMeta = get(controller, '_cacheMeta'); - var propCache = cacheMeta[prop]; - var cacheKey = controller._calculateCacheKey(propCache.prefix || "", propCache.parts, propCache.values); - var value = get(controller, prop); - - // 1. Update model-dep cache - var cache = this._bucketCache; - if (cache) { - controller._bucketCache.stash(cacheKey, prop, value); - } - - // 2. Notify a delegate (e.g. to fire a qp transition) - var delegate = controller._qpDelegate; - if (delegate) { - delegate(controller, prop); - } - }, - - /** - @method _calculateCacheKey - @private - */ - _calculateCacheKey: function(prefix, _parts, values) { - var parts = _parts || [], suffixes = ""; - for (var i = 0, len = parts.length; i < len; ++i) { - var part = parts[i]; - var value = get(values, part); - suffixes += "::" + part + ":" + value; - } - return prefix + suffixes.replace(ALL_PERIODS_REGEX, '-'); - }, - - /** - Transition the application into another route. The route may - be either a single route or route path: - - ```javascript - aController.transitionToRoute('blogPosts'); - aController.transitionToRoute('blogPosts.recentEntries'); - ``` - - Optionally supply a model for the route in question. The model - will be serialized into the URL using the `serialize` hook of - the route: - - ```javascript - aController.transitionToRoute('blogPost', aPost); - ``` - - If a literal is passed (such as a number or a string), it will - be treated as an identifier instead. In this case, the `model` - hook of the route will be triggered: - - ```javascript - aController.transitionToRoute('blogPost', 1); - ``` - - Multiple models will be applied last to first recursively up the - resource tree. - - ```javascript - App.Router.map(function() { - this.resource('blogPost', {path:':blogPostId'}, function(){ - this.resource('blogComment', {path: ':blogCommentId'}); - }); - }); - - aController.transitionToRoute('blogComment', aPost, aComment); - aController.transitionToRoute('blogComment', 1, 13); - ``` - - It is also possible to pass a URL (a string that starts with a - `/`). This is intended for testing and debugging purposes and - should rarely be used in production code. - - ```javascript - aController.transitionToRoute('/'); - aController.transitionToRoute('/blog/post/1/comment/13'); - ``` - - See also [replaceRoute](/api/classes/Ember.ControllerMixin.html#method_replaceRoute). - - @param {String} name the name of the route or a URL - @param {...Object} models the model(s) or identifier(s) to be used - while transitioning to the route. - @for Ember.ControllerMixin - @method transitionToRoute - */ - transitionToRoute: function() { - // target may be either another controller or a router - var target = get(this, 'target'); - var method = target.transitionToRoute || target.transitionTo; - return method.apply(target, arguments); - }, - - /** - @deprecated - @for Ember.ControllerMixin - @method transitionTo - */ - transitionTo: function() { - Ember.deprecate("transitionTo is deprecated. Please use transitionToRoute."); - return this.transitionToRoute.apply(this, arguments); - }, - - /** - Transition into another route while replacing the current URL, if possible. - This will replace the current history entry instead of adding a new one. - Beside that, it is identical to `transitionToRoute` in all other respects. - - ```javascript - aController.replaceRoute('blogPosts'); - aController.replaceRoute('blogPosts.recentEntries'); - ``` - - Optionally supply a model for the route in question. The model - will be serialized into the URL using the `serialize` hook of - the route: - - ```javascript - aController.replaceRoute('blogPost', aPost); - ``` - - If a literal is passed (such as a number or a string), it will - be treated as an identifier instead. In this case, the `model` - hook of the route will be triggered: - - ```javascript - aController.replaceRoute('blogPost', 1); - ``` - - Multiple models will be applied last to first recursively up the - resource tree. - - ```javascript - App.Router.map(function() { - this.resource('blogPost', {path:':blogPostId'}, function(){ - this.resource('blogComment', {path: ':blogCommentId'}); - }); - }); - - aController.replaceRoute('blogComment', aPost, aComment); - aController.replaceRoute('blogComment', 1, 13); - ``` - - It is also possible to pass a URL (a string that starts with a - `/`). This is intended for testing and debugging purposes and - should rarely be used in production code. - - ```javascript - aController.replaceRoute('/'); - aController.replaceRoute('/blog/post/1/comment/13'); - ``` - - @param {String} name the name of the route or a URL - @param {...Object} models the model(s) or identifier(s) to be used - while transitioning to the route. - @for Ember.ControllerMixin - @method replaceRoute - */ - replaceRoute: function() { - // target may be either another controller or a router - var target = get(this, 'target'); - var method = target.replaceRoute || target.replaceWith; - return method.apply(target, arguments); - }, - - /** - @deprecated - @for Ember.ControllerMixin - @method replaceWith - */ - replaceWith: function() { - Ember.deprecate("replaceWith is deprecated. Please use replaceRoute."); - return this.replaceRoute.apply(this, arguments); - } - }); - - var ALL_PERIODS_REGEX = /\./g; - - function accumulateQueryParamDescriptors(_desc, accum) { - var desc = _desc, tmp; - if (typeOf(desc) === 'string') { - tmp = {}; - tmp[desc] = { as: null }; - desc = tmp; - } - - for (var key in desc) { - if (!desc.hasOwnProperty(key)) { return; } - - var singleDesc = desc[key]; - if (typeOf(singleDesc) === 'string') { - singleDesc = { as: singleDesc }; - } - - tmp = accum[key] || { as: null, scope: 'model' }; - merge(tmp, singleDesc); - - accum[key] = tmp; - } - } - - function listenForQueryParamChanges(controller) { - var qpMap = get(controller, '_normalizedQueryParams'); - for (var prop in qpMap) { - if (!qpMap.hasOwnProperty(prop)) { continue; } - controller.addObserver(prop + '.[]', controller, controller._qpChanged); - } - } - - - __exports__["default"] = ControllerMixin; - }); -enifed("ember-routing/ext/run_loop", - ["ember-metal/run_loop"], - function(__dependency1__) { - "use strict"; - var run = __dependency1__["default"]; - - /** - @module ember - @submodule ember-views - */ - - // Add a new named queue after the 'actions' queue (where RSVP promises - // resolve), which is used in router transitions to prevent unnecessary - // loading state entry if all context promises resolve on the - // 'actions' queue first. - - var queues = run.queues; - run._addQueue('routerTransitions', 'actions'); - }); -enifed("ember-routing/ext/view", - ["ember-metal/property_get","ember-metal/property_set","ember-metal/run_loop","ember-views/views/view","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __exports__) { - "use strict"; - var get = __dependency1__.get; - var set = __dependency2__.set; - var run = __dependency3__["default"]; - var EmberView = __dependency4__["default"]; - - /** - @module ember - @submodule ember-routing - */ - - EmberView.reopen({ - - /** - Sets the private `_outlets` object on the view. - - @method init - */ - init: function() { - set(this, '_outlets', {}); - this._super(); - }, - - /** - Manually fill any of a view's `{{outlet}}` areas with the - supplied view. - - Example - - ```javascript - var MyView = Ember.View.extend({ - template: Ember.Handlebars.compile('Child view: {{outlet "main"}} ') - }); - var myView = MyView.create(); - myView.appendTo('body'); - // The html for myView now looks like: - //
    Child view:
    - - var FooView = Ember.View.extend({ - template: Ember.Handlebars.compile('

    Foo

    ') - }); - var fooView = FooView.create(); - myView.connectOutlet('main', fooView); - // The html for myView now looks like: - //
    Child view: - //

    Foo

    - //
    - ``` - @method connectOutlet - @param {String} outletName A unique name for the outlet - @param {Object} view An Ember.View - */ - connectOutlet: function(outletName, view) { - if (this._pendingDisconnections) { - delete this._pendingDisconnections[outletName]; - } - - if (this._hasEquivalentView(outletName, view)) { - view.destroy(); - return; - } - - var outlets = get(this, '_outlets'); - var container = get(this, 'container'); - var router = container && container.lookup('router:main'); - var renderedName = get(view, 'renderedName'); - - set(outlets, outletName, view); - - if (router && renderedName) { - router._connectActiveView(renderedName, view); - } - }, - - /** - Determines if the view has already been created by checking if - the view has the same constructor, template, and context as the - view in the `_outlets` object. - - @private - @method _hasEquivalentView - @param {String} outletName The name of the outlet we are checking - @param {Object} view An Ember.View - @return {Boolean} - */ - _hasEquivalentView: function(outletName, view) { - var existingView = get(this, '_outlets.'+outletName); - return existingView && - existingView.constructor === view.constructor && - existingView.get('template') === view.get('template') && - existingView.get('context') === view.get('context'); - }, - - /** - Removes an outlet from the view. - - Example - - ```javascript - var MyView = Ember.View.extend({ - template: Ember.Handlebars.compile('Child view: {{outlet "main"}} ') - }); - var myView = MyView.create(); - myView.appendTo('body'); - // myView's html: - //
    Child view:
    - - var FooView = Ember.View.extend({ - template: Ember.Handlebars.compile('

    Foo

    ') - }); - var fooView = FooView.create(); - myView.connectOutlet('main', fooView); - // myView's html: - //
    Child view: - //

    Foo

    - //
    - - myView.disconnectOutlet('main'); - // myView's html: - //
    Child view:
    - ``` - - @method disconnectOutlet - @param {String} outletName The name of the outlet to be removed - */ - disconnectOutlet: function(outletName) { - if (!this._pendingDisconnections) { - this._pendingDisconnections = {}; - } - this._pendingDisconnections[outletName] = true; - run.once(this, '_finishDisconnections'); - }, - - /** - Gets an outlet that is pending disconnection and then - nullifys the object on the `_outlet` object. - - @private - @method _finishDisconnections - */ - _finishDisconnections: function() { - if (this.isDestroyed) return; // _outlets will be gone anyway - var outlets = get(this, '_outlets'); - var pendingDisconnections = this._pendingDisconnections; - this._pendingDisconnections = null; - - for (var outletName in pendingDisconnections) { - set(outlets, outletName, null); - } - } - }); - - __exports__["default"] = EmberView; - }); -enifed("ember-routing/location/api", - ["ember-metal/core","ember-metal/property_get","ember-metal/property_set","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __exports__) { - "use strict"; - var Ember = __dependency1__["default"]; - // deprecate, assert - var get = __dependency2__.get; - var set = __dependency3__.set; - - /** - @module ember - @submodule ember-routing - */ - - /** - Ember.Location returns an instance of the correct implementation of - the `location` API. - - ## Implementations - - You can pass an implementation name (`hash`, `history`, `none`) to force a - particular implementation to be used in your application. - - ### HashLocation - - Using `HashLocation` results in URLs with a `#` (hash sign) separating the - server side URL portion of the URL from the portion that is used by Ember. - This relies upon the `hashchange` event existing in the browser. - - Example: - - ```javascript - App.Router.map(function() { - this.resource('posts', function() { - this.route('new'); - }); - }); - - App.Router.reopen({ - location: 'hash' - }); - ``` - - This will result in a posts.new url of `/#/posts/new`. - - ### HistoryLocation - - Using `HistoryLocation` results in URLs that are indistinguishable from a - standard URL. This relies upon the browser's `history` API. - - Example: - - ```javascript - App.Router.map(function() { - this.resource('posts', function() { - this.route('new'); - }); - }); - - App.Router.reopen({ - location: 'history' - }); - ``` - - This will result in a posts.new url of `/posts/new`. - - Keep in mind that your server must serve the Ember app at all the routes you - define. - - ### AutoLocation - - Using `AutoLocation`, the router will use the best Location class supported by - the browser it is running in. - - Browsers that support the `history` API will use `HistoryLocation`, those that - do not, but still support the `hashchange` event will use `HashLocation`, and - in the rare case neither is supported will use `NoneLocation`. - - Example: - - ```javascript - App.Router.map(function() { - this.resource('posts', function() { - this.route('new'); - }); - }); - - App.Router.reopen({ - location: 'auto' - }); - ``` - - This will result in a posts.new url of `/posts/new` for modern browsers that - support the `history` api or `/#/posts/new` for older ones, like Internet - Explorer 9 and below. - - When a user visits a link to your application, they will be automatically - upgraded or downgraded to the appropriate `Location` class, with the URL - transformed accordingly, if needed. - - Keep in mind that since some of your users will use `HistoryLocation`, your - server must serve the Ember app at all the routes you define. - - ### NoneLocation - - Using `NoneLocation` causes Ember to not store the applications URL state - in the actual URL. This is generally used for testing purposes, and is one - of the changes made when calling `App.setupForTesting()`. - - ## Location API - - Each location implementation must provide the following methods: - - * implementation: returns the string name used to reference the implementation. - * getURL: returns the current URL. - * setURL(path): sets the current URL. - * replaceURL(path): replace the current URL (optional). - * onUpdateURL(callback): triggers the callback when the URL changes. - * formatURL(url): formats `url` to be placed into `href` attribute. - - Calling setURL or replaceURL will not trigger onUpdateURL callbacks. - - @class Location - @namespace Ember - @static - */ - __exports__["default"] = { - /** - This is deprecated in favor of using the container to lookup the location - implementation as desired. - - For example: - - ```javascript - // Given a location registered as follows: - container.register('location:history-test', HistoryTestLocation); - - // You could create a new instance via: - container.lookup('location:history-test'); - ``` - - @method create - @param {Object} options - @return {Object} an instance of an implementation of the `location` API - @deprecated Use the container to lookup the location implementation that you - need. - */ - create: function(options) { - var implementation = options && options.implementation; - Ember.assert("Ember.Location.create: you must specify a 'implementation' option", !!implementation); - - var implementationClass = this.implementations[implementation]; - Ember.assert("Ember.Location.create: " + implementation + " is not a valid implementation", !!implementationClass); - - return implementationClass.create.apply(implementationClass, arguments); - }, - - /** - This is deprecated in favor of using the container to register the - location implementation as desired. - - Example: - - ```javascript - Application.initializer({ - name: "history-test-location", - - initialize: function(container, application) { - application.register('location:history-test', HistoryTestLocation); - } - }); - ``` - - @method registerImplementation - @param {String} name - @param {Object} implementation of the `location` API - @deprecated Register your custom location implementation with the - container directly. - */ - registerImplementation: function(name, implementation) { - Ember.deprecate('Using the Ember.Location.registerImplementation is no longer supported. Register your custom location implementation with the container instead.', false); - - this.implementations[name] = implementation; - }, - - implementations: {}, - _location: window.location, - - /** - Returns the current `location.hash` by parsing location.href since browsers - inconsistently URL-decode `location.hash`. - - https://bugzilla.mozilla.org/show_bug.cgi?id=483304 - - @private - @method getHash - @since 1.4.0 - */ - _getHash: function () { - // AutoLocation has it at _location, HashLocation at .location. - // Being nice and not changing - var href = (this._location || this.location).href; - var hashIndex = href.indexOf('#'); - - if (hashIndex === -1) { - return ''; - } else { - return href.substr(hashIndex); - } - } - }; - }); -enifed("ember-routing/location/auto_location", - ["ember-metal/core","ember-metal/property_get","ember-metal/property_set","ember-routing/location/api","ember-routing/location/history_location","ember-routing/location/hash_location","ember-routing/location/none_location","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __exports__) { - "use strict"; - var Ember = __dependency1__["default"]; - // FEATURES - var get = __dependency2__.get; - var set = __dependency3__.set; - - var EmberLocation = __dependency4__["default"]; - var HistoryLocation = __dependency5__["default"]; - var HashLocation = __dependency6__["default"]; - var NoneLocation = __dependency7__["default"]; - - /** - @module ember - @submodule ember-routing - */ - - /** - Ember.AutoLocation will select the best location option based off browser - support with the priority order: history, hash, none. - - Clean pushState paths accessed by hashchange-only browsers will be redirected - to the hash-equivalent and vice versa so future transitions are consistent. - - Keep in mind that since some of your users will use `HistoryLocation`, your - server must serve the Ember app at all the routes you define. - - @class AutoLocation - @namespace Ember - @static - */ - __exports__["default"] = { - - /** - @private - - This property is used by router:main to know whether to cancel the routing - setup process, which is needed while we redirect the browser. - - @since 1.5.1 - @property cancelRouterSetup - @default false - */ - cancelRouterSetup: false, - - /** - @private - - Will be pre-pended to path upon state change. - - @since 1.5.1 - @property rootURL - @default '/' - */ - rootURL: '/', - - /** - @private - - Attached for mocking in tests - - @since 1.5.1 - @property _window - @default window - */ - _window: window, - - /** - @private - - Attached for mocking in tests - - @property location - @default window.location - */ - _location: window.location, - - /** - @private - - Attached for mocking in tests - - @since 1.5.1 - @property _history - @default window.history - */ - _history: window.history, - - /** - @private - - Attached for mocking in tests - - @since 1.5.1 - @property _HistoryLocation - @default Ember.HistoryLocation - */ - _HistoryLocation: HistoryLocation, - - /** - @private - - Attached for mocking in tests - - @since 1.5.1 - @property _HashLocation - @default Ember.HashLocation - */ - _HashLocation: HashLocation, - - /** - @private - - Attached for mocking in tests - - @since 1.5.1 - @property _NoneLocation - @default Ember.NoneLocation - */ - _NoneLocation: NoneLocation, - - /** - @private - - Returns location.origin or builds it if device doesn't support it. - - @method _getOrigin - */ - _getOrigin: function () { - var location = this._location; - var origin = location.origin; - - // Older browsers, especially IE, don't have origin - if (!origin) { - origin = location.protocol + '//' + location.hostname; - - if (location.port) { - origin += ':' + location.port; - } - } - - return origin; - }, - - /** - @private - - We assume that if the history object has a pushState method, the host should - support HistoryLocation. - - @method _getSupportsHistory - */ - _getSupportsHistory: function () { - // Boosted from Modernizr: https://github.com/Modernizr/Modernizr/blob/master/feature-detects/history.js - // The stock browser on Android 2.2 & 2.3 returns positive on history support - // Unfortunately support is really buggy and there is no clean way to detect - // these bugs, so we fall back to a user agent sniff :( - var userAgent = this._window.navigator.userAgent; - - // We only want Android 2, stock browser, and not Chrome which identifies - // itself as 'Mobile Safari' as well - if (userAgent.indexOf('Android 2') !== -1 && - userAgent.indexOf('Mobile Safari') !== -1 && - userAgent.indexOf('Chrome') === -1) { - return false; - } - - return !!(this._history && 'pushState' in this._history); - }, - - /** - @private - - IE8 running in IE7 compatibility mode gives false positive, so we must also - check documentMode. - - @method _getSupportsHashChange - */ - _getSupportsHashChange: function () { - var _window = this._window; - var documentMode = _window.document.documentMode; - - return ('onhashchange' in _window && (documentMode === undefined || documentMode > 7 )); - }, - - /** - @private - - Redirects the browser using location.replace, prepending the locatin.origin - to prevent phishing attempts - - @method _replacePath - */ - _replacePath: function (path) { - this._location.replace(this._getOrigin() + path); - }, - - /** - @since 1.5.1 - @private - @method _getRootURL - */ - _getRootURL: function () { - return this.rootURL; - }, - - /** - @private - - Returns the current `location.pathname`, normalized for IE inconsistencies. - - @method _getPath - */ - _getPath: function () { - var pathname = this._location.pathname; - // Various versions of IE/Opera don't always return a leading slash - if (pathname.charAt(0) !== '/') { - pathname = '/' + pathname; - } - - return pathname; - }, - - /** - @private - - Returns normalized location.hash as an alias to Ember.Location._getHash - - @since 1.5.1 - @method _getHash - */ - _getHash: EmberLocation._getHash, - - /** - @private - - Returns location.search - - @since 1.5.1 - @method _getQuery - */ - _getQuery: function () { - return this._location.search; - }, - - /** - @private - - Returns the full pathname including query and hash - - @method _getFullPath - */ - _getFullPath: function () { - return this._getPath() + this._getQuery() + this._getHash(); - }, - - /** - @private - - Returns the current path as it should appear for HistoryLocation supported - browsers. This may very well differ from the real current path (e.g. if it - starts off as a hashed URL) - - @method _getHistoryPath - */ - _getHistoryPath: function () { - var rootURL = this._getRootURL(); - var path = this._getPath(); - var hash = this._getHash(); - var query = this._getQuery(); - var rootURLIndex = path.indexOf(rootURL); - var routeHash, hashParts; - - Ember.assert('Path ' + path + ' does not start with the provided rootURL ' + rootURL, rootURLIndex === 0); - - // By convention, Ember.js routes using HashLocation are required to start - // with `#/`. Anything else should NOT be considered a route and should - // be passed straight through, without transformation. - if (hash.substr(0, 2) === '#/') { - // There could be extra hash segments after the route - hashParts = hash.substr(1).split('#'); - // The first one is always the route url - routeHash = hashParts.shift(); - - // If the path already has a trailing slash, remove the one - // from the hashed route so we don't double up. - if (path.slice(-1) === '/') { - routeHash = routeHash.substr(1); - } - - // This is the "expected" final order - path += routeHash; - path += query; - - if (hashParts.length) { - path += '#' + hashParts.join('#'); - } - } else { - path += query; - path += hash; - } - - return path; - }, - - /** - @private - - Returns the current path as it should appear for HashLocation supported - browsers. This may very well differ from the real current path. - - @method _getHashPath - */ - _getHashPath: function () { - var rootURL = this._getRootURL(); - var path = rootURL; - var historyPath = this._getHistoryPath(); - var routePath = historyPath.substr(rootURL.length); - - if (routePath !== '') { - if (routePath.charAt(0) !== '/') { - routePath = '/' + routePath; - } - - path += '#' + routePath; - } - - return path; - }, - - /** - Selects the best location option based off browser support and returns an - instance of that Location class. - - @see Ember.AutoLocation - @method create - */ - create: function (options) { - if (options && options.rootURL) { - Ember.assert('rootURL must end with a trailing forward slash e.g. "/app/"', options.rootURL.charAt(options.rootURL.length-1) === '/'); - this.rootURL = options.rootURL; - } - - var historyPath, hashPath; - var cancelRouterSetup = false; - var implementationClass = this._NoneLocation; - var currentPath = this._getFullPath(); - - if (this._getSupportsHistory()) { - historyPath = this._getHistoryPath(); - - // Since we support history paths, let's be sure we're using them else - // switch the location over to it. - if (currentPath === historyPath) { - implementationClass = this._HistoryLocation; - } else { - - if (currentPath.substr(0, 2) === '/#') { - this._history.replaceState({ path: historyPath }, null, historyPath); - implementationClass = this._HistoryLocation; - } else { - cancelRouterSetup = true; - this._replacePath(historyPath); - } - } - - } else if (this._getSupportsHashChange()) { - hashPath = this._getHashPath(); - - // Be sure we're using a hashed path, otherwise let's switch over it to so - // we start off clean and consistent. We'll count an index path with no - // hash as "good enough" as well. - if (currentPath === hashPath || (currentPath === '/' && hashPath === '/#/')) { - implementationClass = this._HashLocation; - } else { - // Our URL isn't in the expected hash-supported format, so we want to - // cancel the router setup and replace the URL to start off clean - cancelRouterSetup = true; - this._replacePath(hashPath); - } - } - - var implementation = implementationClass.create.apply(implementationClass, arguments); - - if (cancelRouterSetup) { - set(implementation, 'cancelRouterSetup', true); - } - - return implementation; - } - }; - }); -enifed("ember-routing/location/hash_location", - ["ember-metal/core","ember-metal/property_get","ember-metal/property_set","ember-metal/run_loop","ember-metal/utils","ember-runtime/system/object","ember-routing/location/api","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __exports__) { - "use strict"; - var Ember = __dependency1__["default"]; - var get = __dependency2__.get; - var set = __dependency3__.set; - var run = __dependency4__["default"]; - var guidFor = __dependency5__.guidFor; - - var EmberObject = __dependency6__["default"]; - var EmberLocation = __dependency7__["default"]; - - /** - @module ember - @submodule ember-routing - */ - - /** - `Ember.HashLocation` implements the location API using the browser's - hash. At present, it relies on a `hashchange` event existing in the - browser. - - @class HashLocation - @namespace Ember - @extends Ember.Object - */ - __exports__["default"] = EmberObject.extend({ - implementation: 'hash', - - init: function() { - set(this, 'location', get(this, '_location') || window.location); - }, - - /** - @private - - Returns normalized location.hash - - @since 1.5.1 - @method getHash - */ - getHash: EmberLocation._getHash, - - /** - Returns the current `location.hash`, minus the '#' at the front. - - @private - @method getURL - */ - getURL: function() { - var path = this.getHash().substr(1); - Ember.deprecate('location.hash value is ambiguous. Support for this will be removed soon. When using location: "hash|auto" your hash paths MUST begin with a forward slash. e.g. #/' + path + ' NOT #' + path + '. See http://emberjs.com/guides/deprecations/#toc_location-hash-paths-must-now-include-a-forward-slash-e-g-foo-not-foo', path.length === 0 || path.charAt(0) === '/'); - return path; - }, - - /** - Set the `location.hash` and remembers what was set. This prevents - `onUpdateURL` callbacks from triggering when the hash was set by - `HashLocation`. - - @private - @method setURL - @param path {String} - */ - setURL: function(path) { - get(this, 'location').hash = path; - set(this, 'lastSetURL', path); - }, - - /** - Uses location.replace to update the url without a page reload - or history modification. - - @private - @method replaceURL - @param path {String} - */ - replaceURL: function(path) { - get(this, 'location').replace('#' + path); - set(this, 'lastSetURL', path); - }, - - /** - Register a callback to be invoked when the hash changes. These - callbacks will execute when the user presses the back or forward - button, but not after `setURL` is invoked. - - @private - @method onUpdateURL - @param callback {Function} - */ - onUpdateURL: function(callback) { - var self = this; - var guid = guidFor(this); - - Ember.$(window).on('hashchange.ember-location-'+guid, function() { - run(function() { - var path = self.getURL(); - if (get(self, 'lastSetURL') === path) { return; } - - set(self, 'lastSetURL', null); - - callback(path); - }); - }); - }, - - /** - Given a URL, formats it to be placed into the page as part - of an element's `href` attribute. - - This is used, for example, when using the {{action}} helper - to generate a URL based on an event. - - @private - @method formatURL - @param url {String} - */ - formatURL: function(url) { - return '#' + url; - }, - - /** - Cleans up the HashLocation event listener. - - @private - @method willDestroy - */ - willDestroy: function() { - var guid = guidFor(this); - - Ember.$(window).off('hashchange.ember-location-'+guid); - } - }); - }); -enifed("ember-routing/location/history_location", - ["ember-metal/core","ember-metal/property_get","ember-metal/property_set","ember-metal/utils","ember-runtime/system/object","ember-views/system/jquery","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __exports__) { - "use strict"; - var Ember = __dependency1__["default"]; - // FEATURES - var get = __dependency2__.get; - var set = __dependency3__.set; - var guidFor = __dependency4__.guidFor; - - var EmberObject = __dependency5__["default"]; - var jQuery = __dependency6__["default"]; - - /** - @module ember - @submodule ember-routing - */ - - var popstateFired = false; - var supportsHistoryState = window.history && 'state' in window.history; - - /** - Ember.HistoryLocation implements the location API using the browser's - history.pushState API. - - @class HistoryLocation - @namespace Ember - @extends Ember.Object - */ - __exports__["default"] = EmberObject.extend({ - implementation: 'history', - - init: function() { - set(this, 'location', get(this, 'location') || window.location); - set(this, 'baseURL', jQuery('base').attr('href') || ''); - }, - - /** - Used to set state on first call to setURL - - @private - @method initState - */ - initState: function() { - set(this, 'history', get(this, 'history') || window.history); - this.replaceState(this.formatURL(this.getURL())); - }, - - /** - Will be pre-pended to path upon state change - - @property rootURL - @default '/' - */ - rootURL: '/', - - /** - Returns the current `location.pathname` without `rootURL` or `baseURL` - - @private - @method getURL - @return url {String} - */ - getURL: function() { - var rootURL = get(this, 'rootURL'); - var location = get(this, 'location'); - var path = location.pathname; - var baseURL = get(this, 'baseURL'); - - rootURL = rootURL.replace(/\/$/, ''); - baseURL = baseURL.replace(/\/$/, ''); - - var url = path.replace(baseURL, '').replace(rootURL, ''); - var search = location.search || ''; - - url += search; - - return url; - }, - - /** - Uses `history.pushState` to update the url without a page reload. - - @private - @method setURL - @param path {String} - */ - setURL: function(path) { - var state = this.getState(); - path = this.formatURL(path); - - if (!state || state.path !== path) { - this.pushState(path); - } - }, - - /** - Uses `history.replaceState` to update the url without a page reload - or history modification. - - @private - @method replaceURL - @param path {String} - */ - replaceURL: function(path) { - var state = this.getState(); - path = this.formatURL(path); - - if (!state || state.path !== path) { - this.replaceState(path); - } - }, - - /** - Get the current `history.state`. Checks for if a polyfill is - required and if so fetches this._historyState. The state returned - from getState may be null if an iframe has changed a window's - history. - - @private - @method getState - @return state {Object} - */ - getState: function() { - return supportsHistoryState ? get(this, 'history').state : this._historyState; - }, - - /** - Pushes a new state. - - @private - @method pushState - @param path {String} - */ - pushState: function(path) { - var state = { path: path }; - - get(this, 'history').pushState(state, null, path); - - // store state if browser doesn't support `history.state` - if (!supportsHistoryState) { - this._historyState = state; - } - - // used for webkit workaround - this._previousURL = this.getURL(); - }, - - /** - Replaces the current state. - - @private - @method replaceState - @param path {String} - */ - replaceState: function(path) { - var state = { path: path }; - - get(this, 'history').replaceState(state, null, path); - - // store state if browser doesn't support `history.state` - if (!supportsHistoryState) { - this._historyState = state; - } - - // used for webkit workaround - this._previousURL = this.getURL(); - }, - - /** - Register a callback to be invoked whenever the browser - history changes, including using forward and back buttons. - - @private - @method onUpdateURL - @param callback {Function} - */ - onUpdateURL: function(callback) { - var guid = guidFor(this); - var self = this; - - jQuery(window).on('popstate.ember-location-'+guid, function(e) { - // Ignore initial page load popstate event in Chrome - if (!popstateFired) { - popstateFired = true; - if (self.getURL() === self._previousURL) { return; } - } - callback(self.getURL()); - }); - }, - - /** - Used when using `{{action}}` helper. The url is always appended to the rootURL. - - @private - @method formatURL - @param url {String} - @return formatted url {String} - */ - formatURL: function(url) { - var rootURL = get(this, 'rootURL'); - var baseURL = get(this, 'baseURL'); - - if (url !== '') { - rootURL = rootURL.replace(/\/$/, ''); - baseURL = baseURL.replace(/\/$/, ''); - } else if(baseURL.match(/^\//) && rootURL.match(/^\//)) { - baseURL = baseURL.replace(/\/$/, ''); - } - - return baseURL + rootURL + url; - }, - - /** - Cleans up the HistoryLocation event listener. - - @private - @method willDestroy - */ - willDestroy: function() { - var guid = guidFor(this); - - jQuery(window).off('popstate.ember-location-'+guid); - } - }); - }); -enifed("ember-routing/location/none_location", - ["ember-metal/property_get","ember-metal/property_set","ember-runtime/system/object","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __exports__) { - "use strict"; - var get = __dependency1__.get; - var set = __dependency2__.set; - var EmberObject = __dependency3__["default"]; - - /** - @module ember - @submodule ember-routing - */ - - /** - Ember.NoneLocation does not interact with the browser. It is useful for - testing, or when you need to manage state with your Router, but temporarily - don't want it to muck with the URL (for example when you embed your - application in a larger page). - - @class NoneLocation - @namespace Ember - @extends Ember.Object - */ - __exports__["default"] = EmberObject.extend({ - implementation: 'none', - path: '', - - /** - Returns the current path. - - @private - @method getURL - @return {String} path - */ - getURL: function() { - return get(this, 'path'); - }, - - /** - Set the path and remembers what was set. Using this method - to change the path will not invoke the `updateURL` callback. - - @private - @method setURL - @param path {String} - */ - setURL: function(path) { - set(this, 'path', path); - }, - - /** - Register a callback to be invoked when the path changes. These - callbacks will execute when the user presses the back or forward - button, but not after `setURL` is invoked. - - @private - @method onUpdateURL - @param callback {Function} - */ - onUpdateURL: function(callback) { - this.updateCallback = callback; - }, - - /** - Sets the path and calls the `updateURL` callback. - - @private - @method handleURL - @param callback {Function} - */ - handleURL: function(url) { - set(this, 'path', url); - this.updateCallback(url); - }, - - /** - Given a URL, formats it to be placed into the page as part - of an element's `href` attribute. - - This is used, for example, when using the {{action}} helper - to generate a URL based on an event. - - @private - @method formatURL - @param url {String} - @return {String} url - */ - formatURL: function(url) { - // The return value is not overly meaningful, but we do not want to throw - // errors when test code renders templates containing {{action href=true}} - // helpers. - return url; - } - }); - }); -enifed("ember-routing/system/cache", - ["ember-runtime/system/object","exports"], - function(__dependency1__, __exports__) { - "use strict"; - var EmberObject = __dependency1__["default"]; - - __exports__["default"] = EmberObject.extend({ - init: function() { - this.cache = {}; - }, - has: function(bucketKey) { - return bucketKey in this.cache; - }, - stash: function(bucketKey, key, value) { - var bucket = this.cache[bucketKey]; - if (!bucket) { - bucket = this.cache[bucketKey] = {}; - } - bucket[key] = value; - }, - lookup: function(bucketKey, prop, defaultValue) { - var cache = this.cache; - if (!(bucketKey in cache)) { - return defaultValue; - } - var bucket = cache[bucketKey]; - if (prop in bucket) { - return bucket[prop]; - } else { - return defaultValue; - } - }, - cache: null - }); - }); -enifed("ember-routing/system/controller_for", - ["exports"], - function(__exports__) { - "use strict"; - /** - @module ember - @submodule ember-routing - */ - - /** - - Finds a controller instance. - - @for Ember - @method controllerFor - @private - */ - __exports__["default"] = function controllerFor(container, controllerName, lookupOptions) { - return container.lookup('controller:' + controllerName, lookupOptions); - } - }); -enifed("ember-routing/system/dsl", - ["ember-metal/core","exports"], - function(__dependency1__, __exports__) { - "use strict"; - var Ember = __dependency1__["default"]; - // FEATURES, assert - - /** - @module ember - @submodule ember-routing - */ - - function DSL(name) { - this.parent = name; - this.matches = []; - } - __exports__["default"] = DSL; - - DSL.prototype = { - route: function(name, options, callback) { - if (arguments.length === 2 && typeof options === 'function') { - callback = options; - options = {}; - } - - if (arguments.length === 1) { - options = {}; - } - - var type = options.resetNamespace === true ? 'resource' : 'route'; - Ember.assert("'basic' cannot be used as a " + type + " name.", name !== 'basic'); - - - if (typeof options.path !== 'string') { - options.path = "/" + name; - } - - if (canNest(this) && options.resetNamespace !== true) { - name = this.parent + "." + name; - } - - if (callback) { - var dsl = new DSL(name); - route(dsl, 'loading'); - route(dsl, 'error', { path: "/_unused_dummy_error_path_route_" + name + "/:error" }); - - if (callback) { callback.call(dsl); } - - this.push(options.path, name, dsl.generate()); - } else { - this.push(options.path, name, null); - } - - }, - - push: function(url, name, callback) { - var parts = name.split('.'); - if (url === "" || url === "/" || parts[parts.length-1] === "index") { this.explicitIndex = true; } - - this.matches.push([url, name, callback]); - }, - - resource: function(name, options, callback) { - if (arguments.length === 2 && typeof options === 'function') { - callback = options; - options = {}; - } - - if (arguments.length === 1) { - options = {}; - } - - options.resetNamespace = true; - this.route(name, options, callback); - }, - - generate: function() { - var dslMatches = this.matches; - - if (!this.explicitIndex) { - route(this, "index", { path: "/" }); - } - - return function(match) { - for (var i=0, l=dslMatches.length; i " + fullName, { fullName: fullName }); - } - - return instance; - } - }); -enifed("ember-routing/system/route", - ["ember-metal/core","ember-metal/error","ember-metal/property_get","ember-metal/property_set","ember-metal/get_properties","ember-metal/enumerable_utils","ember-metal/is_none","ember-metal/computed","ember-metal/merge","ember-metal/utils","ember-metal/run_loop","ember-metal/keys","ember-runtime/copy","ember-runtime/system/string","ember-runtime/system/object","ember-runtime/mixins/action_handler","ember-routing/system/generate_controller","ember-routing-handlebars/helpers/shared","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __dependency11__, __dependency12__, __dependency13__, __dependency14__, __dependency15__, __dependency16__, __dependency17__, __dependency18__, __exports__) { - "use strict"; - var Ember = __dependency1__["default"]; - // FEATURES, K, A, deprecate, assert, Logger - var EmberError = __dependency2__["default"]; - var get = __dependency3__.get; - var set = __dependency4__.set; - var getProperties = __dependency5__["default"]; - var forEach = __dependency6__.forEach; - var replace = __dependency6__.replace; - var isNone = __dependency7__.isNone; - var computed = __dependency8__.computed; - var merge = __dependency9__["default"]; - var isArray = __dependency10__.isArray; - var typeOf = __dependency10__.typeOf; - var run = __dependency11__["default"]; - var keys = __dependency12__["default"]; - var copy = __dependency13__["default"]; - var classify = __dependency14__.classify; - var fmt = __dependency14__.fmt; - var EmberObject = __dependency15__["default"]; - var ActionHandler = __dependency16__["default"]; - var generateController = __dependency17__["default"]; - var stashParamNames = __dependency18__.stashParamNames; - - /** - @module ember - @submodule ember-routing - */ - - /** - The `Ember.Route` class is used to define individual routes. Refer to - the [routing guide](http://emberjs.com/guides/routing/) for documentation. - - @class Route - @namespace Ember - @extends Ember.Object - @uses Ember.ActionHandler - */ - var Route = EmberObject.extend(ActionHandler, { - /** - Configuration hash for this route's queryParams. The possible - configuration options and their defaults are as follows - (assuming a query param whose URL key is `page`): - - ```js - queryParams: { - page: { - // By default, controller query param properties don't - // cause a full transition when they are changed, but - // rather only cause the URL to update. Setting - // `refreshModel` to true will cause an "in-place" - // transition to occur, whereby the model hooks for - // this route (and any child routes) will re-fire, allowing - // you to reload models (e.g., from the server) using the - // updated query param values. - refreshModel: false, - - // By default, changes to controller query param properties - // cause the URL to update via `pushState`, which means an - // item will be added to the browser's history, allowing - // you to use the back button to restore the app to the - // previous state before the query param property was changed. - // Setting `replace` to true will use `replaceState` (or its - // hash location equivalent), which causes no browser history - // item to be added. This options name and default value are - // the same as the `link-to` helper's `replace` option. - replace: false - } - } - ``` - - @property queryParams - @for Ember.Route - @type Hash - */ - queryParams: {}, - - /** - @private - - @property _qp - */ - _qp: computed(function() { - var controllerName = this.controllerName || this.routeName; - var controllerClass = this.container.lookupFactory('controller:' + controllerName); - - if (!controllerClass) { - return defaultQPMeta; - } - - var controllerProto = controllerClass.proto(); - var qpProps = get(controllerProto, '_normalizedQueryParams'); - var cacheMeta = get(controllerProto, '_cacheMeta'); - - var qps = [], map = {}, self = this; - for (var propName in qpProps) { - if (!qpProps.hasOwnProperty(propName)) { continue; } - - var desc = qpProps[propName]; - var urlKey = desc.as || this.serializeQueryParamKey(propName); - var defaultValue = get(controllerProto, propName); - - if (isArray(defaultValue)) { - defaultValue = Ember.A(defaultValue.slice()); - } - - var type = typeOf(defaultValue); - var defaultValueSerialized = this.serializeQueryParam(defaultValue, urlKey, type); - var fprop = controllerName + ':' + propName; - var qp = { - def: defaultValue, - sdef: defaultValueSerialized, - type: type, - urlKey: urlKey, - prop: propName, - fprop: fprop, - ctrl: controllerName, - cProto: controllerProto, - svalue: defaultValueSerialized, - cacheType: desc.scope, - route: this, - cacheMeta: cacheMeta[propName] - }; - - map[propName] = map[urlKey] = map[fprop] = qp; - qps.push(qp); - } - - return { - qps: qps, - map: map, - states: { - active: function(controller, prop) { - return self._activeQPChanged(controller, map[prop]); - }, - allowOverrides: function(controller, prop) { - return self._updatingQPChanged(controller, map[prop]); - }, - changingKeys: function(controller, prop) { - return self._updateSerializedQPValue(controller, map[prop]); - } - } - }; - }), - - /** - @private - - @property _names - */ - _names: null, - - /** - @private - - @method _stashNames - */ - _stashNames: function(_handlerInfo, dynamicParent) { - var handlerInfo = _handlerInfo; - if (this._names) { return; } - var names = this._names = handlerInfo._names; - - if (!names.length) { - handlerInfo = dynamicParent; - names = handlerInfo && handlerInfo._names || []; - } - - var qps = get(this, '_qp.qps'); - var len = qps.length; - - var namePaths = new Array(names.length); - for (var a = 0, nlen = names.length; a < nlen; ++a) { - namePaths[a] = handlerInfo.name + '.' + names[a]; - } - - for (var i = 0; i < len; ++i) { - var qp = qps[i]; - var cacheMeta = qp.cacheMeta; - if (cacheMeta.scope === 'model') { - cacheMeta.parts = namePaths; - } - cacheMeta.prefix = qp.ctrl; - } - }, - - /** - @private - - @property _updateSerializedQPValue - */ - _updateSerializedQPValue: function(controller, qp) { - var value = get(controller, qp.prop); - qp.svalue = this.serializeQueryParam(value, qp.urlKey, qp.type); - }, - - /** - @private - - @property _activeQPChanged - */ - _activeQPChanged: function(controller, qp) { - var value = get(controller, qp.prop); - this.router._queuedQPChanges[qp.fprop] = value; - run.once(this, this._fireQueryParamTransition); - }, - - /** - @private - @method _updatingQPChanged - */ - _updatingQPChanged: function(controller, qp) { - var router = this.router; - if (!router._qpUpdates) { - router._qpUpdates = {}; - } - router._qpUpdates[qp.urlKey] = true; - }, - - mergedProperties: ['events', 'queryParams'], - - /** - @method paramsFor - */ - paramsFor: function(name) { - var route = this.container.lookup('route:' + name); - - if (!route) { - return {}; - } - - var transition = this.router.router.activeTransition; - var state = transition ? transition.state : this.router.router.state; - - var params = {}; - merge(params, state.params[name]); - merge(params, getQueryParamsFor(route, state)); - - return params; - }, - - /** - @method serializeQueryParamKey - */ - serializeQueryParamKey: function(controllerPropertyName) { - return controllerPropertyName; - }, - - /** - @method serializeQueryParam - */ - serializeQueryParam: function(value, urlKey, defaultValueType) { - // urlKey isn't used here, but anyone overriding - // can use it to provide serialization specific - // to a certain query param. - if (defaultValueType === 'array') { - return JSON.stringify(value); - } - return '' + value; - }, - - /** - @method deserializeQueryParam - */ - deserializeQueryParam: function(value, urlKey, defaultValueType) { - // urlKey isn't used here, but anyone overriding - // can use it to provide deserialization specific - // to a certain query param. - - // Use the defaultValueType of the default value (the initial value assigned to a - // controller query param property), to intelligently deserialize and cast. - if (defaultValueType === 'boolean') { - return (value === 'true') ? true : false; - } else if (defaultValueType === 'number') { - return (Number(value)).valueOf(); - } else if (defaultValueType === 'array') { - return Ember.A(JSON.parse(value)); - } - return value; - }, - - - /** - @private - @property _fireQueryParamTransition - */ - _fireQueryParamTransition: function() { - this.transitionTo({ queryParams: this.router._queuedQPChanges }); - this.router._queuedQPChanges = {}; - }, - - /** - A hook you can use to reset controller values either when the model - changes or the route is exiting. - - ```js - App.ArticlesRoute = Ember.Route.extend({ - // ... - - resetController: function (controller, isExiting, transition) { - if (isExiting) { - controller.set('page', 1); - } - } - }); - ``` - - @method resetController - @param {Controller} controller instance - @param {Boolean} isExiting - @param {Object} transition - @since 1.7.0 - */ - resetController: Ember.K, - - /** - @private - - @method exit - */ - exit: function() { - this.deactivate(); - this.teardownViews(); - }, - - /** - @private - - @method _reset - @since 1.7.0 - */ - _reset: function(isExiting, transition) { - var controller = this.controller; - - controller._qpDelegate = get(this, '_qp.states.inactive'); - - this.resetController(controller, isExiting, transition); - }, - - /** - @private - - @method enter - */ - enter: function() { - this.activate(); - }, - - /** - The name of the view to use by default when rendering this routes template. - - When rendering a template, the route will, by default, determine the - template and view to use from the name of the route itself. If you need to - define a specific view, set this property. - - This is useful when multiple routes would benefit from using the same view - because it doesn't require a custom `renderTemplate` method. For example, - the following routes will all render using the `App.PostsListView` view: - - ```js - var PostsList = Ember.Route.extend({ - viewName: 'postsList' - }); - - App.PostsIndexRoute = PostsList.extend(); - App.PostsArchivedRoute = PostsList.extend(); - ``` - - @property viewName - @type String - @default null - @since 1.4.0 - */ - viewName: null, - - /** - The name of the template to use by default when rendering this routes - template. - - This is similar with `viewName`, but is useful when you just want a custom - template without a view. - - ```js - var PostsList = Ember.Route.extend({ - templateName: 'posts/list' - }); - - App.PostsIndexRoute = PostsList.extend(); - App.PostsArchivedRoute = PostsList.extend(); - ``` - - @property templateName - @type String - @default null - @since 1.4.0 - */ - templateName: null, - - /** - The name of the controller to associate with this route. - - By default, Ember will lookup a route's controller that matches the name - of the route (i.e. `App.PostController` for `App.PostRoute`). However, - if you would like to define a specific controller to use, you can do so - using this property. - - This is useful in many ways, as the controller specified will be: - - * passed to the `setupController` method. - * used as the controller for the view being rendered by the route. - * returned from a call to `controllerFor` for the route. - - @property controllerName - @type String - @default null - @since 1.4.0 - */ - controllerName: null, - - /** - The `willTransition` action is fired at the beginning of any - attempted transition with a `Transition` object as the sole - argument. This action can be used for aborting, redirecting, - or decorating the transition from the currently active routes. - - A good example is preventing navigation when a form is - half-filled out: - - ```js - App.ContactFormRoute = Ember.Route.extend({ - actions: { - willTransition: function(transition) { - if (this.controller.get('userHasEnteredData')) { - this.controller.displayNavigationConfirm(); - transition.abort(); - } - } - } - }); - ``` - - You can also redirect elsewhere by calling - `this.transitionTo('elsewhere')` from within `willTransition`. - Note that `willTransition` will not be fired for the - redirecting `transitionTo`, since `willTransition` doesn't - fire when there is already a transition underway. If you want - subsequent `willTransition` actions to fire for the redirecting - transition, you must first explicitly call - `transition.abort()`. - - @event willTransition - @param {Transition} transition - */ - - /** - The `didTransition` action is fired after a transition has - successfully been completed. This occurs after the normal model - hooks (`beforeModel`, `model`, `afterModel`, `setupController`) - have resolved. The `didTransition` action has no arguments, - however, it can be useful for tracking page views or resetting - state on the controller. - - ```js - App.LoginRoute = Ember.Route.extend({ - actions: { - didTransition: function() { - this.controller.get('errors.base').clear(); - return true; // Bubble the didTransition event - } - } - }); - ``` - - @event didTransition - @since 1.2.0 - */ - - /** - The `loading` action is fired on the route when a route's `model` - hook returns a promise that is not already resolved. The current - `Transition` object is the first parameter and the route that - triggered the loading event is the second parameter. - - ```js - App.ApplicationRoute = Ember.Route.extend({ - actions: { - loading: function(transition, route) { - var view = Ember.View.create({ - classNames: ['app-loading'] - }) - .append(); - - this.router.one('didTransition', function () { - view.destroy(); - }); - return true; // Bubble the loading event - } - } - }); - ``` - - @event loading - @param {Transition} transition - @param {Ember.Route} route The route that triggered the loading event - @since 1.2.0 - */ - - /** - When attempting to transition into a route, any of the hooks - may return a promise that rejects, at which point an `error` - action will be fired on the partially-entered routes, allowing - for per-route error handling logic, or shared error handling - logic defined on a parent route. - - Here is an example of an error handler that will be invoked - for rejected promises from the various hooks on the route, - as well as any unhandled errors from child routes: - - ```js - App.AdminRoute = Ember.Route.extend({ - beforeModel: function() { - return Ember.RSVP.reject("bad things!"); - }, - - actions: { - error: function(error, transition) { - // Assuming we got here due to the error in `beforeModel`, - // we can expect that error === "bad things!", - // but a promise model rejecting would also - // call this hook, as would any errors encountered - // in `afterModel`. - - // The `error` hook is also provided the failed - // `transition`, which can be stored and later - // `.retry()`d if desired. - - this.transitionTo('login'); - } - } - }); - ``` - - `error` actions that bubble up all the way to `ApplicationRoute` - will fire a default error handler that logs the error. You can - specify your own global default error handler by overriding the - `error` handler on `ApplicationRoute`: - - ```js - App.ApplicationRoute = Ember.Route.extend({ - actions: { - error: function(error, transition) { - this.controllerFor('banner').displayError(error.message); - } - } - }); - ``` - @event error - @param {Error} error - @param {Transition} transition - */ - - /** - The controller associated with this route. - - Example - - ```javascript - App.FormRoute = Ember.Route.extend({ - actions: { - willTransition: function(transition) { - if (this.controller.get('userHasEnteredData') && - !confirm("Are you sure you want to abandon progress?")) { - transition.abort(); - } else { - // Bubble the `willTransition` action so that - // parent routes can decide whether or not to abort. - return true; - } - } - } - }); - ``` - - @property controller - @type Ember.Controller - @since 1.6.0 - */ - - _actions: { - - queryParamsDidChange: function(changed, totalPresent, removed) { - var totalChanged = keys(changed).concat(keys(removed)); - for (var i = 0, len = totalChanged.length; i < len; ++i) { - var urlKey = totalChanged[i]; - var options = get(this.queryParams, urlKey) || {}; - if (get(options, 'refreshModel')) { - this.refresh(); - } - } - - return true; - }, - - finalizeQueryParamChange: function(params, finalParams, transition) { - if (this.routeName !== 'application') { return true; } - - // Transition object is absent for intermediate transitions. - if (!transition) { return; } - - var handlerInfos = transition.state.handlerInfos; - var router = this.router; - var qpMeta = router._queryParamsFor(handlerInfos[handlerInfos.length-1].name); - var changes = router._qpUpdates; - var replaceUrl; - - stashParamNames(router, handlerInfos); - - for (var i = 0, len = qpMeta.qps.length; i < len; ++i) { - var qp = qpMeta.qps[i]; - var route = qp.route; - var controller = route.controller; - var presentKey = qp.urlKey in params && qp.urlKey; - - // Do a reverse lookup to see if the changed query - // param URL key corresponds to a QP property on - // this controller. - var value, svalue; - if (changes && qp.urlKey in changes) { - // Value updated in/before setupController - value = get(controller, qp.prop); - svalue = route.serializeQueryParam(value, qp.urlKey, qp.type); - } else { - if (presentKey) { - svalue = params[presentKey]; - value = route.deserializeQueryParam(svalue, qp.urlKey, qp.type); - } else { - // No QP provided; use default value. - svalue = qp.sdef; - value = copyDefaultValue(qp.def); - } - } - - controller._qpDelegate = get(this, '_qp.states.inactive'); - - var thisQueryParamChanged = (svalue !== qp.svalue); - if (thisQueryParamChanged) { - var options = get(route, 'queryParams.' + qp.urlKey) || {}; - - if (transition.queryParamsOnly && replaceUrl !== false) { - var replaceConfigValue = get(options, 'replace'); - if (replaceConfigValue) { - replaceUrl = true; - } else if (replaceConfigValue === false) { - // Explicit pushState wins over any other replaceStates. - replaceUrl = false; - } - } - - set(controller, qp.prop, value); - } - - // Stash current serialized value of controller. - qp.svalue = svalue; - - var thisQueryParamHasDefaultValue = (qp.sdef === svalue); - if (!thisQueryParamHasDefaultValue) { - finalParams.push({ - value: svalue, - visible: true, - key: presentKey || qp.urlKey - }); - } - } - - if (replaceUrl) { - transition.method('replace'); - } - - forEach(qpMeta.qps, function(qp) { - var routeQpMeta = get(qp.route, '_qp'); - var finalizedController = qp.route.controller; - finalizedController._qpDelegate = get(routeQpMeta, 'states.active'); - }); - - router._qpUpdates = null; - } - }, - - /** - @deprecated - - Please use `actions` instead. - @method events - */ - events: null, - - /** - This hook is executed when the router completely exits this route. It is - not executed when the model for the route changes. - - @method deactivate - */ - deactivate: Ember.K, - - /** - This hook is executed when the router enters the route. It is not executed - when the model for the route changes. - - @method activate - */ - activate: Ember.K, - - /** - Transition the application into another route. The route may - be either a single route or route path: - - ```javascript - this.transitionTo('blogPosts'); - this.transitionTo('blogPosts.recentEntries'); - ``` - - Optionally supply a model for the route in question. The model - will be serialized into the URL using the `serialize` hook of - the route: - - ```javascript - this.transitionTo('blogPost', aPost); - ``` - - If a literal is passed (such as a number or a string), it will - be treated as an identifier instead. In this case, the `model` - hook of the route will be triggered: - - ```javascript - this.transitionTo('blogPost', 1); - ``` - - Multiple models will be applied last to first recursively up the - resource tree. - - ```javascript - App.Router.map(function() { - this.resource('blogPost', {path:':blogPostId'}, function(){ - this.resource('blogComment', {path: ':blogCommentId'}); - }); - }); - - this.transitionTo('blogComment', aPost, aComment); - this.transitionTo('blogComment', 1, 13); - ``` - - It is also possible to pass a URL (a string that starts with a - `/`). This is intended for testing and debugging purposes and - should rarely be used in production code. - - ```javascript - this.transitionTo('/'); - this.transitionTo('/blog/post/1/comment/13'); - ``` - - See also 'replaceWith'. - - Simple Transition Example - - ```javascript - App.Router.map(function() { - this.route("index"); - this.route("secret"); - this.route("fourOhFour", { path: "*:"}); - }); - - App.IndexRoute = Ember.Route.extend({ - actions: { - moveToSecret: function(context){ - if (authorized()){ - this.transitionTo('secret', context); - } - this.transitionTo('fourOhFour'); - } - } - }); - ``` - - Transition to a nested route - - ```javascript - App.Router.map(function() { - this.resource('articles', { path: '/articles' }, function() { - this.route('new'); - }); - }); - - App.IndexRoute = Ember.Route.extend({ - actions: { - transitionToNewArticle: function() { - this.transitionTo('articles.new'); - } - } - }); - ``` - - Multiple Models Example - - ```javascript - App.Router.map(function() { - this.route("index"); - this.resource('breakfast', {path:':breakfastId'}, function(){ - this.resource('cereal', {path: ':cerealId'}); - }); - }); - - App.IndexRoute = Ember.Route.extend({ - actions: { - moveToChocolateCereal: function(){ - var cereal = { cerealId: "ChocolateYumminess"}, - breakfast = {breakfastId: "CerealAndMilk"}; - - this.transitionTo('cereal', breakfast, cereal); - } - } - }); - ``` - - @method transitionTo - @param {String} name the name of the route or a URL - @param {...Object} models the model(s) or identifier(s) to be used while - transitioning to the route. - @return {Transition} the transition object associated with this - attempted transition - */ - transitionTo: function(name, context) { - var router = this.router; - return router.transitionTo.apply(router, arguments); - }, - - /** - Perform a synchronous transition into another route without attempting - to resolve promises, update the URL, or abort any currently active - asynchronous transitions (i.e. regular transitions caused by - `transitionTo` or URL changes). - - This method is handy for performing intermediate transitions on the - way to a final destination route, and is called internally by the - default implementations of the `error` and `loading` handlers. - - @method intermediateTransitionTo - @param {String} name the name of the route - @param {...Object} models the model(s) to be used while transitioning - to the route. - @since 1.2.0 - */ - intermediateTransitionTo: function() { - var router = this.router; - router.intermediateTransitionTo.apply(router, arguments); - }, - - /** - Refresh the model on this route and any child routes, firing the - `beforeModel`, `model`, and `afterModel` hooks in a similar fashion - to how routes are entered when transitioning in from other route. - The current route params (e.g. `article_id`) will be passed in - to the respective model hooks, and if a different model is returned, - `setupController` and associated route hooks will re-fire as well. - - An example usage of this method is re-querying the server for the - latest information using the same parameters as when the route - was first entered. - - Note that this will cause `model` hooks to fire even on routes - that were provided a model object when the route was initially - entered. - - @method refresh - @return {Transition} the transition object associated with this - attempted transition - @since 1.4.0 - */ - refresh: function() { - return this.router.router.refresh(this); - }, - - /** - Transition into another route while replacing the current URL, if possible. - This will replace the current history entry instead of adding a new one. - Beside that, it is identical to `transitionTo` in all other respects. See - 'transitionTo' for additional information regarding multiple models. - - Example - - ```javascript - App.Router.map(function() { - this.route("index"); - this.route("secret"); - }); - - App.SecretRoute = Ember.Route.extend({ - afterModel: function() { - if (!authorized()){ - this.replaceWith('index'); - } - } - }); - ``` - - @method replaceWith - @param {String} name the name of the route or a URL - @param {...Object} models the model(s) or identifier(s) to be used while - transitioning to the route. - @return {Transition} the transition object associated with this - attempted transition - */ - replaceWith: function() { - var router = this.router; - return router.replaceWith.apply(router, arguments); - }, - - /** - Sends an action to the router, which will delegate it to the currently - active route hierarchy per the bubbling rules explained under `actions`. - - Example - - ```javascript - App.Router.map(function() { - this.route("index"); - }); - - App.ApplicationRoute = Ember.Route.extend({ - actions: { - track: function(arg) { - console.log(arg, 'was clicked'); - } - } - }); - - App.IndexRoute = Ember.Route.extend({ - actions: { - trackIfDebug: function(arg) { - if (debug) { - this.send('track', arg); - } - } - } - }); - ``` - - @method send - @param {String} name the name of the action to trigger - @param {...*} args - */ - send: function() { - return this.router.send.apply(this.router, arguments); - }, - - /** - This hook is the entry point for router.js - - @private - @method setup - */ - setup: function(context, transition) { - var controllerName = this.controllerName || this.routeName; - var controller = this.controllerFor(controllerName, true); - - if (!controller) { - controller = this.generateController(controllerName, context); - } - - // Assign the route's controller so that it can more easily be - // referenced in action handlers - this.controller = controller; - - if (this.setupControllers) { - Ember.deprecate("Ember.Route.setupControllers is deprecated. Please use Ember.Route.setupController(controller, model) instead."); - this.setupControllers(controller, context); - } else { - var states = get(this, '_qp.states'); - if (transition) { - // Update the model dep values used to calculate cache keys. - stashParamNames(this.router, transition.state.handlerInfos); - controller._qpDelegate = states.changingKeys; - controller._updateCacheParams(transition.params); - } - controller._qpDelegate = states.allowOverrides; - - if (transition) { - var qpValues = getQueryParamsFor(this, transition.state); - controller.setProperties(qpValues); - } - - this.setupController(controller, context, transition); - } - - if (this.renderTemplates) { - Ember.deprecate("Ember.Route.renderTemplates is deprecated. Please use Ember.Route.renderTemplate(controller, model) instead."); - this.renderTemplates(context); - } else { - this.renderTemplate(controller, context); - } - }, - - /** - This hook is the first of the route entry validation hooks - called when an attempt is made to transition into a route - or one of its children. It is called before `model` and - `afterModel`, and is appropriate for cases when: - - 1) A decision can be made to redirect elsewhere without - needing to resolve the model first. - 2) Any async operations need to occur first before the - model is attempted to be resolved. - - This hook is provided the current `transition` attempt - as a parameter, which can be used to `.abort()` the transition, - save it for a later `.retry()`, or retrieve values set - on it from a previous hook. You can also just call - `this.transitionTo` to another route to implicitly - abort the `transition`. - - You can return a promise from this hook to pause the - transition until the promise resolves (or rejects). This could - be useful, for instance, for retrieving async code from - the server that is required to enter a route. - - ```js - App.PostRoute = Ember.Route.extend({ - beforeModel: function(transition) { - if (!App.Post) { - return Ember.$.getScript('/models/post.js'); - } - } - }); - ``` - - If `App.Post` doesn't exist in the above example, - `beforeModel` will use jQuery's `getScript`, which - returns a promise that resolves after the server has - successfully retrieved and executed the code from the - server. Note that if an error were to occur, it would - be passed to the `error` hook on `Ember.Route`, but - it's also possible to handle errors specific to - `beforeModel` right from within the hook (to distinguish - from the shared error handling behavior of the `error` - hook): - - ```js - App.PostRoute = Ember.Route.extend({ - beforeModel: function(transition) { - if (!App.Post) { - var self = this; - return Ember.$.getScript('post.js').then(null, function(e) { - self.transitionTo('help'); - - // Note that the above transitionTo will implicitly - // halt the transition. If you were to return - // nothing from this promise reject handler, - // according to promise semantics, that would - // convert the reject into a resolve and the - // transition would continue. To propagate the - // error so that it'd be handled by the `error` - // hook, you would have to either - return Ember.RSVP.reject(e); - }); - } - } - }); - ``` - - @method beforeModel - @param {Transition} transition - @param {Object} queryParams the active query params for this route - @return {Promise} if the value returned from this hook is - a promise, the transition will pause until the transition - resolves. Otherwise, non-promise return values are not - utilized in any way. - */ - beforeModel: Ember.K, - - /** - This hook is called after this route's model has resolved. - It follows identical async/promise semantics to `beforeModel` - but is provided the route's resolved model in addition to - the `transition`, and is therefore suited to performing - logic that can only take place after the model has already - resolved. - - ```js - App.PostsRoute = Ember.Route.extend({ - afterModel: function(posts, transition) { - if (posts.get('length') === 1) { - this.transitionTo('post.show', posts.get('firstObject')); - } - } - }); - ``` - - Refer to documentation for `beforeModel` for a description - of transition-pausing semantics when a promise is returned - from this hook. - - @method afterModel - @param {Object} resolvedModel the value returned from `model`, - or its resolved value if it was a promise - @param {Transition} transition - @param {Object} queryParams the active query params for this handler - @return {Promise} if the value returned from this hook is - a promise, the transition will pause until the transition - resolves. Otherwise, non-promise return values are not - utilized in any way. - */ - afterModel: Ember.K, - - /** - A hook you can implement to optionally redirect to another route. - - If you call `this.transitionTo` from inside of this hook, this route - will not be entered in favor of the other hook. - - `redirect` and `afterModel` behave very similarly and are - called almost at the same time, but they have an important - distinction in the case that, from one of these hooks, a - redirect into a child route of this route occurs: redirects - from `afterModel` essentially invalidate the current attempt - to enter this route, and will result in this route's `beforeModel`, - `model`, and `afterModel` hooks being fired again within - the new, redirecting transition. Redirects that occur within - the `redirect` hook, on the other hand, will _not_ cause - these hooks to be fired again the second time around; in - other words, by the time the `redirect` hook has been called, - both the resolved model and attempted entry into this route - are considered to be fully validated. - - @method redirect - @param {Object} model the model for this route - @param {Transition} transition the transition object associated with the current transition - */ - redirect: Ember.K, - - /** - Called when the context is changed by router.js. - - @private - @method contextDidChange - */ - contextDidChange: function() { - this.currentModel = this.context; - }, - - /** - A hook you can implement to convert the URL into the model for - this route. - - ```js - App.Router.map(function() { - this.resource('post', {path: '/posts/:post_id'}); - }); - ``` - - The model for the `post` route is `store.find('post', params.post_id)`. - - By default, if your route has a dynamic segment ending in `_id`: - - * The model class is determined from the segment (`post_id`'s - class is `App.Post`) - * The find method is called on the model class with the value of - the dynamic segment. - - Note that for routes with dynamic segments, this hook is not always - executed. If the route is entered through a transition (e.g. when - using the `link-to` Handlebars helper or the `transitionTo` method - of routes), and a model context is already provided this hook - is not called. - - A model context does not include a primitive string or number, - which does cause the model hook to be called. - - Routes without dynamic segments will always execute the model hook. - - ```js - // no dynamic segment, model hook always called - this.transitionTo('posts'); - - // model passed in, so model hook not called - thePost = store.find('post', 1); - this.transitionTo('post', thePost); - - // integer passed in, model hook is called - this.transitionTo('post', 1); - ``` - - - This hook follows the asynchronous/promise semantics - described in the documentation for `beforeModel`. In particular, - if a promise returned from `model` fails, the error will be - handled by the `error` hook on `Ember.Route`. - - Example - - ```js - App.PostRoute = Ember.Route.extend({ - model: function(params) { - return this.store.find('post', params.post_id); - } - }); - ``` - - @method model - @param {Object} params the parameters extracted from the URL - @param {Transition} transition - @param {Object} queryParams the query params for this route - @return {Object|Promise} the model for this route. If - a promise is returned, the transition will pause until - the promise resolves, and the resolved value of the promise - will be used as the model for this route. - */ - model: function(params, transition) { - var match, name, sawParams, value; - - var queryParams = get(this, '_qp.map'); - - for (var prop in params) { - if (prop === 'queryParams' || (queryParams && prop in queryParams)) { - continue; - } - - if (match = prop.match(/^(.*)_id$/)) { - name = match[1]; - value = params[prop]; - } - sawParams = true; - } - - if (!name && sawParams) { return copy(params); } - else if (!name) { - if (transition.resolveIndex < 1) { return; } - - var parentModel = transition.state.handlerInfos[transition.resolveIndex-1].context; - - return parentModel; - } - - return this.findModel(name, value); - }, - - /** - @private - @method deserialize - @param {Object} params the parameters extracted from the URL - @param {Transition} transition - @return {Object|Promise} the model for this route. - - Router.js hook. - */ - deserialize: function(params, transition) { - return this.model(this.paramsFor(this.routeName), transition); - }, - - /** - - @method findModel - @param {String} type the model type - @param {Object} value the value passed to find - */ - findModel: function(){ - var store = get(this, 'store'); - return store.find.apply(store, arguments); - }, - - /** - Store property provides a hook for data persistence libraries to inject themselves. - - By default, this store property provides the exact same functionality previously - in the model hook. - - Currently, the required interface is: - - `store.find(modelName, findArguments)` - - @method store - @param {Object} store - */ - store: computed(function(){ - var container = this.container; - var routeName = this.routeName; - var namespace = get(this, 'router.namespace'); - - return { - find: function(name, value) { - var modelClass = container.lookupFactory('model:' + name); - - Ember.assert("You used the dynamic segment " + name + "_id in your route " + - routeName + ", but " + namespace + "." + classify(name) + - " did not exist and you did not override your route's `model` " + - "hook.", modelClass); - - if (!modelClass) { return; } - - Ember.assert(classify(name) + ' has no method `find`.', typeof modelClass.find === 'function'); - - return modelClass.find(value); - } - }; - }), - - /** - A hook you can implement to convert the route's model into parameters - for the URL. - - ```js - App.Router.map(function() { - this.resource('post', {path: '/posts/:post_id'}); - }); - - App.PostRoute = Ember.Route.extend({ - model: function(params) { - // the server returns `{ id: 12 }` - return jQuery.getJSON("/posts/" + params.post_id); - }, - - serialize: function(model) { - // this will make the URL `/posts/12` - return { post_id: model.id }; - } - }); - ``` - - The default `serialize` method will insert the model's `id` into the - route's dynamic segment (in this case, `:post_id`) if the segment contains '_id'. - If the route has multiple dynamic segments or does not contain '_id', `serialize` - will return `Ember.getProperties(model, params)` - - This method is called when `transitionTo` is called with a context - in order to populate the URL. - - @method serialize - @param {Object} model the route's model - @param {Array} params an Array of parameter names for the current - route (in the example, `['post_id']`. - @return {Object} the serialized parameters - */ - serialize: function(model, params) { - if (params.length < 1) { return; } - if (!model) { return; } - - var name = params[0], object = {}; - - if (/_id$/.test(name) && params.length === 1) { - object[name] = get(model, "id"); - } else { - object = getProperties(model, params); - } - - return object; - }, - - /** - A hook you can use to setup the controller for the current route. - - This method is called with the controller for the current route and the - model supplied by the `model` hook. - - By default, the `setupController` hook sets the `model` property of - the controller to the `model`. - - If you implement the `setupController` hook in your Route, it will - prevent this default behavior. If you want to preserve that behavior - when implementing your `setupController` function, make sure to call - `_super`: - - ```js - App.PhotosRoute = Ember.Route.extend({ - model: function() { - return this.store.find('photo'); - }, - - setupController: function (controller, model) { - // Call _super for default behavior - this._super(controller, model); - // Implement your custom setup after - this.controllerFor('application').set('showingPhotos', true); - } - }); - ``` - - This means that your template will get a proxy for the model as its - context, and you can act as though the model itself was the context. - - The provided controller will be one resolved based on the name - of this route. - - If no explicit controller is defined, Ember will automatically create - an appropriate controller for the model. - - * if the model is an `Ember.Array` (including record arrays from Ember - Data), the controller is an `Ember.ArrayController`. - * otherwise, the controller is an `Ember.ObjectController`. - - As an example, consider the router: - - ```js - App.Router.map(function() { - this.resource('post', {path: '/posts/:post_id'}); - }); - ``` - - For the `post` route, a controller named `App.PostController` would - be used if it is defined. If it is not defined, an `Ember.ObjectController` - instance would be used. - - Example - - ```js - App.PostRoute = Ember.Route.extend({ - setupController: function(controller, model) { - controller.set('model', model); - } - }); - ``` - - @method setupController - @param {Controller} controller instance - @param {Object} model - */ - setupController: function(controller, context, transition) { - if (controller && (context !== undefined)) { - set(controller, 'model', context); - } - }, - - /** - Returns the controller for a particular route or name. - - The controller instance must already have been created, either through entering the - associated route or using `generateController`. - - ```js - App.PostRoute = Ember.Route.extend({ - setupController: function(controller, post) { - this._super(controller, post); - this.controllerFor('posts').set('currentPost', post); - } - }); - ``` - - @method controllerFor - @param {String} name the name of the route or controller - @return {Ember.Controller} - */ - controllerFor: function(name, _skipAssert) { - var container = this.container; - var route = container.lookup('route:'+name); - var controller; - - if (route && route.controllerName) { - name = route.controllerName; - } - - controller = container.lookup('controller:' + name); - - // NOTE: We're specifically checking that skipAssert is true, because according - // to the old API the second parameter was model. We do not want people who - // passed a model to skip the assertion. - Ember.assert("The controller named '"+name+"' could not be found. Make sure " + - "that this route exists and has already been entered at least " + - "once. If you are accessing a controller not associated with a " + - "route, make sure the controller class is explicitly defined.", - controller || _skipAssert === true); - - return controller; - }, - - /** - Generates a controller for a route. - - If the optional model is passed then the controller type is determined automatically, - e.g., an ArrayController for arrays. - - Example - - ```js - App.PostRoute = Ember.Route.extend({ - setupController: function(controller, post) { - this._super(controller, post); - this.generateController('posts', post); - } - }); - ``` - - @method generateController - @param {String} name the name of the controller - @param {Object} model the model to infer the type of the controller (optional) - */ - generateController: function(name, model) { - var container = this.container; - - model = model || this.modelFor(name); - - return generateController(container, name, model); - }, - - /** - Returns the model of a parent (or any ancestor) route - in a route hierarchy. During a transition, all routes - must resolve a model object, and if a route - needs access to a parent route's model in order to - resolve a model (or just reuse the model from a parent), - it can call `this.modelFor(theNameOfParentRoute)` to - retrieve it. - - Example - - ```js - App.Router.map(function() { - this.resource('post', { path: '/post/:post_id' }, function() { - this.resource('comments'); - }); - }); - - App.CommentsRoute = Ember.Route.extend({ - afterModel: function() { - this.set('post', this.modelFor('post')); - } - }); - ``` - - @method modelFor - @param {String} name the name of the route - @return {Object} the model object - */ - modelFor: function(name) { - var route = this.container.lookup('route:' + name); - var transition = this.router ? this.router.router.activeTransition : null; - - // If we are mid-transition, we want to try and look up - // resolved parent contexts on the current transitionEvent. - if (transition) { - var modelLookupName = (route && route.routeName) || name; - if (transition.resolvedModels.hasOwnProperty(modelLookupName)) { - return transition.resolvedModels[modelLookupName]; - } - } - - return route && route.currentModel; - }, - - /** - A hook you can use to render the template for the current route. - - This method is called with the controller for the current route and the - model supplied by the `model` hook. By default, it renders the route's - template, configured with the controller for the route. - - This method can be overridden to set up and render additional or - alternative templates. - - ```js - App.PostsRoute = Ember.Route.extend({ - renderTemplate: function(controller, model) { - var favController = this.controllerFor('favoritePost'); - - // Render the `favoritePost` template into - // the outlet `posts`, and display the `favoritePost` - // controller. - this.render('favoritePost', { - outlet: 'posts', - controller: favController - }); - } - }); - ``` - - @method renderTemplate - @param {Object} controller the route's controller - @param {Object} model the route's model - */ - renderTemplate: function(controller, model) { - this.render(); - }, - - /** - `render` is used to render a template into a region of another template - (indicated by an `{{outlet}}`). `render` is used both during the entry - phase of routing (via the `renderTemplate` hook) and later in response to - user interaction. - - For example, given the following minimal router and templates: - - ```js - Router.map(function() { - this.resource('photos'); - }); - ``` - - ```handlebars - -
    - {{outlet "anOutletName"}} -
    - ``` - - ```handlebars - -

    Photos

    - ``` - - You can render `photos.hbs` into the `"anOutletName"` outlet of - `application.hbs` by calling `render`: - - ```js - // posts route - Ember.Route.extend({ - renderTemplate: function(){ - this.render('photos', { - into: 'application', - outlet: 'anOutletName' - }) - } - }); - ``` - - `render` additionally allows you to supply which `view`, `controller`, and - `model` objects should be loaded and associated with the rendered template. - - - ```js - // posts route - Ember.Route.extend({ - renderTemplate: function(controller, model){ - this.render('posts', { // the template to render, referenced by name - into: 'application', // the template to render into, referenced by name - outlet: 'anOutletName', // the outlet inside `options.template` to render into. - view: 'aViewName', // the view to use for this template, referenced by name - controller: 'someControllerName', // the controller to use for this template, referenced by name - model: model // the model to set on `options.controller`. - }) - } - }); - ``` - - The string values provided for the template name, view, and controller - will eventually pass through to the resolver for lookup. See - Ember.Resolver for how these are mapped to JavaScript objects in your - application. - - Not all options need to be passed to `render`. Default values will be used - based on the name of the route specified in the router or the Route's - `controllerName`, `viewName` and and `templateName` properties. - - For example: - - ```js - // router - Router.map(function() { - this.route('index'); - this.resource('post', {path: '/posts/:post_id'}); - }); - ``` - - ```js - // post route - PostRoute = App.Route.extend({ - renderTemplate: function() { - this.render(); // all defaults apply - } - }); - ``` - - The name of the `PostRoute`, defined by the router, is `post`. - - The following equivalent default options will be applied when - the Route calls `render`: - - ```js - // - this.render('post', { // the template name associated with 'post' Route - into: 'application', // the parent route to 'post' Route - outlet: 'main', // {{outlet}} and {{outlet 'main' are synonymous}}, - view: 'post', // the view associated with the 'post' Route - controller: 'post', // the controller associated with the 'post' Route - }) - ``` - - By default the controller's `model` will be the route's model, so it does not - need to be passed unless you wish to change which model is being used. - - @method render - @param {String} name the name of the template to render - @param {Object} [options] the options - @param {String} [options.into] the template to render into, - referenced by name. Defaults to the parent template - @param {String} [options.outlet] the outlet inside `options.template` to render into. - Defaults to 'main' - @param {String} [options.controller] the controller to use for this template, - referenced by name. Defaults to the Route's paired controller - @param {String} [options.model] the model object to set on `options.controller` - Defaults to the return value of the Route's model hook - */ - render: function(name, options) { - Ember.assert("The name in the given arguments is undefined", arguments.length > 0 ? !isNone(arguments[0]) : true); - - var namePassed = typeof name === 'string' && !!name; - - if (typeof name === 'object' && !options) { - options = name; - name = this.routeName; - } - - options = options || {}; - options.namePassed = namePassed; - - var templateName; - - if (name) { - name = name.replace(/\//g, '.'); - templateName = name; - } else { - name = this.routeName; - templateName = this.templateName || name; - } - - var viewName = options.view || namePassed && name || this.viewName || name; - - var container = this.container; - var view = container.lookup('view:' + viewName); - var template = view ? view.get('template') : null; - - if (!template) { - template = container.lookup('template:' + templateName); - } - - if (!view && !template) { - Ember.assert("Could not find \"" + name + "\" template or view.", Ember.isEmpty(arguments[0])); - if (get(this.router, 'namespace.LOG_VIEW_LOOKUPS')) { - Ember.Logger.info("Could not find \"" + name + "\" template or view. Nothing will be rendered", { fullName: 'template:' + name }); - } - return; - } - - options = normalizeOptions(this, name, template, options); - view = setupView(view, container, options); - - if (options.outlet === 'main') { this.lastRenderedTemplate = name; } - - appendView(this, view, options); - }, - - /** - Disconnects a view that has been rendered into an outlet. - - You may pass any or all of the following options to `disconnectOutlet`: - - * `outlet`: the name of the outlet to clear (default: 'main') - * `parentView`: the name of the view containing the outlet to clear - (default: the view rendered by the parent route) - - Example: - - ```js - App.ApplicationRoute = App.Route.extend({ - actions: { - showModal: function(evt) { - this.render(evt.modalName, { - outlet: 'modal', - into: 'application' - }); - }, - hideModal: function(evt) { - this.disconnectOutlet({ - outlet: 'modal', - parentView: 'application' - }); - } - } - }); - ``` - - Alternatively, you can pass the `outlet` name directly as a string. - - Example: - - ```js - hideModal: function(evt) { - this.disconnectOutlet('modal'); - } - ``` - - @method disconnectOutlet - @param {Object|String} options the options hash or outlet name - */ - disconnectOutlet: function(options) { - if (!options || typeof options === "string") { - var outletName = options; - options = {}; - options.outlet = outletName; - } - options.parentView = options.parentView ? options.parentView.replace(/\//g, '.') : parentTemplate(this); - options.outlet = options.outlet || 'main'; - - var parentView = this.router._lookupActiveView(options.parentView); - if (parentView) { parentView.disconnectOutlet(options.outlet); } - }, - - willDestroy: function() { - this.teardownViews(); - }, - - /** - @private - - @method teardownViews - */ - teardownViews: function() { - // Tear down the top level view - if (this.teardownTopLevelView) { this.teardownTopLevelView(); } - - // Tear down any outlets rendered with 'into' - var teardownOutletViews = this.teardownOutletViews || []; - forEach(teardownOutletViews, function(teardownOutletView) { - teardownOutletView(); - }); - - delete this.teardownTopLevelView; - delete this.teardownOutletViews; - delete this.lastRenderedTemplate; - } - }); - - var defaultQPMeta = { - qps: [], - map: {}, - states: {} - }; - - function parentRoute(route) { - var handlerInfo = handlerInfoFor(route, route.router.router.state.handlerInfos, -1); - return handlerInfo && handlerInfo.handler; - } - - function handlerInfoFor(route, handlerInfos, _offset) { - if (!handlerInfos) { return; } - - var offset = _offset || 0, current; - for (var i=0, l=handlerInfos.length; i " + routeName, { fullName: routeName }); - } - } - - handler.routeName = name; - return handler; - }; - }, - - _setupRouter: function(router, location) { - var lastURL, emberRouter = this; - - router.getHandler = this._getHandlerFunction(); - - var doUpdateURL = function() { - location.setURL(lastURL); - }; - - router.updateURL = function(path) { - lastURL = path; - run.once(doUpdateURL); - }; - - if (location.replaceURL) { - var doReplaceURL = function() { - location.replaceURL(lastURL); - }; - - router.replaceURL = function(path) { - lastURL = path; - run.once(doReplaceURL); - }; - } - - router.didTransition = function(infos) { - emberRouter.didTransition(infos); - }; - }, - - _serializeQueryParams: function(targetRouteName, queryParams) { - var groupedByUrlKey = {}; - - forEachQueryParam(this, targetRouteName, queryParams, function(key, value, qp) { - var urlKey = qp.urlKey; - if (!groupedByUrlKey[urlKey]) { - groupedByUrlKey[urlKey] = []; - } - groupedByUrlKey[urlKey].push({ - qp: qp, - value: value - }); - delete queryParams[key]; - }); - - for (var key in groupedByUrlKey) { - var qps = groupedByUrlKey[key]; - if (qps.length > 1) { - var qp0 = qps[0].qp, qp1=qps[1].qp; - Ember.assert(fmt("You're not allowed to have more than one controller property map to the same query param key, but both `%@` and `%@` map to `%@`. You can fix this by mapping one of the controller properties to a different query param key via the `as` config option, e.g. `%@: { as: 'other-%@' }`", [qp0.fprop, qp1.fprop, qp0.urlKey, qp0.prop, qp0.prop]), false); - } - var qp = qps[0].qp; - queryParams[qp.urlKey] = qp.route.serializeQueryParam(qps[0].value, qp.urlKey, qp.type); - } - }, - - _deserializeQueryParams: function(targetRouteName, queryParams) { - forEachQueryParam(this, targetRouteName, queryParams, function(key, value, qp) { - delete queryParams[key]; - queryParams[qp.prop] = qp.route.deserializeQueryParam(value, qp.urlKey, qp.type); - }); - }, - - _pruneDefaultQueryParamValues: function(targetRouteName, queryParams) { - var qps = this._queryParamsFor(targetRouteName); - for (var key in queryParams) { - var qp = qps.map[key]; - if (qp && qp.sdef === queryParams[key]) { - delete queryParams[key]; - } - } - }, - - _doTransition: function(_targetRouteName, models, _queryParams) { - var targetRouteName = _targetRouteName || getActiveTargetName(this.router); - Ember.assert("The route " + targetRouteName + " was not found", targetRouteName && this.router.hasRoute(targetRouteName)); - - var queryParams = {}; - merge(queryParams, _queryParams); - this._prepareQueryParams(targetRouteName, models, queryParams); - - var transitionArgs = routeArgs(targetRouteName, models, queryParams); - var transitionPromise = this.router.transitionTo.apply(this.router, transitionArgs); - - listenForTransitionErrors(transitionPromise); - - return transitionPromise; - }, - - _prepareQueryParams: function(targetRouteName, models, queryParams) { - this._hydrateUnsuppliedQueryParams(targetRouteName, models, queryParams); - this._serializeQueryParams(targetRouteName, queryParams); - this._pruneDefaultQueryParamValues(targetRouteName, queryParams); - }, - - /** - Returns a merged query params meta object for a given route. - Useful for asking a route what its known query params are. - */ - _queryParamsFor: function(leafRouteName) { - if (this._qpCache[leafRouteName]) { - return this._qpCache[leafRouteName]; - } - - var map = {}, qps = [], qpCache = this._qpCache[leafRouteName] = { - map: map, - qps: qps - }; - - var routerjs = this.router; - var recogHandlerInfos = routerjs.recognizer.handlersFor(leafRouteName); - - for (var i = 0, len = recogHandlerInfos.length; i < len; ++i) { - var recogHandler = recogHandlerInfos[i]; - var route = routerjs.getHandler(recogHandler.handler); - var qpMeta = get(route, '_qp'); - - if (!qpMeta) { continue; } - - merge(map, qpMeta.map); - qps.push.apply(qps, qpMeta.qps); - } - - return { - qps: qps, - map: map - }; - }, - - /* - becomeResolved: function(payload, resolvedContext) { - var params = this.serialize(resolvedContext); - - if (payload) { - this.stashResolvedModel(payload, resolvedContext); - payload.params = payload.params || {}; - payload.params[this.name] = params; - } - - return this.factory('resolved', { - context: resolvedContext, - name: this.name, - handler: this.handler, - params: params - }); - }, - */ - - _hydrateUnsuppliedQueryParams: function(leafRouteName, contexts, queryParams) { - var state = calculatePostTransitionState(this, leafRouteName, contexts); - var handlerInfos = state.handlerInfos; - var appCache = this._bucketCache; - - stashParamNames(this, handlerInfos); - - for (var i = 0, len = handlerInfos.length; i < len; ++i) { - var route = handlerInfos[i].handler; - var qpMeta = get(route, '_qp'); - - for (var j = 0, qpLen = qpMeta.qps.length; j < qpLen; ++j) { - var qp = qpMeta.qps[j]; - var presentProp = qp.prop in queryParams && qp.prop || - qp.fprop in queryParams && qp.fprop; - - if (presentProp) { - if (presentProp !== qp.fprop) { - queryParams[qp.fprop] = queryParams[presentProp]; - delete queryParams[presentProp]; - } - } else { - var controllerProto = qp.cProto; - var cacheMeta = get(controllerProto, '_cacheMeta'); - - var cacheKey = controllerProto._calculateCacheKey(qp.ctrl, cacheMeta[qp.prop].parts, state.params); - queryParams[qp.fprop] = appCache.lookup(cacheKey, qp.prop, qp.def); - } - } - } - }, - - _scheduleLoadingEvent: function(transition, originRoute) { - this._cancelLoadingEvent(); - this._loadingStateTimer = run.scheduleOnce('routerTransitions', this, '_fireLoadingEvent', transition, originRoute); - }, - - _fireLoadingEvent: function(transition, originRoute) { - if (!this.router.activeTransition) { - // Don't fire an event if we've since moved on from - // the transition that put us in a loading state. - return; - } - - transition.trigger(true, 'loading', transition, originRoute); - }, - - _cancelLoadingEvent: function () { - if (this._loadingStateTimer) { - run.cancel(this._loadingStateTimer); - } - this._loadingStateTimer = null; - } - }); - - /* - Helper function for iterating root-ward, starting - from (but not including) the provided `originRoute`. - - Returns true if the last callback fired requested - to bubble upward. - - @private - */ - function forEachRouteAbove(originRoute, transition, callback) { - var handlerInfos = transition.state.handlerInfos; - var originRouteFound = false; - var handlerInfo, route; - - for (var i = handlerInfos.length - 1; i >= 0; --i) { - handlerInfo = handlerInfos[i]; - route = handlerInfo.handler; - - if (!originRouteFound) { - if (originRoute === route) { - originRouteFound = true; - } - continue; - } - - if (callback(route, handlerInfos[i + 1].handler) !== true) { - return false; - } - } - return true; - } - - // These get invoked when an action bubbles above ApplicationRoute - // and are not meant to be overridable. - var defaultActionHandlers = { - - willResolveModel: function(transition, originRoute) { - originRoute.router._scheduleLoadingEvent(transition, originRoute); - }, - - error: function(error, transition, originRoute) { - // Attempt to find an appropriate error substate to enter. - var router = originRoute.router; - - var tryTopLevel = forEachRouteAbove(originRoute, transition, function(route, childRoute) { - var childErrorRouteName = findChildRouteName(route, childRoute, 'error'); - if (childErrorRouteName) { - router.intermediateTransitionTo(childErrorRouteName, error); - return; - } - return true; - }); - - if (tryTopLevel) { - // Check for top-level error state to enter. - if (routeHasBeenDefined(originRoute.router, 'application_error')) { - router.intermediateTransitionTo('application_error', error); - return; - } - } - - logError(error, 'Error while processing route: ' + transition.targetName); - }, - - loading: function(transition, originRoute) { - // Attempt to find an appropriate loading substate to enter. - var router = originRoute.router; - - var tryTopLevel = forEachRouteAbove(originRoute, transition, function(route, childRoute) { - var childLoadingRouteName = findChildRouteName(route, childRoute, 'loading'); - - if (childLoadingRouteName) { - router.intermediateTransitionTo(childLoadingRouteName); - return; - } - - // Don't bubble above pivot route. - if (transition.pivotHandler !== route) { - return true; - } - }); - - if (tryTopLevel) { - // Check for top-level loading state to enter. - if (routeHasBeenDefined(originRoute.router, 'application_loading')) { - router.intermediateTransitionTo('application_loading'); - return; - } - } - } - }; - - function logError(error, initialMessage) { - var errorArgs = []; - - if (initialMessage) { errorArgs.push(initialMessage); } - - if (error) { - if (error.message) { errorArgs.push(error.message); } - if (error.stack) { errorArgs.push(error.stack); } - - if (typeof error === "string") { errorArgs.push(error); } - } - - Ember.Logger.error.apply(this, errorArgs); - } - - function findChildRouteName(parentRoute, originatingChildRoute, name) { - var router = parentRoute.router; - var childName; - var targetChildRouteName = originatingChildRoute.routeName.split('.').pop(); - var namespace = parentRoute.routeName === 'application' ? '' : parentRoute.routeName + '.'; - - - // Second, try general loading state, e.g. 'loading' - childName = namespace + name; - if (routeHasBeenDefined(router, childName)) { - return childName; - } - } - - function routeHasBeenDefined(router, name) { - var container = router.container; - return router.hasRoute(name) && - (container.has('template:' + name) || container.has('route:' + name)); - } - - function triggerEvent(handlerInfos, ignoreFailure, args) { - var name = args.shift(); - - if (!handlerInfos) { - if (ignoreFailure) { return; } - throw new EmberError("Can't trigger action '" + name + "' because your app hasn't finished transitioning into its first route. To trigger an action on destination routes during a transition, you can call `.send()` on the `Transition` object passed to the `model/beforeModel/afterModel` hooks."); - } - - var eventWasHandled = false; - var handlerInfo, handler; - - for (var i = handlerInfos.length - 1; i >= 0; i--) { - handlerInfo = handlerInfos[i]; - handler = handlerInfo.handler; - - if (handler._actions && handler._actions[name]) { - if (handler._actions[name].apply(handler, args) === true) { - eventWasHandled = true; - } else { - return; - } - } - } - - if (defaultActionHandlers[name]) { - defaultActionHandlers[name].apply(null, args); - return; - } - - if (!eventWasHandled && !ignoreFailure) { - throw new EmberError("Nothing handled the action '" + name + "'. If you did handle the action, this error can be caused by returning true from an action handler in a controller, causing the action to bubble."); - } - } - - function calculatePostTransitionState(emberRouter, leafRouteName, contexts) { - var routerjs = emberRouter.router; - var state = routerjs.applyIntent(leafRouteName, contexts); - var handlerInfos = state.handlerInfos; - var params = state.params; - - for (var i = 0, len = handlerInfos.length; i < len; ++i) { - var handlerInfo = handlerInfos[i]; - if (!handlerInfo.isResolved) { - handlerInfo = handlerInfo.becomeResolved(null, handlerInfo.context); - } - params[handlerInfo.name] = handlerInfo.params; - } - return state; - } - - function updatePaths(router) { - var appController = router.container.lookup('controller:application'); - - if (!appController) { - // appController might not exist when top-level loading/error - // substates have been entered since ApplicationRoute hasn't - // actually been entered at that point. - return; - } - - var infos = router.router.currentHandlerInfos; - var path = EmberRouter._routePath(infos); - - if (!('currentPath' in appController)) { - defineProperty(appController, 'currentPath'); - } - - set(appController, 'currentPath', path); - - if (!('currentRouteName' in appController)) { - defineProperty(appController, 'currentRouteName'); - } - - set(appController, 'currentRouteName', infos[infos.length - 1].name); - } - - EmberRouter.reopenClass({ - router: null, - - /** - The `Router.map` function allows you to define mappings from URLs to routes - and resources in your application. These mappings are defined within the - supplied callback function using `this.resource` and `this.route`. - - ```javascript - App.Router.map(function({ - this.route('about'); - this.resource('article'); - })); - ``` - - For more detailed examples please see - [the guides](http://emberjs.com/guides/routing/defining-your-routes/). - - @method map - @param callback - */ - map: function(callback) { - var router = this.router; - if (!router) { - router = new Router(); - - - router._triggerWillChangeContext = Ember.K; - router._triggerWillLeave = Ember.K; - - - router.callbacks = []; - router.triggerEvent = triggerEvent; - this.reopenClass({ router: router }); - } - - var dsl = EmberRouterDSL.map(function() { - this.resource('application', { path: "/" }, function() { - for (var i=0; i < router.callbacks.length; i++) { - router.callbacks[i].call(this); - } - callback.call(this); - }); - }); - - router.callbacks.push(callback); - router.map(dsl.generate()); - return router; - }, - - _routePath: function(handlerInfos) { - var path = []; - - // We have to handle coalescing resource names that - // are prefixed with their parent's names, e.g. - // ['foo', 'foo.bar.baz'] => 'foo.bar.baz', not 'foo.foo.bar.baz' - - function intersectionMatches(a1, a2) { - for (var i = 0, len = a1.length; i < len; ++i) { - if (a1[i] !== a2[i]) { - return false; - } - } - return true; - } - - var name, nameParts, oldNameParts; - for (var i=1, l=handlerInfos.length; i 0) - (diff < 0); - } - - /** - This will compare two javascript values of possibly different types. - It will tell you which one is greater than the other by returning: - - - -1 if the first is smaller than the second, - - 0 if both are equal, - - 1 if the first is greater than the second. - - The order is calculated based on `Ember.ORDER_DEFINITION`, if types are different. - In case they have the same type an appropriate comparison for this type is made. - - ```javascript - Ember.compare('hello', 'hello'); // 0 - Ember.compare('abc', 'dfg'); // -1 - Ember.compare(2, 1); // 1 - ``` - - @method compare - @for Ember - @param {Object} v First value to compare - @param {Object} w Second value to compare - @return {Number} -1 if v < w, 0 if v = w and 1 if v > w. - */ - __exports__["default"] = function compare(v, w) { - if (v === w) { - return 0; - } - - var type1 = typeOf(v); - var type2 = typeOf(w); - - if (Comparable) { - if (type1 ==='instance' && Comparable.detect(v.constructor)) { - return v.constructor.compare(v, w); - } - - if (type2 === 'instance' && Comparable.detect(w.constructor)) { - return 1 - w.constructor.compare(w, v); - } - } - - var res = spaceship(TYPE_ORDER[type1], TYPE_ORDER[type2]); - if (res !== 0) { - return res; - } - - // types are equal - so we have to check values now - switch (type1) { - case 'boolean': - case 'number': - return spaceship(v,w); - - case 'string': - return spaceship(v.localeCompare(w), 0); - - case 'array': - var vLen = v.length; - var wLen = w.length; - var len = Math.min(vLen, wLen); - - for (var i = 0; i < len; i++) { - var r = compare(v[i], w[i]); - if (r !== 0) { - return r; - } - } - - // all elements are equal now - // shorter array should be ordered first - return spaceship(vLen, wLen); - - case 'instance': - if (Comparable && Comparable.detect(v)) { - return v.compare(v, w); - } - return 0; - - case 'date': - return spaceship(v.getTime(), w.getTime()); - - default: - return 0; - } - } - }); -enifed("ember-runtime/computed/array_computed", - ["ember-metal/core","ember-runtime/computed/reduce_computed","ember-metal/enumerable_utils","ember-metal/platform","ember-metal/observer","ember-metal/error","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __exports__) { - "use strict"; - var Ember = __dependency1__["default"]; - var reduceComputed = __dependency2__.reduceComputed; - var ReduceComputedProperty = __dependency2__.ReduceComputedProperty; - var forEach = __dependency3__.forEach; - var o_create = __dependency4__.create; - var addObserver = __dependency5__.addObserver; - var EmberError = __dependency6__["default"]; - - var a_slice = [].slice; - - function ArrayComputedProperty() { - var cp = this; - - ReduceComputedProperty.apply(this, arguments); - - this.func = (function(reduceFunc) { - return function (propertyName) { - if (!cp._hasInstanceMeta(this, propertyName)) { - // When we recompute an array computed property, we need already - // retrieved arrays to be updated; we can't simply empty the cache and - // hope the array is re-retrieved. - forEach(cp._dependentKeys, function(dependentKey) { - addObserver(this, dependentKey, function() { - cp.recomputeOnce.call(this, propertyName); - }); - }, this); - } - - return reduceFunc.apply(this, arguments); - }; - })(this.func); - - return this; - } - - ArrayComputedProperty.prototype = o_create(ReduceComputedProperty.prototype); - - ArrayComputedProperty.prototype.initialValue = function () { - return Ember.A(); - }; - - ArrayComputedProperty.prototype.resetValue = function (array) { - array.clear(); - return array; - }; - - // This is a stopgap to keep the reference counts correct with lazy CPs. - ArrayComputedProperty.prototype.didChange = function (obj, keyName) { - return; - }; - - /** - Creates a computed property which operates on dependent arrays and - is updated with "one at a time" semantics. When items are added or - removed from the dependent array(s) an array computed only operates - on the change instead of re-evaluating the entire array. This should - return an array, if you'd like to use "one at a time" semantics and - compute some value other then an array look at - `Ember.reduceComputed`. - - If there are more than one arguments the first arguments are - considered to be dependent property keys. The last argument is - required to be an options object. The options object can have the - following three properties. - - `initialize` - An optional initialize function. Typically this will be used - to set up state on the instanceMeta object. - - `removedItem` - A function that is called each time an element is - removed from the array. - - `addedItem` - A function that is called each time an element is - added to the array. - - - The `initialize` function has the following signature: - - ```javascript - function(array, changeMeta, instanceMeta) - ``` - - `array` - The initial value of the arrayComputed, an empty array. - - `changeMeta` - An object which contains meta information about the - computed. It contains the following properties: - - - `property` the computed property - - `propertyName` the name of the property on the object - - `instanceMeta` - An object that can be used to store meta - information needed for calculating your computed. For example a - unique computed might use this to store the number of times a given - element is found in the dependent array. - - - The `removedItem` and `addedItem` functions both have the following signature: - - ```javascript - function(accumulatedValue, item, changeMeta, instanceMeta) - ``` - - `accumulatedValue` - The value returned from the last time - `removedItem` or `addedItem` was called or an empty array. - - `item` - the element added or removed from the array - - `changeMeta` - An object which contains meta information about the - change. It contains the following properties: - - - `property` the computed property - - `propertyName` the name of the property on the object - - `index` the index of the added or removed item - - `item` the added or removed item: this is exactly the same as - the second arg - - `arrayChanged` the array that triggered the change. Can be - useful when depending on multiple arrays. - - For property changes triggered on an item property change (when - depKey is something like `someArray.@each.someProperty`), - `changeMeta` will also contain the following property: - - - `previousValues` an object whose keys are the properties that changed on - the item, and whose values are the item's previous values. - - `previousValues` is important Ember coalesces item property changes via - Ember.run.once. This means that by the time removedItem gets called, item has - the new values, but you may need the previous value (eg for sorting & - filtering). - - `instanceMeta` - An object that can be used to store meta - information needed for calculating your computed. For example a - unique computed might use this to store the number of times a given - element is found in the dependent array. - - The `removedItem` and `addedItem` functions should return the accumulated - value. It is acceptable to not return anything (ie return undefined) - to invalidate the computation. This is generally not a good idea for - arrayComputed but it's used in eg max and min. - - Example - - ```javascript - Ember.computed.map = function(dependentKey, callback) { - var options = { - addedItem: function(array, item, changeMeta, instanceMeta) { - var mapped = callback(item); - array.insertAt(changeMeta.index, mapped); - return array; - }, - removedItem: function(array, item, changeMeta, instanceMeta) { - array.removeAt(changeMeta.index, 1); - return array; - } - }; - - return Ember.arrayComputed(dependentKey, options); - }; - ``` - - @method arrayComputed - @for Ember - @param {String} [dependentKeys*] - @param {Object} options - @return {Ember.ComputedProperty} - */ - function arrayComputed (options) { - var args; - - if (arguments.length > 1) { - args = a_slice.call(arguments, 0, -1); - options = a_slice.call(arguments, -1)[0]; - } - - if (typeof options !== 'object') { - throw new EmberError('Array Computed Property declared without an options hash'); - } - - var cp = new ArrayComputedProperty(options); - - if (args) { - cp.property.apply(cp, args); - } - - return cp; - } - - __exports__.arrayComputed = arrayComputed; - __exports__.ArrayComputedProperty = ArrayComputedProperty; - }); -enifed("ember-runtime/computed/reduce_computed", - ["ember-metal/core","ember-metal/property_get","ember-metal/property_set","ember-metal/utils","ember-metal/error","ember-metal/property_events","ember-metal/expand_properties","ember-metal/observer","ember-metal/computed","ember-metal/platform","ember-metal/enumerable_utils","ember-runtime/system/tracked_array","ember-runtime/mixins/array","ember-metal/run_loop","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __dependency11__, __dependency12__, __dependency13__, __dependency14__, __exports__) { - "use strict"; - var Ember = __dependency1__["default"]; - // Ember.assert - var e_get = __dependency2__.get; - var set = __dependency3__.set; - var guidFor = __dependency4__.guidFor; - var metaFor = __dependency4__.meta; - var EmberError = __dependency5__["default"]; - var propertyWillChange = __dependency6__.propertyWillChange; - var propertyDidChange = __dependency6__.propertyDidChange; - var expandProperties = __dependency7__["default"]; - var addObserver = __dependency8__.addObserver; - var observersFor = __dependency8__.observersFor; - var removeObserver = __dependency8__.removeObserver; - var addBeforeObserver = __dependency8__.addBeforeObserver; - var removeBeforeObserver = __dependency8__.removeBeforeObserver; - var ComputedProperty = __dependency9__.ComputedProperty; - var cacheFor = __dependency9__.cacheFor; - var o_create = __dependency10__.create; - var forEach = __dependency11__.forEach; - var TrackedArray = __dependency12__["default"]; - var EmberArray = __dependency13__["default"]; - var run = __dependency14__["default"]; - var isArray = __dependency4__.isArray; - - var cacheSet = cacheFor.set; - var cacheGet = cacheFor.get; - var cacheRemove = cacheFor.remove; - var a_slice = [].slice; - // Here we explicitly don't allow `@each.foo`; it would require some special - // testing, but there's no particular reason why it should be disallowed. - var eachPropertyPattern = /^(.*)\.@each\.(.*)/; - var doubleEachPropertyPattern = /(.*\.@each){2,}/; - var arrayBracketPattern = /\.\[\]$/; - - function get(obj, key) { - if (key === '@this') { - return obj; - } - - return e_get(obj, key); - } - - /* - Tracks changes to dependent arrays, as well as to properties of items in - dependent arrays. - - @class DependentArraysObserver - */ - function DependentArraysObserver(callbacks, cp, instanceMeta, context, propertyName, sugarMeta) { - // user specified callbacks for `addedItem` and `removedItem` - this.callbacks = callbacks; - - // the computed property: remember these are shared across instances - this.cp = cp; - - // the ReduceComputedPropertyInstanceMeta this DependentArraysObserver is - // associated with - this.instanceMeta = instanceMeta; - - // A map of array guids to dependentKeys, for the given context. We track - // this because we want to set up the computed property potentially before the - // dependent array even exists, but when the array observer fires, we lack - // enough context to know what to update: we can recover that context by - // getting the dependentKey. - this.dependentKeysByGuid = {}; - - // a map of dependent array guids -> TrackedArray instances. We use - // this to lazily recompute indexes for item property observers. - this.trackedArraysByGuid = {}; - - // We suspend observers to ignore replacements from `reset` when totally - // recomputing. Unfortunately we cannot properly suspend the observers - // because we only have the key; instead we make the observers no-ops - this.suspended = false; - - // This is used to coalesce item changes from property observers within a - // single item. - this.changedItems = {}; - // This is used to coalesce item changes for multiple items that depend on - // some shared state. - this.changedItemCount = 0; - } - - function ItemPropertyObserverContext (dependentArray, index, trackedArray) { - Ember.assert('Internal error: trackedArray is null or undefined', trackedArray); - - this.dependentArray = dependentArray; - this.index = index; - this.item = dependentArray.objectAt(index); - this.trackedArray = trackedArray; - this.beforeObserver = null; - this.observer = null; - this.destroyed = false; - } - - DependentArraysObserver.prototype = { - setValue: function (newValue) { - this.instanceMeta.setValue(newValue, true); - }, - - getValue: function () { - return this.instanceMeta.getValue(); - }, - - setupObservers: function (dependentArray, dependentKey) { - this.dependentKeysByGuid[guidFor(dependentArray)] = dependentKey; - - dependentArray.addArrayObserver(this, { - willChange: 'dependentArrayWillChange', - didChange: 'dependentArrayDidChange' - }); - - if (this.cp._itemPropertyKeys[dependentKey]) { - this.setupPropertyObservers(dependentKey, this.cp._itemPropertyKeys[dependentKey]); - } - }, - - teardownObservers: function (dependentArray, dependentKey) { - var itemPropertyKeys = this.cp._itemPropertyKeys[dependentKey] || []; - - delete this.dependentKeysByGuid[guidFor(dependentArray)]; - - this.teardownPropertyObservers(dependentKey, itemPropertyKeys); - - dependentArray.removeArrayObserver(this, { - willChange: 'dependentArrayWillChange', - didChange: 'dependentArrayDidChange' - }); - }, - - suspendArrayObservers: function (callback, binding) { - var oldSuspended = this.suspended; - this.suspended = true; - callback.call(binding); - this.suspended = oldSuspended; - }, - - setupPropertyObservers: function (dependentKey, itemPropertyKeys) { - var dependentArray = get(this.instanceMeta.context, dependentKey); - var length = get(dependentArray, 'length'); - var observerContexts = new Array(length); - - this.resetTransformations(dependentKey, observerContexts); - - forEach(dependentArray, function (item, index) { - var observerContext = this.createPropertyObserverContext(dependentArray, index, this.trackedArraysByGuid[dependentKey]); - observerContexts[index] = observerContext; - - forEach(itemPropertyKeys, function (propertyKey) { - addBeforeObserver(item, propertyKey, this, observerContext.beforeObserver); - addObserver(item, propertyKey, this, observerContext.observer); - }, this); - }, this); - }, - - teardownPropertyObservers: function (dependentKey, itemPropertyKeys) { - var dependentArrayObserver = this; - var trackedArray = this.trackedArraysByGuid[dependentKey]; - var beforeObserver, observer, item; - - if (!trackedArray) { return; } - - trackedArray.apply(function (observerContexts, offset, operation) { - if (operation === TrackedArray.DELETE) { return; } - - forEach(observerContexts, function (observerContext) { - observerContext.destroyed = true; - beforeObserver = observerContext.beforeObserver; - observer = observerContext.observer; - item = observerContext.item; - - forEach(itemPropertyKeys, function (propertyKey) { - removeBeforeObserver(item, propertyKey, dependentArrayObserver, beforeObserver); - removeObserver(item, propertyKey, dependentArrayObserver, observer); - }); - }); - }); - }, - - createPropertyObserverContext: function (dependentArray, index, trackedArray) { - var observerContext = new ItemPropertyObserverContext(dependentArray, index, trackedArray); - - this.createPropertyObserver(observerContext); - - return observerContext; - }, - - createPropertyObserver: function (observerContext) { - var dependentArrayObserver = this; - - observerContext.beforeObserver = function (obj, keyName) { - return dependentArrayObserver.itemPropertyWillChange(obj, keyName, observerContext.dependentArray, observerContext); - }; - - observerContext.observer = function (obj, keyName) { - return dependentArrayObserver.itemPropertyDidChange(obj, keyName, observerContext.dependentArray, observerContext); - }; - }, - - resetTransformations: function (dependentKey, observerContexts) { - this.trackedArraysByGuid[dependentKey] = new TrackedArray(observerContexts); - }, - - trackAdd: function (dependentKey, index, newItems) { - var trackedArray = this.trackedArraysByGuid[dependentKey]; - - if (trackedArray) { - trackedArray.addItems(index, newItems); - } - }, - - trackRemove: function (dependentKey, index, removedCount) { - var trackedArray = this.trackedArraysByGuid[dependentKey]; - - if (trackedArray) { - return trackedArray.removeItems(index, removedCount); - } - - return []; - }, - - updateIndexes: function (trackedArray, array) { - var length = get(array, 'length'); - // OPTIMIZE: we could stop updating once we hit the object whose observer - // fired; ie partially apply the transformations - trackedArray.apply(function (observerContexts, offset, operation, operationIndex) { - // we don't even have observer contexts for removed items, even if we did, - // they no longer have any index in the array - if (operation === TrackedArray.DELETE) { return; } - if (operationIndex === 0 && operation === TrackedArray.RETAIN && observerContexts.length === length && offset === 0) { - // If we update many items we don't want to walk the array each time: we - // only need to update the indexes at most once per run loop. - return; - } - - forEach(observerContexts, function (context, index) { - context.index = index + offset; - }); - }); - }, - - dependentArrayWillChange: function (dependentArray, index, removedCount, addedCount) { - if (this.suspended) { return; } - - var removedItem = this.callbacks.removedItem; - var changeMeta; - var guid = guidFor(dependentArray); - var dependentKey = this.dependentKeysByGuid[guid]; - var itemPropertyKeys = this.cp._itemPropertyKeys[dependentKey] || []; - var length = get(dependentArray, 'length'); - var normalizedIndex = normalizeIndex(index, length, 0); - var normalizedRemoveCount = normalizeRemoveCount(normalizedIndex, length, removedCount); - var item, itemIndex, sliceIndex, observerContexts; - - observerContexts = this.trackRemove(dependentKey, normalizedIndex, normalizedRemoveCount); - - function removeObservers(propertyKey) { - observerContexts[sliceIndex].destroyed = true; - removeBeforeObserver(item, propertyKey, this, observerContexts[sliceIndex].beforeObserver); - removeObserver(item, propertyKey, this, observerContexts[sliceIndex].observer); - } - - for (sliceIndex = normalizedRemoveCount - 1; sliceIndex >= 0; --sliceIndex) { - itemIndex = normalizedIndex + sliceIndex; - if (itemIndex >= length) { break; } - - item = dependentArray.objectAt(itemIndex); - - forEach(itemPropertyKeys, removeObservers, this); - - changeMeta = new ChangeMeta(dependentArray, item, itemIndex, this.instanceMeta.propertyName, this.cp, normalizedRemoveCount); - this.setValue(removedItem.call( - this.instanceMeta.context, this.getValue(), item, changeMeta, this.instanceMeta.sugarMeta)); - } - this.callbacks.flushedChanges.call(this.instanceMeta.context, this.getValue(), this.instanceMeta.sugarMeta); - }, - - dependentArrayDidChange: function (dependentArray, index, removedCount, addedCount) { - if (this.suspended) { return; } - - var addedItem = this.callbacks.addedItem; - var guid = guidFor(dependentArray); - var dependentKey = this.dependentKeysByGuid[guid]; - var observerContexts = new Array(addedCount); - var itemPropertyKeys = this.cp._itemPropertyKeys[dependentKey]; - var length = get(dependentArray, 'length'); - var normalizedIndex = normalizeIndex(index, length, addedCount); - var endIndex = normalizedIndex + addedCount; - var changeMeta, observerContext; - - forEach(dependentArray.slice(normalizedIndex, endIndex), function (item, sliceIndex) { - if (itemPropertyKeys) { - observerContext = this.createPropertyObserverContext(dependentArray, normalizedIndex + sliceIndex, - this.trackedArraysByGuid[dependentKey]); - observerContexts[sliceIndex] = observerContext; - - forEach(itemPropertyKeys, function (propertyKey) { - addBeforeObserver(item, propertyKey, this, observerContext.beforeObserver); - addObserver(item, propertyKey, this, observerContext.observer); - }, this); - } - - changeMeta = new ChangeMeta(dependentArray, item, normalizedIndex + sliceIndex, this.instanceMeta.propertyName, this.cp, addedCount); - this.setValue(addedItem.call( - this.instanceMeta.context, this.getValue(), item, changeMeta, this.instanceMeta.sugarMeta)); - }, this); - this.callbacks.flushedChanges.call(this.instanceMeta.context, this.getValue(), this.instanceMeta.sugarMeta); - this.trackAdd(dependentKey, normalizedIndex, observerContexts); - }, - - itemPropertyWillChange: function (obj, keyName, array, observerContext) { - var guid = guidFor(obj); - - if (!this.changedItems[guid]) { - this.changedItems[guid] = { - array: array, - observerContext: observerContext, - obj: obj, - previousValues: {} - }; - } - - ++this.changedItemCount; - this.changedItems[guid].previousValues[keyName] = get(obj, keyName); - }, - - itemPropertyDidChange: function (obj, keyName, array, observerContext) { - if (--this.changedItemCount === 0) { - this.flushChanges(); - } - }, - - flushChanges: function () { - var changedItems = this.changedItems; - var key, c, changeMeta; - - for (key in changedItems) { - c = changedItems[key]; - if (c.observerContext.destroyed) { continue; } - - this.updateIndexes(c.observerContext.trackedArray, c.observerContext.dependentArray); - - changeMeta = new ChangeMeta(c.array, c.obj, c.observerContext.index, this.instanceMeta.propertyName, this.cp, changedItems.length, c.previousValues); - this.setValue( - this.callbacks.removedItem.call(this.instanceMeta.context, this.getValue(), c.obj, changeMeta, this.instanceMeta.sugarMeta)); - this.setValue( - this.callbacks.addedItem.call(this.instanceMeta.context, this.getValue(), c.obj, changeMeta, this.instanceMeta.sugarMeta)); - } - - this.changedItems = {}; - this.callbacks.flushedChanges.call(this.instanceMeta.context, this.getValue(), this.instanceMeta.sugarMeta); - } - }; - - function normalizeIndex(index, length, newItemsOffset) { - if (index < 0) { - return Math.max(0, length + index); - } else if (index < length) { - return index; - } else /* index > length */ { - return Math.min(length - newItemsOffset, index); - } - } - - function normalizeRemoveCount(index, length, removedCount) { - return Math.min(removedCount, length - index); - } - - function ChangeMeta(dependentArray, item, index, propertyName, property, changedCount, previousValues){ - this.arrayChanged = dependentArray; - this.index = index; - this.item = item; - this.propertyName = propertyName; - this.property = property; - this.changedCount = changedCount; - - if (previousValues) { - // previous values only available for item property changes - this.previousValues = previousValues; - } - } - - function addItems(dependentArray, callbacks, cp, propertyName, meta) { - forEach(dependentArray, function (item, index) { - meta.setValue( callbacks.addedItem.call( - this, meta.getValue(), item, new ChangeMeta(dependentArray, item, index, propertyName, cp, dependentArray.length), meta.sugarMeta)); - }, this); - callbacks.flushedChanges.call(this, meta.getValue(), meta.sugarMeta); - } - - function reset(cp, propertyName) { - var callbacks = cp._callbacks(); - var hadMeta = cp._hasInstanceMeta(this, propertyName); - var meta = cp._instanceMeta(this, propertyName); - - if (hadMeta) { meta.setValue(cp.resetValue(meta.getValue())); } - - if (cp.options.initialize) { - cp.options.initialize.call(this, meta.getValue(), { - property: cp, - propertyName: propertyName - }, meta.sugarMeta); - } - } - - function partiallyRecomputeFor(obj, dependentKey) { - if (arrayBracketPattern.test(dependentKey)) { - return false; - } - - var value = get(obj, dependentKey); - return EmberArray.detect(value); - } - - function ReduceComputedPropertyInstanceMeta(context, propertyName, initialValue) { - this.context = context; - this.propertyName = propertyName; - this.cache = metaFor(context).cache; - this.dependentArrays = {}; - this.sugarMeta = {}; - this.initialValue = initialValue; - } - - ReduceComputedPropertyInstanceMeta.prototype = { - getValue: function () { - var value = cacheGet(this.cache, this.propertyName); - - if (value !== undefined) { - return value; - } else { - return this.initialValue; - } - }, - - setValue: function(newValue, triggerObservers) { - // This lets sugars force a recomputation, handy for very simple - // implementations of eg max. - if (newValue === cacheGet(this.cache, this.propertyName)) { - return; - } - - if (triggerObservers) { - propertyWillChange(this.context, this.propertyName); - } - - if (newValue === undefined) { - cacheRemove(this.cache, this.propertyName); - } else { - cacheSet(this.cache, this.propertyName, newValue); - } - - if (triggerObservers) { - propertyDidChange(this.context, this.propertyName); - } - } - }; - - /** - A computed property whose dependent keys are arrays and which is updated with - "one at a time" semantics. - - @class ReduceComputedProperty - @namespace Ember - @extends Ember.ComputedProperty - @constructor - */ - - __exports__.ReduceComputedProperty = ReduceComputedProperty; - // TODO: default export - - function ReduceComputedProperty(options) { - var cp = this; - - this.options = options; - this._dependentKeys = null; - // A map of dependentKey -> [itemProperty, ...] that tracks what properties of - // items in the array we must track to update this property. - this._itemPropertyKeys = {}; - this._previousItemPropertyKeys = {}; - - this.readOnly(); - this.cacheable(); - - this.recomputeOnce = function(propertyName) { - // What we really want to do is coalesce by . - // We need a form of `scheduleOnce` that accepts an arbitrary token to - // coalesce by, in addition to the target and method. - run.once(this, recompute, propertyName); - }; - - var recompute = function(propertyName) { - var dependentKeys = cp._dependentKeys; - var meta = cp._instanceMeta(this, propertyName); - var callbacks = cp._callbacks(); - - reset.call(this, cp, propertyName); - - meta.dependentArraysObserver.suspendArrayObservers(function () { - forEach(cp._dependentKeys, function (dependentKey) { - Ember.assert( - 'dependent array ' + dependentKey + ' must be an `Ember.Array`. ' + - 'If you are not extending arrays, you will need to wrap native arrays with `Ember.A`', - !(isArray(get(this, dependentKey)) && !EmberArray.detect(get(this, dependentKey)))); - - if (!partiallyRecomputeFor(this, dependentKey)) { return; } - - var dependentArray = get(this, dependentKey); - var previousDependentArray = meta.dependentArrays[dependentKey]; - - if (dependentArray === previousDependentArray) { - // The array may be the same, but our item property keys may have - // changed, so we set them up again. We can't easily tell if they've - // changed: the array may be the same object, but with different - // contents. - if (cp._previousItemPropertyKeys[dependentKey]) { - delete cp._previousItemPropertyKeys[dependentKey]; - meta.dependentArraysObserver.setupPropertyObservers(dependentKey, cp._itemPropertyKeys[dependentKey]); - } - } else { - meta.dependentArrays[dependentKey] = dependentArray; - - if (previousDependentArray) { - meta.dependentArraysObserver.teardownObservers(previousDependentArray, dependentKey); - } - - if (dependentArray) { - meta.dependentArraysObserver.setupObservers(dependentArray, dependentKey); - } - } - }, this); - }, this); - - forEach(cp._dependentKeys, function(dependentKey) { - if (!partiallyRecomputeFor(this, dependentKey)) { return; } - - var dependentArray = get(this, dependentKey); - - if (dependentArray) { - addItems.call(this, dependentArray, callbacks, cp, propertyName, meta); - } - }, this); - }; - - - this.func = function (propertyName) { - Ember.assert('Computed reduce values require at least one dependent key', cp._dependentKeys); - - recompute.call(this, propertyName); - - return cp._instanceMeta(this, propertyName).getValue(); - }; - } - - ReduceComputedProperty.prototype = o_create(ComputedProperty.prototype); - - function defaultCallback(computedValue) { - return computedValue; - } - - ReduceComputedProperty.prototype._callbacks = function () { - if (!this.callbacks) { - var options = this.options; - - this.callbacks = { - removedItem: options.removedItem || defaultCallback, - addedItem: options.addedItem || defaultCallback, - flushedChanges: options.flushedChanges || defaultCallback - }; - } - - return this.callbacks; - }; - - ReduceComputedProperty.prototype._hasInstanceMeta = function (context, propertyName) { - return !!metaFor(context).cacheMeta[propertyName]; - }; - - ReduceComputedProperty.prototype._instanceMeta = function (context, propertyName) { - var cacheMeta = metaFor(context).cacheMeta; - var meta = cacheMeta[propertyName]; - - if (!meta) { - meta = cacheMeta[propertyName] = new ReduceComputedPropertyInstanceMeta(context, propertyName, this.initialValue()); - meta.dependentArraysObserver = new DependentArraysObserver(this._callbacks(), this, meta, context, propertyName, meta.sugarMeta); - } - - return meta; - }; - - ReduceComputedProperty.prototype.initialValue = function () { - if (typeof this.options.initialValue === 'function') { - return this.options.initialValue(); - } - else { - return this.options.initialValue; - } - }; - - ReduceComputedProperty.prototype.resetValue = function (value) { - return this.initialValue(); - }; - - ReduceComputedProperty.prototype.itemPropertyKey = function (dependentArrayKey, itemPropertyKey) { - this._itemPropertyKeys[dependentArrayKey] = this._itemPropertyKeys[dependentArrayKey] || []; - this._itemPropertyKeys[dependentArrayKey].push(itemPropertyKey); - }; - - ReduceComputedProperty.prototype.clearItemPropertyKeys = function (dependentArrayKey) { - if (this._itemPropertyKeys[dependentArrayKey]) { - this._previousItemPropertyKeys[dependentArrayKey] = this._itemPropertyKeys[dependentArrayKey]; - this._itemPropertyKeys[dependentArrayKey] = []; - } - }; - - ReduceComputedProperty.prototype.property = function () { - var cp = this; - var args = a_slice.call(arguments); - var propertyArgs = {}; - var match, dependentArrayKey, itemPropertyKey; - - forEach(args, function (dependentKey) { - if (doubleEachPropertyPattern.test(dependentKey)) { - throw new EmberError('Nested @each properties not supported: ' + dependentKey); - } else if (match = eachPropertyPattern.exec(dependentKey)) { - dependentArrayKey = match[1]; - - var itemPropertyKeyPattern = match[2]; - var addItemPropertyKey = function (itemPropertyKey) { - cp.itemPropertyKey(dependentArrayKey, itemPropertyKey); - }; - - expandProperties(itemPropertyKeyPattern, addItemPropertyKey); - propertyArgs[guidFor(dependentArrayKey)] = dependentArrayKey; - } else { - propertyArgs[guidFor(dependentKey)] = dependentKey; - } - }); - - var propertyArgsToArray = []; - for (var guid in propertyArgs) { - propertyArgsToArray.push(propertyArgs[guid]); - } - - return ComputedProperty.prototype.property.apply(this, propertyArgsToArray); - }; - - /** - Creates a computed property which operates on dependent arrays and - is updated with "one at a time" semantics. When items are added or - removed from the dependent array(s) a reduce computed only operates - on the change instead of re-evaluating the entire array. - - If there are more than one arguments the first arguments are - considered to be dependent property keys. The last argument is - required to be an options object. The options object can have the - following four properties: - - `initialValue` - A value or function that will be used as the initial - value for the computed. If this property is a function the result of calling - the function will be used as the initial value. This property is required. - - `initialize` - An optional initialize function. Typically this will be used - to set up state on the instanceMeta object. - - `removedItem` - A function that is called each time an element is removed - from the array. - - `addedItem` - A function that is called each time an element is added to - the array. - - - The `initialize` function has the following signature: - - ```javascript - function(initialValue, changeMeta, instanceMeta) - ``` - - `initialValue` - The value of the `initialValue` property from the - options object. - - `changeMeta` - An object which contains meta information about the - computed. It contains the following properties: - - - `property` the computed property - - `propertyName` the name of the property on the object - - `instanceMeta` - An object that can be used to store meta - information needed for calculating your computed. For example a - unique computed might use this to store the number of times a given - element is found in the dependent array. - - - The `removedItem` and `addedItem` functions both have the following signature: - - ```javascript - function(accumulatedValue, item, changeMeta, instanceMeta) - ``` - - `accumulatedValue` - The value returned from the last time - `removedItem` or `addedItem` was called or `initialValue`. - - `item` - the element added or removed from the array - - `changeMeta` - An object which contains meta information about the - change. It contains the following properties: - - - `property` the computed property - - `propertyName` the name of the property on the object - - `index` the index of the added or removed item - - `item` the added or removed item: this is exactly the same as - the second arg - - `arrayChanged` the array that triggered the change. Can be - useful when depending on multiple arrays. - - For property changes triggered on an item property change (when - depKey is something like `someArray.@each.someProperty`), - `changeMeta` will also contain the following property: - - - `previousValues` an object whose keys are the properties that changed on - the item, and whose values are the item's previous values. - - `previousValues` is important Ember coalesces item property changes via - Ember.run.once. This means that by the time removedItem gets called, item has - the new values, but you may need the previous value (eg for sorting & - filtering). - - `instanceMeta` - An object that can be used to store meta - information needed for calculating your computed. For example a - unique computed might use this to store the number of times a given - element is found in the dependent array. - - The `removedItem` and `addedItem` functions should return the accumulated - value. It is acceptable to not return anything (ie return undefined) - to invalidate the computation. This is generally not a good idea for - arrayComputed but it's used in eg max and min. - - Note that observers will be fired if either of these functions return a value - that differs from the accumulated value. When returning an object that - mutates in response to array changes, for example an array that maps - everything from some other array (see `Ember.computed.map`), it is usually - important that the *same* array be returned to avoid accidentally triggering observers. - - Example - - ```javascript - Ember.computed.max = function(dependentKey) { - return Ember.reduceComputed(dependentKey, { - initialValue: -Infinity, - - addedItem: function(accumulatedValue, item, changeMeta, instanceMeta) { - return Math.max(accumulatedValue, item); - }, - - removedItem: function(accumulatedValue, item, changeMeta, instanceMeta) { - if (item < accumulatedValue) { - return accumulatedValue; - } - } - }); - }; - ``` - - Dependent keys may refer to `@this` to observe changes to the object itself, - which must be array-like, rather than a property of the object. This is - mostly useful for array proxies, to ensure objects are retrieved via - `objectAtContent`. This is how you could sort items by properties defined on an item controller. - - Example - - ```javascript - App.PeopleController = Ember.ArrayController.extend({ - itemController: 'person', - - sortedPeople: Ember.computed.sort('@this.@each.reversedName', function(personA, personB) { - // `reversedName` isn't defined on Person, but we have access to it via - // the item controller App.PersonController. If we'd used - // `content.@each.reversedName` above, we would be getting the objects - // directly and not have access to `reversedName`. - // - var reversedNameA = get(personA, 'reversedName'); - var reversedNameB = get(personB, 'reversedName'); - - return Ember.compare(reversedNameA, reversedNameB); - }) - }); - - App.PersonController = Ember.ObjectController.extend({ - reversedName: function() { - return reverse(get(this, 'name')); - }.property('name') - }); - ``` - - Dependent keys whose values are not arrays are treated as regular - dependencies: when they change, the computed property is completely - recalculated. It is sometimes useful to have dependent arrays with similar - semantics. Dependent keys which end in `.[]` do not use "one at a time" - semantics. When an item is added or removed from such a dependency, the - computed property is completely recomputed. - - When the computed property is completely recomputed, the `accumulatedValue` - is discarded, it starts with `initialValue` again, and each item is passed - to `addedItem` in turn. - - Example - - ```javascript - Ember.Object.extend({ - // When `string` is changed, `computed` is completely recomputed. - string: 'a string', - - // When an item is added to `array`, `addedItem` is called. - array: [], - - // When an item is added to `anotherArray`, `computed` is completely - // recomputed. - anotherArray: [], - - computed: Ember.reduceComputed('string', 'array', 'anotherArray.[]', { - addedItem: addedItemCallback, - removedItem: removedItemCallback - }) - }); - ``` - - @method reduceComputed - @for Ember - @param {String} [dependentKeys*] - @param {Object} options - @return {Ember.ComputedProperty} - */ - function reduceComputed(options) { - var args; - - if (arguments.length > 1) { - args = a_slice.call(arguments, 0, -1); - options = a_slice.call(arguments, -1)[0]; - } - - if (typeof options !== 'object') { - throw new EmberError('Reduce Computed Property declared without an options hash'); - } - - if (!('initialValue' in options)) { - throw new EmberError('Reduce Computed Property declared without an initial value'); - } - - var cp = new ReduceComputedProperty(options); - - if (args) { - cp.property.apply(cp, args); - } - - return cp; - } - - __exports__.reduceComputed = reduceComputed; - }); -enifed("ember-runtime/computed/reduce_computed_macros", - ["ember-metal/core","ember-metal/property_get","ember-metal/property_set","ember-metal/utils","ember-metal/error","ember-metal/enumerable_utils","ember-metal/run_loop","ember-metal/observer","ember-runtime/computed/array_computed","ember-runtime/computed/reduce_computed","ember-runtime/system/subarray","ember-metal/keys","ember-runtime/compare","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __dependency11__, __dependency12__, __dependency13__, __exports__) { - "use strict"; - /** - @module ember - @submodule ember-runtime - */ - - var Ember = __dependency1__["default"]; - // Ember.assert - var get = __dependency2__.get; - var set = __dependency3__.set; - var isArray = __dependency4__.isArray; - var guidFor = __dependency4__.guidFor; - var EmberError = __dependency5__["default"]; - var forEach = __dependency6__.forEach; - var run = __dependency7__["default"]; - var addObserver = __dependency8__.addObserver; - var arrayComputed = __dependency9__.arrayComputed; - var reduceComputed = __dependency10__.reduceComputed; - var SubArray = __dependency11__["default"]; - var keys = __dependency12__["default"]; - var compare = __dependency13__["default"]; - - var a_slice = [].slice; - - /** - A computed property that returns the sum of the value - in the dependent array. - - @method computed.sum - @for Ember - @param {String} dependentKey - @return {Ember.ComputedProperty} computes the sum of all values in the dependentKey's array - @since 1.4.0 - */ - - function sum(dependentKey){ - return reduceComputed(dependentKey, { - initialValue: 0, - - addedItem: function(accumulatedValue, item, changeMeta, instanceMeta){ - return accumulatedValue + item; - }, - - removedItem: function(accumulatedValue, item, changeMeta, instanceMeta){ - return accumulatedValue - item; - } - }); - } - - __exports__.sum = sum;/** - A computed property that calculates the maximum value in the - dependent array. This will return `-Infinity` when the dependent - array is empty. - - ```javascript - var Person = Ember.Object.extend({ - childAges: Ember.computed.mapBy('children', 'age'), - maxChildAge: Ember.computed.max('childAges') - }); - - var lordByron = Person.create({ children: [] }); - - lordByron.get('maxChildAge'); // -Infinity - lordByron.get('children').pushObject({ - name: 'Augusta Ada Byron', age: 7 - }); - lordByron.get('maxChildAge'); // 7 - lordByron.get('children').pushObjects([{ - name: 'Allegra Byron', - age: 5 - }, { - name: 'Elizabeth Medora Leigh', - age: 8 - }]); - lordByron.get('maxChildAge'); // 8 - ``` - - @method computed.max - @for Ember - @param {String} dependentKey - @return {Ember.ComputedProperty} computes the largest value in the dependentKey's array - */ - function max(dependentKey) { - return reduceComputed(dependentKey, { - initialValue: -Infinity, - - addedItem: function (accumulatedValue, item, changeMeta, instanceMeta) { - return Math.max(accumulatedValue, item); - }, - - removedItem: function (accumulatedValue, item, changeMeta, instanceMeta) { - if (item < accumulatedValue) { - return accumulatedValue; - } - } - }); - } - - __exports__.max = max;/** - A computed property that calculates the minimum value in the - dependent array. This will return `Infinity` when the dependent - array is empty. - - ```javascript - var Person = Ember.Object.extend({ - childAges: Ember.computed.mapBy('children', 'age'), - minChildAge: Ember.computed.min('childAges') - }); - - var lordByron = Person.create({ children: [] }); - - lordByron.get('minChildAge'); // Infinity - lordByron.get('children').pushObject({ - name: 'Augusta Ada Byron', age: 7 - }); - lordByron.get('minChildAge'); // 7 - lordByron.get('children').pushObjects([{ - name: 'Allegra Byron', - age: 5 - }, { - name: 'Elizabeth Medora Leigh', - age: 8 - }]); - lordByron.get('minChildAge'); // 5 - ``` - - @method computed.min - @for Ember - @param {String} dependentKey - @return {Ember.ComputedProperty} computes the smallest value in the dependentKey's array - */ - function min(dependentKey) { - return reduceComputed(dependentKey, { - initialValue: Infinity, - - addedItem: function (accumulatedValue, item, changeMeta, instanceMeta) { - return Math.min(accumulatedValue, item); - }, - - removedItem: function (accumulatedValue, item, changeMeta, instanceMeta) { - if (item > accumulatedValue) { - return accumulatedValue; - } - } - }); - } - - __exports__.min = min;/** - Returns an array mapped via the callback - - The callback method you provide should have the following signature. - `item` is the current item in the iteration. - `index` is the integer index of the current item in the iteration. - - ```javascript - function(item, index); - ``` - - Example - - ```javascript - var Hamster = Ember.Object.extend({ - excitingChores: Ember.computed.map('chores', function(chore, index) { - return chore.toUpperCase() + '!'; - }) - }); - - var hamster = Hamster.create({ - chores: ['clean', 'write more unit tests'] - }); - - hamster.get('excitingChores'); // ['CLEAN!', 'WRITE MORE UNIT TESTS!'] - ``` - - @method computed.map - @for Ember - @param {String} dependentKey - @param {Function} callback - @return {Ember.ComputedProperty} an array mapped via the callback - */ - function map(dependentKey, callback) { - var options = { - addedItem: function(array, item, changeMeta, instanceMeta) { - var mapped = callback.call(this, item, changeMeta.index); - array.insertAt(changeMeta.index, mapped); - return array; - }, - removedItem: function(array, item, changeMeta, instanceMeta) { - array.removeAt(changeMeta.index, 1); - return array; - } - }; - - return arrayComputed(dependentKey, options); - } - - __exports__.map = map;/** - Returns an array mapped to the specified key. - - ```javascript - var Person = Ember.Object.extend({ - childAges: Ember.computed.mapBy('children', 'age') - }); - - var lordByron = Person.create({ children: [] }); - - lordByron.get('childAges'); // [] - lordByron.get('children').pushObject({ name: 'Augusta Ada Byron', age: 7 }); - lordByron.get('childAges'); // [7] - lordByron.get('children').pushObjects([{ - name: 'Allegra Byron', - age: 5 - }, { - name: 'Elizabeth Medora Leigh', - age: 8 - }]); - lordByron.get('childAges'); // [7, 5, 8] - ``` - - @method computed.mapBy - @for Ember - @param {String} dependentKey - @param {String} propertyKey - @return {Ember.ComputedProperty} an array mapped to the specified key - */ - function mapBy (dependentKey, propertyKey) { - var callback = function(item) { return get(item, propertyKey); }; - return map(dependentKey + '.@each.' + propertyKey, callback); - } - - __exports__.mapBy = mapBy;/** - @method computed.mapProperty - @for Ember - @deprecated Use `Ember.computed.mapBy` instead - @param dependentKey - @param propertyKey - */ - var mapProperty = mapBy; - __exports__.mapProperty = mapProperty; - /** - Filters the array by the callback. - - The callback method you provide should have the following signature. - `item` is the current item in the iteration. - `index` is the integer index of the current item in the iteration. - - ```javascript - function(item, index); - ``` - - ```javascript - var Hamster = Ember.Object.extend({ - remainingChores: Ember.computed.filter('chores', function(chore, index) { - return !chore.done; - }) - }); - - var hamster = Hamster.create({ - chores: [ - { name: 'cook', done: true }, - { name: 'clean', done: true }, - { name: 'write more unit tests', done: false } - ] - }); - - hamster.get('remainingChores'); // [{name: 'write more unit tests', done: false}] - ``` - - @method computed.filter - @for Ember - @param {String} dependentKey - @param {Function} callback - @return {Ember.ComputedProperty} the filtered array - */ - function filter(dependentKey, callback) { - var options = { - initialize: function (array, changeMeta, instanceMeta) { - instanceMeta.filteredArrayIndexes = new SubArray(); - }, - - addedItem: function (array, item, changeMeta, instanceMeta) { - var match = !!callback.call(this, item, changeMeta.index); - var filterIndex = instanceMeta.filteredArrayIndexes.addItem(changeMeta.index, match); - - if (match) { - array.insertAt(filterIndex, item); - } - - return array; - }, - - removedItem: function(array, item, changeMeta, instanceMeta) { - var filterIndex = instanceMeta.filteredArrayIndexes.removeItem(changeMeta.index); - - if (filterIndex > -1) { - array.removeAt(filterIndex); - } - - return array; - } - }; - - return arrayComputed(dependentKey, options); - } - - __exports__.filter = filter;/** - Filters the array by the property and value - - ```javascript - var Hamster = Ember.Object.extend({ - remainingChores: Ember.computed.filterBy('chores', 'done', false) - }); - - var hamster = Hamster.create({ - chores: [ - { name: 'cook', done: true }, - { name: 'clean', done: true }, - { name: 'write more unit tests', done: false } - ] - }); - - hamster.get('remainingChores'); // [{ name: 'write more unit tests', done: false }] - ``` - - @method computed.filterBy - @for Ember - @param {String} dependentKey - @param {String} propertyKey - @param {*} value - @return {Ember.ComputedProperty} the filtered array - */ - function filterBy (dependentKey, propertyKey, value) { - var callback; - - if (arguments.length === 2) { - callback = function(item) { - return get(item, propertyKey); - }; - } else { - callback = function(item) { - return get(item, propertyKey) === value; - }; - } - - return filter(dependentKey + '.@each.' + propertyKey, callback); - } - - __exports__.filterBy = filterBy;/** - @method computed.filterProperty - @for Ember - @param dependentKey - @param propertyKey - @param value - @deprecated Use `Ember.computed.filterBy` instead - */ - var filterProperty = filterBy; - __exports__.filterProperty = filterProperty; - /** - A computed property which returns a new array with all the unique - elements from one or more dependent arrays. - - Example - - ```javascript - var Hamster = Ember.Object.extend({ - uniqueFruits: Ember.computed.uniq('fruits') - }); - - var hamster = Hamster.create({ - fruits: [ - 'banana', - 'grape', - 'kale', - 'banana' - ] - }); - - hamster.get('uniqueFruits'); // ['banana', 'grape', 'kale'] - ``` - - @method computed.uniq - @for Ember - @param {String} propertyKey* - @return {Ember.ComputedProperty} computes a new array with all the - unique elements from the dependent array - */ - function uniq() { - var args = a_slice.call(arguments); - - args.push({ - initialize: function(array, changeMeta, instanceMeta) { - instanceMeta.itemCounts = {}; - }, - - addedItem: function(array, item, changeMeta, instanceMeta) { - var guid = guidFor(item); - - if (!instanceMeta.itemCounts[guid]) { - instanceMeta.itemCounts[guid] = 1; - array.pushObject(item); - } else { - ++instanceMeta.itemCounts[guid]; - } - return array; - }, - - removedItem: function(array, item, _, instanceMeta) { - var guid = guidFor(item); - var itemCounts = instanceMeta.itemCounts; - - if (--itemCounts[guid] === 0) { - array.removeObject(item); - } - - return array; - } - }); - - return arrayComputed.apply(null, args); - } - - __exports__.uniq = uniq;/** - Alias for [Ember.computed.uniq](/api/#method_computed_uniq). - - @method computed.union - @for Ember - @param {String} propertyKey* - @return {Ember.ComputedProperty} computes a new array with all the - unique elements from the dependent array - */ - var union = uniq; - __exports__.union = union; - /** - A computed property which returns a new array with all the duplicated - elements from two or more dependent arrays. - - Example - - ```javascript - var obj = Ember.Object.createWithMixins({ - adaFriends: ['Charles Babbage', 'John Hobhouse', 'William King', 'Mary Somerville'], - charlesFriends: ['William King', 'Mary Somerville', 'Ada Lovelace', 'George Peacock'], - friendsInCommon: Ember.computed.intersect('adaFriends', 'charlesFriends') - }); - - obj.get('friendsInCommon'); // ['William King', 'Mary Somerville'] - ``` - - @method computed.intersect - @for Ember - @param {String} propertyKey* - @return {Ember.ComputedProperty} computes a new array with all the - duplicated elements from the dependent arrays - */ - function intersect() { - var args = a_slice.call(arguments); - - args.push({ - initialize: function (array, changeMeta, instanceMeta) { - instanceMeta.itemCounts = {}; - }, - - addedItem: function(array, item, changeMeta, instanceMeta) { - var itemGuid = guidFor(item); - var dependentGuid = guidFor(changeMeta.arrayChanged); - var numberOfDependentArrays = changeMeta.property._dependentKeys.length; - var itemCounts = instanceMeta.itemCounts; - - if (!itemCounts[itemGuid]) { - itemCounts[itemGuid] = {}; - } - - if (itemCounts[itemGuid][dependentGuid] === undefined) { - itemCounts[itemGuid][dependentGuid] = 0; - } - - if (++itemCounts[itemGuid][dependentGuid] === 1 && - numberOfDependentArrays === keys(itemCounts[itemGuid]).length) { - array.addObject(item); - } - - return array; - }, - - removedItem: function(array, item, changeMeta, instanceMeta) { - var itemGuid = guidFor(item); - var dependentGuid = guidFor(changeMeta.arrayChanged); - var numberOfDependentArrays = changeMeta.property._dependentKeys.length; - var numberOfArraysItemAppearsIn; - var itemCounts = instanceMeta.itemCounts; - - if (itemCounts[itemGuid][dependentGuid] === undefined) { - itemCounts[itemGuid][dependentGuid] = 0; - } - - if (--itemCounts[itemGuid][dependentGuid] === 0) { - delete itemCounts[itemGuid][dependentGuid]; - numberOfArraysItemAppearsIn = keys(itemCounts[itemGuid]).length; - - if (numberOfArraysItemAppearsIn === 0) { - delete itemCounts[itemGuid]; - } - - array.removeObject(item); - } - - return array; - } - }); - - return arrayComputed.apply(null, args); - } - - __exports__.intersect = intersect;/** - A computed property which returns a new array with all the - properties from the first dependent array that are not in the second - dependent array. - - Example - - ```javascript - var Hamster = Ember.Object.extend({ - likes: ['banana', 'grape', 'kale'], - wants: Ember.computed.setDiff('likes', 'fruits') - }); - - var hamster = Hamster.create({ - fruits: [ - 'grape', - 'kale', - ] - }); - - hamster.get('wants'); // ['banana'] - ``` - - @method computed.setDiff - @for Ember - @param {String} setAProperty - @param {String} setBProperty - @return {Ember.ComputedProperty} computes a new array with all the - items from the first dependent array that are not in the second - dependent array - */ - function setDiff(setAProperty, setBProperty) { - if (arguments.length !== 2) { - throw new EmberError('setDiff requires exactly two dependent arrays.'); - } - - return arrayComputed(setAProperty, setBProperty, { - addedItem: function (array, item, changeMeta, instanceMeta) { - var setA = get(this, setAProperty); - var setB = get(this, setBProperty); - - if (changeMeta.arrayChanged === setA) { - if (!setB.contains(item)) { - array.addObject(item); - } - } else { - array.removeObject(item); - } - - return array; - }, - - removedItem: function (array, item, changeMeta, instanceMeta) { - var setA = get(this, setAProperty); - var setB = get(this, setBProperty); - - if (changeMeta.arrayChanged === setB) { - if (setA.contains(item)) { - array.addObject(item); - } - } else { - array.removeObject(item); - } - - return array; - } - }); - } - - __exports__.setDiff = setDiff;function binarySearch(array, item, low, high) { - var mid, midItem, res, guidMid, guidItem; - - if (arguments.length < 4) { - high = get(array, 'length'); - } - - if (arguments.length < 3) { - low = 0; - } - - if (low === high) { - return low; - } - - mid = low + Math.floor((high - low) / 2); - midItem = array.objectAt(mid); - - guidMid = guidFor(midItem); - guidItem = guidFor(item); - - if (guidMid === guidItem) { - return mid; - } - - res = this.order(midItem, item); - - if (res === 0) { - res = guidMid < guidItem ? -1 : 1; - } - - - if (res < 0) { - return this.binarySearch(array, item, mid+1, high); - } else if (res > 0) { - return this.binarySearch(array, item, low, mid); - } - - return mid; - } - - - /** - A computed property which returns a new array with all the - properties from the first dependent array sorted based on a property - or sort function. - - The callback method you provide should have the following signature: - - ```javascript - function(itemA, itemB); - ``` - - - `itemA` the first item to compare. - - `itemB` the second item to compare. - - This function should return negative number (e.g. `-1`) when `itemA` should come before - `itemB`. It should return positive number (e.g. `1`) when `itemA` should come after - `itemB`. If the `itemA` and `itemB` are equal this function should return `0`. - - Therefore, if this function is comparing some numeric values, simple `itemA - itemB` or - `itemA.get( 'foo' ) - itemB.get( 'foo' )` can be used instead of series of `if`. - - Example - - ```javascript - var ToDoList = Ember.Object.extend({ - // using standard ascending sort - todosSorting: ['name'], - sortedTodos: Ember.computed.sort('todos', 'todosSorting'), - - // using descending sort - todosSortingDesc: ['name:desc'], - sortedTodosDesc: Ember.computed.sort('todos', 'todosSortingDesc'), - - // using a custom sort function - priorityTodos: Ember.computed.sort('todos', function(a, b){ - if (a.priority > b.priority) { - return 1; - } else if (a.priority < b.priority) { - return -1; - } - - return 0; - }) - }); - - var todoList = ToDoList.create({todos: [ - { name: 'Unit Test', priority: 2 }, - { name: 'Documentation', priority: 3 }, - { name: 'Release', priority: 1 } - ]}); - - todoList.get('sortedTodos'); // [{ name:'Documentation', priority:3 }, { name:'Release', priority:1 }, { name:'Unit Test', priority:2 }] - todoList.get('sortedTodosDesc'); // [{ name:'Unit Test', priority:2 }, { name:'Release', priority:1 }, { name:'Documentation', priority:3 }] - todoList.get('priorityTodos'); // [{ name:'Release', priority:1 }, { name:'Unit Test', priority:2 }, { name:'Documentation', priority:3 }] - ``` - - @method computed.sort - @for Ember - @param {String} dependentKey - @param {String or Function} sortDefinition a dependent key to an - array of sort properties (add `:desc` to the arrays sort properties to sort descending) or a function to use when sorting - @return {Ember.ComputedProperty} computes a new sorted array based - on the sort property array or callback function - */ - function sort(itemsKey, sortDefinition) { - Ember.assert('Ember.computed.sort requires two arguments: an array key to sort and ' + - 'either a sort properties key or sort function', arguments.length === 2); - - if (typeof sortDefinition === 'function') { - return customSort(itemsKey, sortDefinition); - } else { - return propertySort(itemsKey, sortDefinition); - } - } - - __exports__.sort = sort;function customSort(itemsKey, comparator) { - return arrayComputed(itemsKey, { - initialize: function (array, changeMeta, instanceMeta) { - instanceMeta.order = comparator; - instanceMeta.binarySearch = binarySearch; - instanceMeta.waitingInsertions = []; - instanceMeta.insertWaiting = function() { - var index, item; - var waiting = instanceMeta.waitingInsertions; - instanceMeta.waitingInsertions = []; - for (var i=0; i{{post.title}} ({{post.titleLength}} characters) - {{/each}} - ``` - - ```javascript - App.PostsController = Ember.ArrayController.extend({ - itemController: 'post' - }); - - App.PostController = Ember.ObjectController.extend({ - // the `title` property will be proxied to the underlying post. - titleLength: function() { - return this.get('title').length; - }.property('title') - }); - ``` - - In some cases it is helpful to return a different `itemController` depending - on the particular item. Subclasses can do this by overriding - `lookupItemController`. - - For example: - - ```javascript - App.MyArrayController = Ember.ArrayController.extend({ - lookupItemController: function( object ) { - if (object.get('isSpecial')) { - return "special"; // use App.SpecialController - } else { - return "regular"; // use App.RegularController - } - } - }); - ``` - - The itemController instances will have a `parentController` property set to - the `ArrayController` instance. - - @class ArrayController - @namespace Ember - @extends Ember.ArrayProxy - @uses Ember.SortableMixin - @uses Ember.ControllerMixin - */ - - __exports__["default"] = ArrayProxy.extend(ControllerMixin, SortableMixin, { - - /** - The controller used to wrap items, if any. If the value is a string, it will - be used to lookup the container for the controller. As an alternative, you - can also provide a controller class as the value. - - For example: - - ```javascript - App.MyArrayController = Ember.ArrayController.extend({ - itemController: Ember.ObjectController.extend({ - //Item Controller Implementation - }) - }); - ``` - - @property itemController - @type String | Ember.Controller - @default null - */ - itemController: null, - - /** - Return the name of the controller to wrap items, or `null` if items should - be returned directly. The default implementation simply returns the - `itemController` property, but subclasses can override this method to return - different controllers for different objects. - - For example: - - ```javascript - App.MyArrayController = Ember.ArrayController.extend({ - lookupItemController: function( object ) { - if (object.get('isSpecial')) { - return "special"; // use App.SpecialController - } else { - return "regular"; // use App.RegularController - } - } - }); - ``` - - @method lookupItemController - @param {Object} object - @return {String} - */ - lookupItemController: function(object) { - return get(this, 'itemController'); - }, - - objectAtContent: function(idx) { - var length = get(this, 'length'); - var arrangedContent = get(this, 'arrangedContent'); - var object = arrangedContent && arrangedContent.objectAt(idx); - var controllerClass; - - if (idx >= 0 && idx < length) { - controllerClass = this.lookupItemController(object); - - if (controllerClass) { - return this.controllerAt(idx, object, controllerClass); - } - } - - // When `controllerClass` is falsy, we have not opted in to using item - // controllers, so return the object directly. - - // When the index is out of range, we want to return the "out of range" - // value, whatever that might be. Rather than make assumptions - // (e.g. guessing `null` or `undefined`) we defer this to `arrangedContent`. - return object; - }, - - arrangedContentDidChange: function() { - this._super(); - this._resetSubControllers(); - }, - - arrayContentDidChange: function(idx, removedCnt, addedCnt) { - var subControllers = this._subControllers; - - if (subControllers.length) { - var subControllersToRemove = subControllers.slice(idx, idx + removedCnt); - - forEach(subControllersToRemove, function(subController) { - if (subController) { - subController.destroy(); - } - }); - - replace(subControllers, idx, removedCnt, new Array(addedCnt)); - } - - // The shadow array of subcontrollers must be updated before we trigger - // observers, otherwise observers will get the wrong subcontainer when - // calling `objectAt` - this._super(idx, removedCnt, addedCnt); - }, - - init: function() { - this._super(); - this._subControllers = []; - }, - - model: computed(function () { - return Ember.A(); - }), - - /** - * Flag to mark as being "virtual". Used to keep this instance - * from participating in the parentController hierarchy. - * - * @private - * @property _isVirtual - * @type Boolean - */ - _isVirtual: false, - - controllerAt: function(idx, object, controllerClass) { - var container = get(this, 'container'); - var subControllers = this._subControllers; - var fullName, subController, subControllerFactory, parentController, options; - - if (subControllers.length > idx) { - subController = subControllers[idx]; - - if (subController) { - return subController; - } - } - - if (this._isVirtual) { - parentController = get(this, 'parentController'); - } else { - parentController = this; - } - - - fullName = 'controller:' + controllerClass; - - if (!container.has(fullName)) { - throw new EmberError('Could not resolve itemController: "' + controllerClass + '"'); - } - - subController = container.lookupFactory(fullName).create({ - target: parentController, - parentController: parentController, - model: object - }); - - - subControllers[idx] = subController; - - return subController; - }, - - _subControllers: null, - - _resetSubControllers: function() { - var controller; - var subControllers = this._subControllers; - - if (subControllers.length) { - for (var i = 0, length = subControllers.length; length > i; i++) { - controller = subControllers[i]; - - if (controller) { - controller.destroy(); - } - } - - subControllers.length = 0; - } - }, - - willDestroy: function() { - this._resetSubControllers(); - this._super(); - } - }); - }); -enifed("ember-runtime/controllers/controller", - ["ember-runtime/system/object","ember-runtime/mixins/controller","exports"], - function(__dependency1__, __dependency2__, __exports__) { - "use strict"; - var EmberObject = __dependency1__["default"]; - var Mixin = __dependency2__["default"]; - - /** - @module ember - @submodule ember-runtime - */ - - /** - @class Controller - @namespace Ember - @extends Ember.Object - @uses Ember.ControllerMixin - */ - __exports__["default"] = EmberObject.extend(Mixin); - }); -enifed("ember-runtime/controllers/object_controller", - ["ember-runtime/mixins/controller","ember-runtime/system/object_proxy","exports"], - function(__dependency1__, __dependency2__, __exports__) { - "use strict"; - var ControllerMixin = __dependency1__["default"]; - var ObjectProxy = __dependency2__["default"]; - - /** - @module ember - @submodule ember-runtime - */ - - /** - `Ember.ObjectController` is part of Ember's Controller layer. It is intended - to wrap a single object, proxying unhandled attempts to `get` and `set` to the underlying - model object, and to forward unhandled action attempts to its `target`. - - `Ember.ObjectController` derives this functionality from its superclass - `Ember.ObjectProxy` and the `Ember.ControllerMixin` mixin. - - @class ObjectController - @namespace Ember - @extends Ember.ObjectProxy - @uses Ember.ControllerMixin - **/ - __exports__["default"] = ObjectProxy.extend(ControllerMixin); - }); -enifed("ember-runtime/copy", - ["ember-metal/enumerable_utils","ember-metal/utils","ember-runtime/system/object","ember-runtime/mixins/copyable","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __exports__) { - "use strict"; - var indexOf = __dependency1__.indexOf; - var typeOf = __dependency2__.typeOf; - var EmberObject = __dependency3__["default"]; - var Copyable = __dependency4__["default"]; - - function _copy(obj, deep, seen, copies) { - var ret, loc, key; - - // primitive data types are immutable, just return them. - if (typeof obj !== 'object' || obj === null) { - return obj; - } - - // avoid cyclical loops - if (deep && (loc = indexOf(seen, obj)) >= 0) { - return copies[loc]; - } - - Ember.assert('Cannot clone an Ember.Object that does not implement Ember.Copyable', - !(obj instanceof EmberObject) || (Copyable && Copyable.detect(obj))); - - // IMPORTANT: this specific test will detect a native array only. Any other - // object will need to implement Copyable. - if (typeOf(obj) === 'array') { - ret = obj.slice(); - - if (deep) { - loc = ret.length; - - while (--loc >= 0) { - ret[loc] = _copy(ret[loc], deep, seen, copies); - } - } - } else if (Copyable && Copyable.detect(obj)) { - ret = obj.copy(deep, seen, copies); - } else if (obj instanceof Date) { - ret = new Date(obj.getTime()); - } else { - ret = {}; - - for (key in obj) { - // support Null prototype - if (!Object.prototype.hasOwnProperty.call(obj, key)) { - continue; - } - - // Prevents browsers that don't respect non-enumerability from - // copying internal Ember properties - if (key.substring(0, 2) === '__') { - continue; - } - - ret[key] = deep ? _copy(obj[key], deep, seen, copies) : obj[key]; - } - } - - if (deep) { - seen.push(obj); - copies.push(ret); - } - - return ret; - } - - /** - Creates a clone of the passed object. This function can take just about - any type of object and create a clone of it, including primitive values - (which are not actually cloned because they are immutable). - - If the passed object implements the `clone()` method, then this function - will simply call that method and return the result. - - @method copy - @for Ember - @param {Object} obj The object to clone - @param {Boolean} deep If true, a deep copy of the object is made - @return {Object} The cloned object - */ - __exports__["default"] = function copy(obj, deep) { - // fast paths - if ('object' !== typeof obj || obj === null) { - return obj; // can't copy primitives - } - - if (Copyable && Copyable.detect(obj)) { - return obj.copy(deep); - } - - return _copy(obj, deep, deep ? [] : null, deep ? [] : null); - } - }); -enifed("ember-runtime/core", - ["exports"], - function(__exports__) { - "use strict"; - /** - @module ember - @submodule ember-runtime - */ - - /** - Compares two objects, returning true if they are logically equal. This is - a deeper comparison than a simple triple equal. For sets it will compare the - internal objects. For any other object that implements `isEqual()` it will - respect that method. - - ```javascript - Ember.isEqual('hello', 'hello'); // true - Ember.isEqual(1, 2); // false - Ember.isEqual([4, 2], [4, 2]); // false - ``` - - @method isEqual - @for Ember - @param {Object} a first object to compare - @param {Object} b second object to compare - @return {Boolean} - */ - var isEqual = function isEqual(a, b) { - if (a && typeof a.isEqual === 'function') { - return a.isEqual(b); - } - - if (a instanceof Date && b instanceof Date) { - return a.getTime() === b.getTime(); - } - - return a === b; - }; - __exports__.isEqual = isEqual; - }); -enifed("ember-runtime/ext/function", - ["ember-metal/core","ember-metal/expand_properties","ember-metal/computed","ember-metal/mixin"], - function(__dependency1__, __dependency2__, __dependency3__, __dependency4__) { - "use strict"; - /** - @module ember - @submodule ember-runtime - */ - - var Ember = __dependency1__["default"]; - // Ember.EXTEND_PROTOTYPES, Ember.assert - var expandProperties = __dependency2__["default"]; - var computed = __dependency3__.computed; - var observer = __dependency4__.observer; - - var a_slice = Array.prototype.slice; - var FunctionPrototype = Function.prototype; - - if (Ember.EXTEND_PROTOTYPES === true || Ember.EXTEND_PROTOTYPES.Function) { - - /** - The `property` extension of Javascript's Function prototype is available - when `Ember.EXTEND_PROTOTYPES` or `Ember.EXTEND_PROTOTYPES.Function` is - `true`, which is the default. - - Computed properties allow you to treat a function like a property: - - ```javascript - MyApp.President = Ember.Object.extend({ - firstName: '', - lastName: '', - - fullName: function() { - return this.get('firstName') + ' ' + this.get('lastName'); - }.property() // Call this flag to mark the function as a property - }); - - var president = MyApp.President.create({ - firstName: 'Barack', - lastName: 'Obama' - }); - - president.get('fullName'); // 'Barack Obama' - ``` - - Treating a function like a property is useful because they can work with - bindings, just like any other property. - - Many computed properties have dependencies on other properties. For - example, in the above example, the `fullName` property depends on - `firstName` and `lastName` to determine its value. You can tell Ember - about these dependencies like this: - - ```javascript - MyApp.President = Ember.Object.extend({ - firstName: '', - lastName: '', - - fullName: function() { - return this.get('firstName') + ' ' + this.get('lastName'); - - // Tell Ember.js that this computed property depends on firstName - // and lastName - }.property('firstName', 'lastName') - }); - ``` - - Make sure you list these dependencies so Ember knows when to update - bindings that connect to a computed property. Changing a dependency - will not immediately trigger an update of the computed property, but - will instead clear the cache so that it is updated when the next `get` - is called on the property. - - See [Ember.ComputedProperty](/api/classes/Ember.ComputedProperty.html), [Ember.computed](/api/#method_computed). - - @method property - @for Function - */ - FunctionPrototype.property = function () { - var ret = computed(this); - // ComputedProperty.prototype.property expands properties; no need for us to - // do so here. - return ret.property.apply(ret, arguments); - }; - - /** - The `observes` extension of Javascript's Function prototype is available - when `Ember.EXTEND_PROTOTYPES` or `Ember.EXTEND_PROTOTYPES.Function` is - true, which is the default. - - You can observe property changes simply by adding the `observes` - call to the end of your method declarations in classes that you write. - For example: - - ```javascript - Ember.Object.extend({ - valueObserver: function() { - // Executes whenever the "value" property changes - }.observes('value') - }); - ``` - - In the future this method may become asynchronous. If you want to ensure - synchronous behavior, use `observesImmediately`. - - See `Ember.observer`. - - @method observes - @for Function - */ - FunctionPrototype.observes = function() { - var length = arguments.length; - var args = new Array(length); - for (var x = 0; x < length; x++) { - args[x] = arguments[x]; - } - return observer.apply(this, args.concat(this)); - }; - - /** - The `observesImmediately` extension of Javascript's Function prototype is - available when `Ember.EXTEND_PROTOTYPES` or - `Ember.EXTEND_PROTOTYPES.Function` is true, which is the default. - - You can observe property changes simply by adding the `observesImmediately` - call to the end of your method declarations in classes that you write. - For example: - - ```javascript - Ember.Object.extend({ - valueObserver: function() { - // Executes immediately after the "value" property changes - }.observesImmediately('value') - }); - ``` - - In the future, `observes` may become asynchronous. In this event, - `observesImmediately` will maintain the synchronous behavior. - - See `Ember.immediateObserver`. - - @method observesImmediately - @for Function - */ - FunctionPrototype.observesImmediately = function () { - for (var i = 0, l = arguments.length; i < l; i++) { - var arg = arguments[i]; - Ember.assert('Immediate observers must observe internal properties only, ' + - 'not properties on other objects.', arg.indexOf('.') === -1); - } - - // observes handles property expansion - return this.observes.apply(this, arguments); - }; - - /** - The `observesBefore` extension of Javascript's Function prototype is - available when `Ember.EXTEND_PROTOTYPES` or - `Ember.EXTEND_PROTOTYPES.Function` is true, which is the default. - - You can get notified when a property change is about to happen by - by adding the `observesBefore` call to the end of your method - declarations in classes that you write. For example: - - ```javascript - Ember.Object.extend({ - valueObserver: function() { - // Executes whenever the "value" property is about to change - }.observesBefore('value') - }); - ``` - - See `Ember.beforeObserver`. - - @method observesBefore - @for Function - */ - FunctionPrototype.observesBefore = function () { - var watched = []; - var addWatchedProperty = function (obs) { - watched.push(obs); - }; - - for (var i = 0, l = arguments.length; i < l; ++i) { - expandProperties(arguments[i], addWatchedProperty); - } - - this.__ember_observesBefore__ = watched; - - return this; - }; - - /** - The `on` extension of Javascript's Function prototype is available - when `Ember.EXTEND_PROTOTYPES` or `Ember.EXTEND_PROTOTYPES.Function` is - true, which is the default. - - You can listen for events simply by adding the `on` call to the end of - your method declarations in classes or mixins that you write. For example: - - ```javascript - Ember.Mixin.create({ - doSomethingWithElement: function() { - // Executes whenever the "didInsertElement" event fires - }.on('didInsertElement') - }); - ``` - - See `Ember.on`. - - @method on - @for Function - */ - FunctionPrototype.on = function () { - var events = a_slice.call(arguments); - this.__ember_listens__ = events; - - return this; - }; - } - }); -enifed("ember-runtime/ext/rsvp", - ["ember-metal/core","ember-metal/logger","ember-metal/run_loop","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __exports__) { - "use strict"; - /* globals RSVP:true */ - - var Ember = __dependency1__["default"]; - var Logger = __dependency2__["default"]; - var run = __dependency3__["default"]; - - var RSVP = requireModule('rsvp'); - var testModuleName = 'ember-testing/test'; - var Test; - - var asyncStart = function() { - if (Ember.Test && Ember.Test.adapter) { - Ember.Test.adapter.asyncStart(); - } - }; - - var asyncEnd = function() { - if (Ember.Test && Ember.Test.adapter) { - Ember.Test.adapter.asyncEnd(); - } - }; - - RSVP.configure('async', function(callback, promise) { - var async = !run.currentRunLoop; - - if (Ember.testing && async) { asyncStart(); } - - run.backburner.schedule('actions', function(){ - if (Ember.testing && async) { asyncEnd(); } - callback(promise); - }); - }); - - RSVP.Promise.prototype.fail = function(callback, label){ - Ember.deprecate('RSVP.Promise.fail has been renamed as RSVP.Promise.catch'); - return this['catch'](callback, label); - }; - - RSVP.onerrorDefault = function (error) { - if (error instanceof Error) { - if (Ember.testing) { - // ES6TODO: remove when possible - if (!Test && Ember.__loader.registry[testModuleName]) { - Test = requireModule(testModuleName)['default']; - } - - if (Test && Test.adapter) { - Test.adapter.exception(error); - } else { - throw error; - } - } else if (Ember.onerror) { - Ember.onerror(error); - } else { - Logger.error(error.stack); - Ember.assert(error, false); - } - } - }; - - RSVP.on('error', RSVP.onerrorDefault); - - __exports__["default"] = RSVP; - }); -enifed("ember-runtime/ext/string", - ["ember-metal/core","ember-runtime/system/string"], - function(__dependency1__, __dependency2__) { - "use strict"; - /** - @module ember - @submodule ember-runtime - */ - - var Ember = __dependency1__["default"]; - // Ember.EXTEND_PROTOTYPES, Ember.assert, Ember.FEATURES - var fmt = __dependency2__.fmt; - var w = __dependency2__.w; - var loc = __dependency2__.loc; - var camelize = __dependency2__.camelize; - var decamelize = __dependency2__.decamelize; - var dasherize = __dependency2__.dasherize; - var underscore = __dependency2__.underscore; - var capitalize = __dependency2__.capitalize; - var classify = __dependency2__.classify; - - var StringPrototype = String.prototype; - - if (Ember.EXTEND_PROTOTYPES === true || Ember.EXTEND_PROTOTYPES.String) { - - /** - See [Ember.String.fmt](/api/classes/Ember.String.html#method_fmt). - - @method fmt - @for String - */ - StringPrototype.fmt = function () { - return fmt(this, arguments); - }; - - /** - See [Ember.String.w](/api/classes/Ember.String.html#method_w). - - @method w - @for String - */ - StringPrototype.w = function () { - return w(this); - }; - - /** - See [Ember.String.loc](/api/classes/Ember.String.html#method_loc). - - @method loc - @for String - */ - StringPrototype.loc = function () { - return loc(this, arguments); - }; - - /** - See [Ember.String.camelize](/api/classes/Ember.String.html#method_camelize). - - @method camelize - @for String - */ - StringPrototype.camelize = function () { - return camelize(this); - }; - - /** - See [Ember.String.decamelize](/api/classes/Ember.String.html#method_decamelize). - - @method decamelize - @for String - */ - StringPrototype.decamelize = function () { - return decamelize(this); - }; - - /** - See [Ember.String.dasherize](/api/classes/Ember.String.html#method_dasherize). - - @method dasherize - @for String - */ - StringPrototype.dasherize = function () { - return dasherize(this); - }; - - /** - See [Ember.String.underscore](/api/classes/Ember.String.html#method_underscore). - - @method underscore - @for String - */ - StringPrototype.underscore = function () { - return underscore(this); - }; - - /** - See [Ember.String.classify](/api/classes/Ember.String.html#method_classify). - - @method classify - @for String - */ - StringPrototype.classify = function () { - return classify(this); - }; - - /** - See [Ember.String.capitalize](/api/classes/Ember.String.html#method_capitalize). - - @method capitalize - @for String - */ - StringPrototype.capitalize = function () { - return capitalize(this); - }; - } - }); -enifed("ember-runtime/mixins/-proxy", - ["ember-metal/core","ember-metal/property_get","ember-metal/property_set","ember-metal/utils","ember-metal/observer","ember-metal/property_events","ember-metal/computed","ember-metal/properties","ember-metal/mixin","ember-runtime/system/string","ember-runtime/system/object","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __dependency11__, __exports__) { - "use strict"; - /** - @module ember - @submodule ember-runtime - */ - - var Ember = __dependency1__["default"]; - // Ember.assert - var get = __dependency2__.get; - var set = __dependency3__.set; - var meta = __dependency4__.meta; - var addObserver = __dependency5__.addObserver; - var removeObserver = __dependency5__.removeObserver; - var addBeforeObserver = __dependency5__.addBeforeObserver; - var removeBeforeObserver = __dependency5__.removeBeforeObserver; - var propertyWillChange = __dependency6__.propertyWillChange; - var propertyDidChange = __dependency6__.propertyDidChange; - var computed = __dependency7__.computed; - var defineProperty = __dependency8__.defineProperty; - var Mixin = __dependency9__.Mixin; - var observer = __dependency9__.observer; - var fmt = __dependency10__.fmt; - var EmberObject = __dependency11__["default"]; - - function contentPropertyWillChange(content, contentKey) { - var key = contentKey.slice(8); // remove "content." - if (key in this) { return; } // if shadowed in proxy - propertyWillChange(this, key); - } - - function contentPropertyDidChange(content, contentKey) { - var key = contentKey.slice(8); // remove "content." - if (key in this) { return; } // if shadowed in proxy - propertyDidChange(this, key); - } - - /** - `Ember.ProxyMixin` forwards all properties not defined by the proxy itself - to a proxied `content` object. See Ember.ObjectProxy for more details. - - @class ProxyMixin - @namespace Ember - */ - __exports__["default"] = Mixin.create({ - /** - The object whose properties will be forwarded. - - @property content - @type Ember.Object - @default null - */ - content: null, - _contentDidChange: observer('content', function() { - Ember.assert("Can't set Proxy's content to itself", get(this, 'content') !== this); - }), - - isTruthy: computed.bool('content'), - - _debugContainerKey: null, - - willWatchProperty: function (key) { - var contentKey = 'content.' + key; - addBeforeObserver(this, contentKey, null, contentPropertyWillChange); - addObserver(this, contentKey, null, contentPropertyDidChange); - }, - - didUnwatchProperty: function (key) { - var contentKey = 'content.' + key; - removeBeforeObserver(this, contentKey, null, contentPropertyWillChange); - removeObserver(this, contentKey, null, contentPropertyDidChange); - }, - - unknownProperty: function (key) { - var content = get(this, 'content'); - if (content) { - return get(content, key); - } - }, - - setUnknownProperty: function (key, value) { - var m = meta(this); - if (m.proto === this) { - // if marked as prototype then just defineProperty - // rather than delegate - defineProperty(this, key, null, value); - return value; - } - - var content = get(this, 'content'); - Ember.assert(fmt("Cannot delegate set('%@', %@) to the 'content' property of object proxy %@: its 'content' is undefined.", [key, value, this]), content); - return set(content, key, value); - } - - }); - }); -enifed("ember-runtime/mixins/action_handler", - ["ember-metal/merge","ember-metal/mixin","ember-metal/property_get","ember-metal/utils","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __exports__) { - "use strict"; - /** - @module ember - @submodule ember-runtime - */ - var merge = __dependency1__["default"]; - var Mixin = __dependency2__.Mixin; - var get = __dependency3__.get; - var typeOf = __dependency4__.typeOf; - - /** - The `Ember.ActionHandler` mixin implements support for moving an `actions` - property to an `_actions` property at extend time, and adding `_actions` - to the object's mergedProperties list. - - `Ember.ActionHandler` is available on some familiar classes including - `Ember.Route`, `Ember.View`, `Ember.Component`, and controllers such as - `Ember.Controller` and `Ember.ObjectController`. - (Internally the mixin is used by `Ember.CoreView`, `Ember.ControllerMixin`, - and `Ember.Route` and available to the above classes through - inheritance.) - - @class ActionHandler - @namespace Ember - */ - var ActionHandler = Mixin.create({ - mergedProperties: ['_actions'], - - /** - The collection of functions, keyed by name, available on this - `ActionHandler` as action targets. - - These functions will be invoked when a matching `{{action}}` is triggered - from within a template and the application's current route is this route. - - Actions can also be invoked from other parts of your application - via `ActionHandler#send`. - - The `actions` hash will inherit action handlers from - the `actions` hash defined on extended parent classes - or mixins rather than just replace the entire hash, e.g.: - - ```js - App.CanDisplayBanner = Ember.Mixin.create({ - actions: { - displayBanner: function(msg) { - // ... - } - } - }); - - App.WelcomeRoute = Ember.Route.extend(App.CanDisplayBanner, { - actions: { - playMusic: function() { - // ... - } - } - }); - - // `WelcomeRoute`, when active, will be able to respond - // to both actions, since the actions hash is merged rather - // then replaced when extending mixins / parent classes. - this.send('displayBanner'); - this.send('playMusic'); - ``` - - Within a Controller, Route, View or Component's action handler, - the value of the `this` context is the Controller, Route, View or - Component object: - - ```js - App.SongRoute = Ember.Route.extend({ - actions: { - myAction: function() { - this.controllerFor("song"); - this.transitionTo("other.route"); - ... - } - } - }); - ``` - - It is also possible to call `this._super()` from within an - action handler if it overrides a handler defined on a parent - class or mixin: - - Take for example the following routes: - - ```js - App.DebugRoute = Ember.Mixin.create({ - actions: { - debugRouteInformation: function() { - console.debug("trololo"); - } - } - }); - - App.AnnoyingDebugRoute = Ember.Route.extend(App.DebugRoute, { - actions: { - debugRouteInformation: function() { - // also call the debugRouteInformation of mixed in App.DebugRoute - this._super(); - - // show additional annoyance - window.alert(...); - } - } - }); - ``` - - ## Bubbling - - By default, an action will stop bubbling once a handler defined - on the `actions` hash handles it. To continue bubbling the action, - you must return `true` from the handler: - - ```js - App.Router.map(function() { - this.resource("album", function() { - this.route("song"); - }); - }); - - App.AlbumRoute = Ember.Route.extend({ - actions: { - startPlaying: function() { - } - } - }); - - App.AlbumSongRoute = Ember.Route.extend({ - actions: { - startPlaying: function() { - // ... - - if (actionShouldAlsoBeTriggeredOnParentRoute) { - return true; - } - } - } - }); - ``` - - @property actions - @type Hash - @default null - */ - - /** - Moves `actions` to `_actions` at extend time. Note that this currently - modifies the mixin themselves, which is technically dubious but - is practically of little consequence. This may change in the future. - - @private - @method willMergeMixin - */ - willMergeMixin: function(props) { - var hashName; - - if (!props._actions) { - Ember.assert("'actions' should not be a function", typeof(props.actions) !== 'function'); - - if (typeOf(props.actions) === 'object') { - hashName = 'actions'; - } else if (typeOf(props.events) === 'object') { - Ember.deprecate('Action handlers contained in an `events` object are deprecated in favor of putting them in an `actions` object', false); - hashName = 'events'; - } - - if (hashName) { - props._actions = merge(props._actions || {}, props[hashName]); - } - - delete props[hashName]; - } - }, - - /** - Triggers a named action on the `ActionHandler`. Any parameters - supplied after the `actionName` string will be passed as arguments - to the action target function. - - If the `ActionHandler` has its `target` property set, actions may - bubble to the `target`. Bubbling happens when an `actionName` can - not be found in the `ActionHandler`'s `actions` hash or if the - action target function returns `true`. - - Example - - ```js - App.WelcomeRoute = Ember.Route.extend({ - actions: { - playTheme: function() { - this.send('playMusic', 'theme.mp3'); - }, - playMusic: function(track) { - // ... - } - } - }); - ``` - - @method send - @param {String} actionName The action to trigger - @param {*} context a context to send with the action - */ - send: function(actionName) { - var args = [].slice.call(arguments, 1); - var target; - - if (this._actions && this._actions[actionName]) { - if (this._actions[actionName].apply(this, args) === true) { - // handler returned true, so this action will bubble - } else { - return; - } - } - - if (target = get(this, 'target')) { - Ember.assert("The `target` for " + this + " (" + target + ") does not have a `send` method", typeof target.send === 'function'); - target.send.apply(target, arguments); - } - } - }); - - __exports__["default"] = ActionHandler; - }); -enifed("ember-runtime/mixins/array", - ["ember-metal/core","ember-metal/property_get","ember-metal/computed","ember-metal/is_none","ember-runtime/mixins/enumerable","ember-metal/enumerable_utils","ember-metal/mixin","ember-metal/property_events","ember-metal/events","ember-metal/watching","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __exports__) { - "use strict"; - /** - @module ember - @submodule ember-runtime - */ - - // .......................................................... - // HELPERS - // - var Ember = __dependency1__["default"]; - // ES6TODO: Ember.A - var get = __dependency2__.get; - var computed = __dependency3__.computed; - var cacheFor = __dependency3__.cacheFor; - var isNone = __dependency4__.isNone; - var none = __dependency4__.none; - var Enumerable = __dependency5__["default"]; - var map = __dependency6__.map; - var Mixin = __dependency7__.Mixin; - var required = __dependency7__.required; - var propertyWillChange = __dependency8__.propertyWillChange; - var propertyDidChange = __dependency8__.propertyDidChange; - var addListener = __dependency9__.addListener; - var removeListener = __dependency9__.removeListener; - var sendEvent = __dependency9__.sendEvent; - var hasListeners = __dependency9__.hasListeners; - var isWatching = __dependency10__.isWatching; - - function arrayObserversHelper(obj, target, opts, operation, notify) { - var willChange = (opts && opts.willChange) || 'arrayWillChange'; - var didChange = (opts && opts.didChange) || 'arrayDidChange'; - var hasObservers = get(obj, 'hasArrayObservers'); - - if (hasObservers === notify) { - propertyWillChange(obj, 'hasArrayObservers'); - } - - operation(obj, '@array:before', target, willChange); - operation(obj, '@array:change', target, didChange); - - if (hasObservers === notify) { - propertyDidChange(obj, 'hasArrayObservers'); - } - - return obj; - } - - // .......................................................... - // ARRAY - // - /** - This mixin implements Observer-friendly Array-like behavior. It is not a - concrete implementation, but it can be used up by other classes that want - to appear like arrays. - - For example, ArrayProxy and ArrayController are both concrete classes that can - be instantiated to implement array-like behavior. Both of these classes use - the Array Mixin by way of the MutableArray mixin, which allows observable - changes to be made to the underlying array. - - Unlike `Ember.Enumerable,` this mixin defines methods specifically for - collections that provide index-ordered access to their contents. When you - are designing code that needs to accept any kind of Array-like object, you - should use these methods instead of Array primitives because these will - properly notify observers of changes to the array. - - Although these methods are efficient, they do add a layer of indirection to - your application so it is a good idea to use them only when you need the - flexibility of using both true JavaScript arrays and "virtual" arrays such - as controllers and collections. - - You can use the methods defined in this module to access and modify array - contents in a KVO-friendly way. You can also be notified whenever the - membership of an array changes by using `.observes('myArray.[]')`. - - To support `Ember.Array` in your own class, you must override two - primitives to use it: `replace()` and `objectAt()`. - - Note that the Ember.Array mixin also incorporates the `Ember.Enumerable` - mixin. All `Ember.Array`-like objects are also enumerable. - - @class Array - @namespace Ember - @uses Ember.Enumerable - @since Ember 0.9.0 - */ - __exports__["default"] = Mixin.create(Enumerable, { - - /** - Your array must support the `length` property. Your replace methods should - set this property whenever it changes. - - @property {Number} length - */ - length: required(), - - /** - Returns the object at the given `index`. If the given `index` is negative - or is greater or equal than the array length, returns `undefined`. - - This is one of the primitives you must implement to support `Ember.Array`. - If your object supports retrieving the value of an array item using `get()` - (i.e. `myArray.get(0)`), then you do not need to implement this method - yourself. - - ```javascript - var arr = ['a', 'b', 'c', 'd']; - - arr.objectAt(0); // 'a' - arr.objectAt(3); // 'd' - arr.objectAt(-1); // undefined - arr.objectAt(4); // undefined - arr.objectAt(5); // undefined - ``` - - @method objectAt - @param {Number} idx The index of the item to return. - @return {*} item at index or undefined - */ - objectAt: function(idx) { - if (idx < 0 || idx >= get(this, 'length')) { - return undefined; - } - - return get(this, idx); - }, - - /** - This returns the objects at the specified indexes, using `objectAt`. - - ```javascript - var arr = ['a', 'b', 'c', 'd']; - - arr.objectsAt([0, 1, 2]); // ['a', 'b', 'c'] - arr.objectsAt([2, 3, 4]); // ['c', 'd', undefined] - ``` - - @method objectsAt - @param {Array} indexes An array of indexes of items to return. - @return {Array} - */ - objectsAt: function(indexes) { - var self = this; - - return map(indexes, function(idx) { - return self.objectAt(idx); - }); - }, - - // overrides Ember.Enumerable version - nextObject: function(idx) { - return this.objectAt(idx); - }, - - /** - This is the handler for the special array content property. If you get - this property, it will return this. If you set this property to a new - array, it will replace the current content. - - This property overrides the default property defined in `Ember.Enumerable`. - - @property [] - @return this - */ - '[]': computed(function(key, value) { - if (value !== undefined) { - this.replace(0, get(this, 'length'), value); - } - - return this; - }), - - firstObject: computed(function() { - return this.objectAt(0); - }), - - lastObject: computed(function() { - return this.objectAt(get(this, 'length') - 1); - }), - - // optimized version from Enumerable - contains: function(obj) { - return this.indexOf(obj) >= 0; - }, - - // Add any extra methods to Ember.Array that are native to the built-in Array. - /** - Returns a new array that is a slice of the receiver. This implementation - uses the observable array methods to retrieve the objects for the new - slice. - - ```javascript - var arr = ['red', 'green', 'blue']; - - arr.slice(0); // ['red', 'green', 'blue'] - arr.slice(0, 2); // ['red', 'green'] - arr.slice(1, 100); // ['green', 'blue'] - ``` - - @method slice - @param {Integer} beginIndex (Optional) index to begin slicing from. - @param {Integer} endIndex (Optional) index to end the slice at (but not included). - @return {Array} New array with specified slice - */ - slice: function(beginIndex, endIndex) { - var ret = Ember.A(); - var length = get(this, 'length'); - - if (isNone(beginIndex)) { - beginIndex = 0; - } - - if (isNone(endIndex) || (endIndex > length)) { - endIndex = length; - } - - if (beginIndex < 0) { - beginIndex = length + beginIndex; - } - - if (endIndex < 0) { - endIndex = length + endIndex; - } - - while (beginIndex < endIndex) { - ret[ret.length] = this.objectAt(beginIndex++); - } - - return ret; - }, - - /** - Returns the index of the given object's first occurrence. - If no `startAt` argument is given, the starting location to - search is 0. If it's negative, will count backward from - the end of the array. Returns -1 if no match is found. - - ```javascript - var arr = ['a', 'b', 'c', 'd', 'a']; - - arr.indexOf('a'); // 0 - arr.indexOf('z'); // -1 - arr.indexOf('a', 2); // 4 - arr.indexOf('a', -1); // 4 - arr.indexOf('b', 3); // -1 - arr.indexOf('a', 100); // -1 - ``` - - @method indexOf - @param {Object} object the item to search for - @param {Number} startAt optional starting location to search, default 0 - @return {Number} index or -1 if not found - */ - indexOf: function(object, startAt) { - var len = get(this, 'length'); - var idx; - - if (startAt === undefined) { - startAt = 0; - } - - if (startAt < 0) { - startAt += len; - } - - for (idx = startAt; idx < len; idx++) { - if (this.objectAt(idx) === object) { - return idx; - } - } - - return -1; - }, - - /** - Returns the index of the given object's last occurrence. - If no `startAt` argument is given, the search starts from - the last position. If it's negative, will count backward - from the end of the array. Returns -1 if no match is found. - - ```javascript - var arr = ['a', 'b', 'c', 'd', 'a']; - - arr.lastIndexOf('a'); // 4 - arr.lastIndexOf('z'); // -1 - arr.lastIndexOf('a', 2); // 0 - arr.lastIndexOf('a', -1); // 4 - arr.lastIndexOf('b', 3); // 1 - arr.lastIndexOf('a', 100); // 4 - ``` - - @method lastIndexOf - @param {Object} object the item to search for - @param {Number} startAt optional starting location to search, default 0 - @return {Number} index or -1 if not found - */ - lastIndexOf: function(object, startAt) { - var len = get(this, 'length'); - var idx; - - if (startAt === undefined || startAt >= len) { - startAt = len-1; - } - - if (startAt < 0) { - startAt += len; - } - - for (idx = startAt; idx >= 0; idx--) { - if (this.objectAt(idx) === object) { - return idx; - } - } - - return -1; - }, - - // .......................................................... - // ARRAY OBSERVERS - // - - /** - Adds an array observer to the receiving array. The array observer object - normally must implement two methods: - - * `arrayWillChange(observedObj, start, removeCount, addCount)` - This method will be - called just before the array is modified. - * `arrayDidChange(observedObj, start, removeCount, addCount)` - This method will be - called just after the array is modified. - - Both callbacks will be passed the observed object, starting index of the - change as well a a count of the items to be removed and added. You can use - these callbacks to optionally inspect the array during the change, clear - caches, or do any other bookkeeping necessary. - - In addition to passing a target, you can also include an options hash - which you can use to override the method names that will be invoked on the - target. - - @method addArrayObserver - @param {Object} target The observer object. - @param {Hash} opts Optional hash of configuration options including - `willChange` and `didChange` option. - @return {Ember.Array} receiver - */ - - addArrayObserver: function(target, opts) { - return arrayObserversHelper(this, target, opts, addListener, false); - }, - - /** - Removes an array observer from the object if the observer is current - registered. Calling this method multiple times with the same object will - have no effect. - - @method removeArrayObserver - @param {Object} target The object observing the array. - @param {Hash} opts Optional hash of configuration options including - `willChange` and `didChange` option. - @return {Ember.Array} receiver - */ - removeArrayObserver: function(target, opts) { - return arrayObserversHelper(this, target, opts, removeListener, true); - }, - - /** - Becomes true whenever the array currently has observers watching changes - on the array. - - @property {Boolean} hasArrayObservers - */ - hasArrayObservers: computed(function() { - return hasListeners(this, '@array:change') || hasListeners(this, '@array:before'); - }), - - /** - If you are implementing an object that supports `Ember.Array`, call this - method just before the array content changes to notify any observers and - invalidate any related properties. Pass the starting index of the change - as well as a delta of the amounts to change. - - @method arrayContentWillChange - @param {Number} startIdx The starting index in the array that will change. - @param {Number} removeAmt The number of items that will be removed. If you - pass `null` assumes 0 - @param {Number} addAmt The number of items that will be added. If you - pass `null` assumes 0. - @return {Ember.Array} receiver - */ - arrayContentWillChange: function(startIdx, removeAmt, addAmt) { - var removing, lim; - - // if no args are passed assume everything changes - if (startIdx === undefined) { - startIdx = 0; - removeAmt = addAmt = -1; - } else { - if (removeAmt === undefined) { - removeAmt = -1; - } - - if (addAmt === undefined) { - addAmt = -1; - } - } - - // Make sure the @each proxy is set up if anyone is observing @each - if (isWatching(this, '@each')) { - get(this, '@each'); - } - - sendEvent(this, '@array:before', [this, startIdx, removeAmt, addAmt]); - - if (startIdx >= 0 && removeAmt >= 0 && get(this, 'hasEnumerableObservers')) { - removing = []; - lim = startIdx + removeAmt; - - for (var idx = startIdx; idx < lim; idx++) { - removing.push(this.objectAt(idx)); - } - } else { - removing = removeAmt; - } - - this.enumerableContentWillChange(removing, addAmt); - - return this; - }, - - /** - If you are implementing an object that supports `Ember.Array`, call this - method just after the array content changes to notify any observers and - invalidate any related properties. Pass the starting index of the change - as well as a delta of the amounts to change. - - @method arrayContentDidChange - @param {Number} startIdx The starting index in the array that did change. - @param {Number} removeAmt The number of items that were removed. If you - pass `null` assumes 0 - @param {Number} addAmt The number of items that were added. If you - pass `null` assumes 0. - @return {Ember.Array} receiver - */ - arrayContentDidChange: function(startIdx, removeAmt, addAmt) { - var adding, lim; - - // if no args are passed assume everything changes - if (startIdx === undefined) { - startIdx = 0; - removeAmt = addAmt = -1; - } else { - if (removeAmt === undefined) { - removeAmt = -1; - } - - if (addAmt === undefined) { - addAmt = -1; - } - } - - if (startIdx >= 0 && addAmt >= 0 && get(this, 'hasEnumerableObservers')) { - adding = []; - lim = startIdx + addAmt; - - for (var idx = startIdx; idx < lim; idx++) { - adding.push(this.objectAt(idx)); - } - } else { - adding = addAmt; - } - - this.enumerableContentDidChange(removeAmt, adding); - sendEvent(this, '@array:change', [this, startIdx, removeAmt, addAmt]); - - var length = get(this, 'length'); - var cachedFirst = cacheFor(this, 'firstObject'); - var cachedLast = cacheFor(this, 'lastObject'); - - if (this.objectAt(0) !== cachedFirst) { - propertyWillChange(this, 'firstObject'); - propertyDidChange(this, 'firstObject'); - } - - if (this.objectAt(length-1) !== cachedLast) { - propertyWillChange(this, 'lastObject'); - propertyDidChange(this, 'lastObject'); - } - - return this; - }, - - // .......................................................... - // ENUMERATED PROPERTIES - // - - /** - Returns a special object that can be used to observe individual properties - on the array. Just get an equivalent property on this object and it will - return an enumerable that maps automatically to the named key on the - member objects. - - If you merely want to watch for any items being added or removed to the array, - use the `[]` property instead of `@each`. - - @property @each - */ - '@each': computed(function() { - if (!this.__each) { - // ES6TODO: GRRRRR - var EachProxy = requireModule('ember-runtime/system/each_proxy')['EachProxy']; - - this.__each = new EachProxy(this); - } - - return this.__each; - }) - }); - }); -enifed("ember-runtime/mixins/comparable", - ["ember-metal/mixin","exports"], - function(__dependency1__, __exports__) { - "use strict"; - var Mixin = __dependency1__.Mixin; - var required = __dependency1__.required; - - /** - @module ember - @submodule ember-runtime - */ - - /** - Implements some standard methods for comparing objects. Add this mixin to - any class you create that can compare its instances. - - You should implement the `compare()` method. - - @class Comparable - @namespace Ember - @since Ember 0.9 - */ - __exports__["default"] = Mixin.create({ - - /** - Override to return the result of the comparison of the two parameters. The - compare method should return: - - - `-1` if `a < b` - - `0` if `a == b` - - `1` if `a > b` - - Default implementation raises an exception. - - @method compare - @param a {Object} the first object to compare - @param b {Object} the second object to compare - @return {Integer} the result of the comparison - */ - compare: required(Function) - }); - }); -enifed("ember-runtime/mixins/controller", - ["ember-metal/core","ember-metal/property_get","ember-runtime/system/object","ember-metal/mixin","ember-metal/computed","ember-runtime/mixins/action_handler","ember-runtime/mixins/controller_content_model_alias_deprecation","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __exports__) { - "use strict"; - var Ember = __dependency1__["default"]; - // Ember.assert, Ember.deprecate - var get = __dependency2__.get; - var EmberObject = __dependency3__["default"]; - var Mixin = __dependency4__.Mixin; - var computed = __dependency5__.computed; - var ActionHandler = __dependency6__["default"]; - var ControllerContentModelAliasDeprecation = __dependency7__["default"]; - - /** - `Ember.ControllerMixin` provides a standard interface for all classes that - compose Ember's controller layer: `Ember.Controller`, - `Ember.ArrayController`, and `Ember.ObjectController`. - - @class ControllerMixin - @namespace Ember - @uses Ember.ActionHandler - */ - __exports__["default"] = Mixin.create(ActionHandler, ControllerContentModelAliasDeprecation, { - /* ducktype as a controller */ - isController: true, - - /** - The object to which actions from the view should be sent. - - For example, when a Handlebars template uses the `{{action}}` helper, - it will attempt to send the action to the view's controller's `target`. - - By default, the value of the target property is set to the router, and - is injected when a controller is instantiated. This injection is defined - in Ember.Application#buildContainer, and is applied as part of the - applications initialization process. It can also be set after a controller - has been instantiated, for instance when using the render helper in a - template, or when a controller is used as an `itemController`. In most - cases the `target` property will automatically be set to the logical - consumer of actions for the controller. - - @property target - @default null - */ - target: null, - - container: null, - - parentController: null, - - store: null, - - /** - The controller's current model. When retrieving or modifying a controller's - model, this property should be used instead of the `content` property. - - @property model - @public - */ - model: null, - - /** - @private - */ - content: computed.alias('model') - - }); - }); -enifed("ember-runtime/mixins/controller_content_model_alias_deprecation", - ["ember-metal/core","ember-metal/property_get","ember-metal/mixin","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __exports__) { - "use strict"; - var Ember = __dependency1__["default"]; - // Ember.deprecate - var get = __dependency2__.get; - var Mixin = __dependency3__.Mixin; - - /** - The ControllerContentModelAliasDeprecation mixin is used to provide a useful - deprecation warning when specifying `content` directly on a `Ember.Controller` - (without also specifying `model`). - - Ember versions prior to 1.7 used `model` as an alias of `content`, but due to - much confusion this alias was reversed (so `content` is now an alias of `model). - - This change reduces many caveats with model/content, and also sets a - simple ground rule: Never set a controllers content, rather always set - it's model and ember will do the right thing. - - - `Ember.ControllerContentModelAliasDeprecation` is used internally by Ember in - `Ember.Controller`. - - @class ControllerContentModelAliasDeprecation - @namespace Ember - @private - @since 1.7.0 - */ - __exports__["default"] = Mixin.create({ - /** - @private - - Moves `content` to `model` at extend time if a `model` is not also specified. - - Note that this currently modifies the mixin themselves, which is technically - dubious but is practically of little consequence. This may change in the - future. - - @method willMergeMixin - @since 1.4.0 - */ - willMergeMixin: function(props) { - // Calling super is only OK here since we KNOW that - // there is another Mixin loaded first. - this._super.apply(this, arguments); - - var modelSpecified = !!props.model; - - if (props.content && !modelSpecified) { - props.model = props.content; - delete props['content']; - - Ember.deprecate('Do not specify `content` on a Controller, use `model` instead.', false); - } - } - }); - }); -enifed("ember-runtime/mixins/copyable", - ["ember-metal/property_get","ember-metal/property_set","ember-metal/mixin","ember-runtime/mixins/freezable","ember-runtime/system/string","ember-metal/error","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __exports__) { - "use strict"; - /** - @module ember - @submodule ember-runtime - */ - - - var get = __dependency1__.get; - var set = __dependency2__.set; - var required = __dependency3__.required; - var Freezable = __dependency4__.Freezable; - var Mixin = __dependency3__.Mixin; - var fmt = __dependency5__.fmt; - var EmberError = __dependency6__["default"]; - - - /** - Implements some standard methods for copying an object. Add this mixin to - any object you create that can create a copy of itself. This mixin is - added automatically to the built-in array. - - You should generally implement the `copy()` method to return a copy of the - receiver. - - Note that `frozenCopy()` will only work if you also implement - `Ember.Freezable`. - - @class Copyable - @namespace Ember - @since Ember 0.9 - */ - __exports__["default"] = Mixin.create({ - /** - Override to return a copy of the receiver. Default implementation raises - an exception. - - @method copy - @param {Boolean} deep if `true`, a deep copy of the object should be made - @return {Object} copy of receiver - */ - copy: required(Function), - - /** - If the object implements `Ember.Freezable`, then this will return a new - copy if the object is not frozen and the receiver if the object is frozen. - - Raises an exception if you try to call this method on a object that does - not support freezing. - - You should use this method whenever you want a copy of a freezable object - since a freezable object can simply return itself without actually - consuming more memory. - - @method frozenCopy - @return {Object} copy of receiver or receiver - */ - frozenCopy: function() { - if (Freezable && Freezable.detect(this)) { - return get(this, 'isFrozen') ? this : this.copy().freeze(); - } else { - throw new EmberError(fmt("%@ does not support freezing", [this])); - } - } - }); - }); -enifed("ember-runtime/mixins/deferred", - ["ember-metal/core","ember-metal/property_get","ember-metal/mixin","ember-metal/computed","ember-runtime/ext/rsvp","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __exports__) { - "use strict"; - var Ember = __dependency1__["default"]; - // Ember.FEATURES, Ember.Test - var get = __dependency2__.get; - var Mixin = __dependency3__.Mixin; - var computed = __dependency4__.computed; - var RSVP = __dependency5__["default"]; - - /** - @module ember - @submodule ember-runtime - */ - - - /** - @class Deferred - @namespace Ember - */ - __exports__["default"] = Mixin.create({ - /** - Add handlers to be called when the Deferred object is resolved or rejected. - - @method then - @param {Function} resolve a callback function to be called when done - @param {Function} reject a callback function to be called when failed - */ - then: function(resolve, reject, label) { - var deferred, promise, entity; - - entity = this; - deferred = get(this, '_deferred'); - promise = deferred.promise; - - function fulfillmentHandler(fulfillment) { - if (fulfillment === promise) { - return resolve(entity); - } else { - return resolve(fulfillment); - } - } - - return promise.then(resolve && fulfillmentHandler, reject, label); - }, - - /** - Resolve a Deferred object and call any `doneCallbacks` with the given args. - - @method resolve - */ - resolve: function(value) { - var deferred, promise; - - deferred = get(this, '_deferred'); - promise = deferred.promise; - - if (value === this) { - deferred.resolve(promise); - } else { - deferred.resolve(value); - } - }, - - /** - Reject a Deferred object and call any `failCallbacks` with the given args. - - @method reject - */ - reject: function(value) { - get(this, '_deferred').reject(value); - }, - - _deferred: computed(function() { - Ember.deprecate('Usage of Ember.DeferredMixin or Ember.Deferred is deprecated.', this._suppressDeferredDeprecation); - - return RSVP.defer('Ember: DeferredMixin - ' + this); - }) - }); - }); -enifed("ember-runtime/mixins/enumerable", - ["ember-metal/core","ember-metal/property_get","ember-metal/property_set","ember-metal/utils","ember-metal/mixin","ember-metal/enumerable_utils","ember-metal/computed","ember-metal/property_events","ember-metal/events","ember-runtime/compare","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __exports__) { - "use strict"; - /** - @module ember - @submodule ember-runtime - */ - - // .......................................................... - // HELPERS - // - - var Ember = __dependency1__["default"]; - var get = __dependency2__.get; - var set = __dependency3__.set; - var apply = __dependency4__.apply; - var Mixin = __dependency5__.Mixin; - var required = __dependency5__.required; - var aliasMethod = __dependency5__.aliasMethod; - var indexOf = __dependency6__.indexOf; - var computed = __dependency7__.computed; - var propertyWillChange = __dependency8__.propertyWillChange; - var propertyDidChange = __dependency8__.propertyDidChange; - var addListener = __dependency9__.addListener; - var removeListener = __dependency9__.removeListener; - var sendEvent = __dependency9__.sendEvent; - var hasListeners = __dependency9__.hasListeners; - var compare = __dependency10__["default"]; - - var a_slice = Array.prototype.slice; - - var contexts = []; - - function popCtx() { - return contexts.length===0 ? {} : contexts.pop(); - } - - function pushCtx(ctx) { - contexts.push(ctx); - return null; - } - - function iter(key, value) { - var valueProvided = arguments.length === 2; - - function i(item) { - var cur = get(item, key); - return valueProvided ? value===cur : !!cur; - } - - return i; - } - - /** - This mixin defines the common interface implemented by enumerable objects - in Ember. Most of these methods follow the standard Array iteration - API defined up to JavaScript 1.8 (excluding language-specific features that - cannot be emulated in older versions of JavaScript). - - This mixin is applied automatically to the Array class on page load, so you - can use any of these methods on simple arrays. If Array already implements - one of these methods, the mixin will not override them. - - ## Writing Your Own Enumerable - - To make your own custom class enumerable, you need two items: - - 1. You must have a length property. This property should change whenever - the number of items in your enumerable object changes. If you use this - with an `Ember.Object` subclass, you should be sure to change the length - property using `set().` - - 2. You must implement `nextObject().` See documentation. - - Once you have these two methods implemented, apply the `Ember.Enumerable` mixin - to your class and you will be able to enumerate the contents of your object - like any other collection. - - ## Using Ember Enumeration with Other Libraries - - Many other libraries provide some kind of iterator or enumeration like - facility. This is often where the most common API conflicts occur. - Ember's API is designed to be as friendly as possible with other - libraries by implementing only methods that mostly correspond to the - JavaScript 1.8 API. - - @class Enumerable - @namespace Ember - @since Ember 0.9 - */ - __exports__["default"] = Mixin.create({ - - /** - Implement this method to make your class enumerable. - - This method will be call repeatedly during enumeration. The index value - will always begin with 0 and increment monotonically. You don't have to - rely on the index value to determine what object to return, but you should - always check the value and start from the beginning when you see the - requested index is 0. - - The `previousObject` is the object that was returned from the last call - to `nextObject` for the current iteration. This is a useful way to - manage iteration if you are tracing a linked list, for example. - - Finally the context parameter will always contain a hash you can use as - a "scratchpad" to maintain any other state you need in order to iterate - properly. The context object is reused and is not reset between - iterations so make sure you setup the context with a fresh state whenever - the index parameter is 0. - - Generally iterators will continue to call `nextObject` until the index - reaches the your current length-1. If you run out of data before this - time for some reason, you should simply return undefined. - - The default implementation of this method simply looks up the index. - This works great on any Array-like objects. - - @method nextObject - @param {Number} index the current index of the iteration - @param {Object} previousObject the value returned by the last call to - `nextObject`. - @param {Object} context a context object you can use to maintain state. - @return {Object} the next object in the iteration or undefined - */ - nextObject: required(Function), - - /** - Helper method returns the first object from a collection. This is usually - used by bindings and other parts of the framework to extract a single - object if the enumerable contains only one item. - - If you override this method, you should implement it so that it will - always return the same value each time it is called. If your enumerable - contains only one object, this method should always return that object. - If your enumerable is empty, this method should return `undefined`. - - ```javascript - var arr = ["a", "b", "c"]; - arr.get('firstObject'); // "a" - - var arr = []; - arr.get('firstObject'); // undefined - ``` - - @property firstObject - @return {Object} the object or undefined - */ - firstObject: computed('[]', function() { - if (get(this, 'length')===0) return undefined ; - - // handle generic enumerables - var context = popCtx(), ret; - ret = this.nextObject(0, null, context); - pushCtx(context); - return ret; - }), - - /** - Helper method returns the last object from a collection. If your enumerable - contains only one object, this method should always return that object. - If your enumerable is empty, this method should return `undefined`. - - ```javascript - var arr = ["a", "b", "c"]; - arr.get('lastObject'); // "c" - - var arr = []; - arr.get('lastObject'); // undefined - ``` - - @property lastObject - @return {Object} the last object or undefined - */ - lastObject: computed('[]', function() { - var len = get(this, 'length'); - if (len===0) return undefined ; - var context = popCtx(), idx=0, cur, last = null; - do { - last = cur; - cur = this.nextObject(idx++, last, context); - } while (cur !== undefined); - pushCtx(context); - return last; - }), - - /** - Returns `true` if the passed object can be found in the receiver. The - default version will iterate through the enumerable until the object - is found. You may want to override this with a more efficient version. - - ```javascript - var arr = ["a", "b", "c"]; - arr.contains("a"); // true - arr.contains("z"); // false - ``` - - @method contains - @param {Object} obj The object to search for. - @return {Boolean} `true` if object is found in enumerable. - */ - contains: function(obj) { - return this.find(function(item) { return item===obj; }) !== undefined; - }, - - /** - Iterates through the enumerable, calling the passed function on each - item. This method corresponds to the `forEach()` method defined in - JavaScript 1.6. - - The callback method you provide should have the following signature (all - parameters are optional): - - ```javascript - function(item, index, enumerable); - ``` - - - `item` is the current item in the iteration. - - `index` is the current index in the iteration. - - `enumerable` is the enumerable object itself. - - Note that in addition to a callback, you can also pass an optional target - object that will be set as `this` on the context. This is a good way - to give your iterator function access to the current object. - - @method forEach - @param {Function} callback The callback to execute - @param {Object} [target] The target object to use - @return {Object} receiver - */ - forEach: function(callback, target) { - if (typeof callback !== 'function') throw new TypeError() ; - var len = get(this, 'length'), last = null, context = popCtx(); - - if (target === undefined) target = null; - - for(var idx=0;idx1) args = a_slice.call(arguments, 1); - - this.forEach(function(x, idx) { - var method = x && x[methodName]; - if ('function' === typeof method) { - ret[idx] = args ? apply(x, method, args) : x[methodName](); - } - }, this); - - return ret; - }, - - /** - Simply converts the enumerable into a genuine array. The order is not - guaranteed. Corresponds to the method implemented by Prototype. - - @method toArray - @return {Array} the enumerable as an array. - */ - toArray: function() { - var ret = Ember.A(); - this.forEach(function(o, idx) { ret[idx] = o; }); - return ret; - }, - - /** - Returns a copy of the array with all null and undefined elements removed. - - ```javascript - var arr = ["a", null, "c", undefined]; - arr.compact(); // ["a", "c"] - ``` - - @method compact - @return {Array} the array without null and undefined elements. - */ - compact: function() { - return this.filter(function(value) { return value != null; }); - }, - - /** - Returns a new enumerable that excludes the passed value. The default - implementation returns an array regardless of the receiver type unless - the receiver does not contain the value. - - ```javascript - var arr = ["a", "b", "a", "c"]; - arr.without("a"); // ["b", "c"] - ``` - - @method without - @param {Object} value - @return {Ember.Enumerable} - */ - without: function(value) { - if (!this.contains(value)) return this; // nothing to do - var ret = Ember.A(); - this.forEach(function(k) { - if (k !== value) ret[ret.length] = k; - }) ; - return ret ; - }, - - /** - Returns a new enumerable that contains only unique values. The default - implementation returns an array regardless of the receiver type. - - ```javascript - var arr = ["a", "a", "b", "b"]; - arr.uniq(); // ["a", "b"] - ``` - - @method uniq - @return {Ember.Enumerable} - */ - uniq: function() { - var ret = Ember.A(); - this.forEach(function(k) { - if (indexOf(ret, k)<0) ret.push(k); - }); - return ret; - }, - - /** - This property will trigger anytime the enumerable's content changes. - You can observe this property to be notified of changes to the enumerables - content. - - For plain enumerables, this property is read only. `Array` overrides - this method. - - @property [] - @type Array - @return this - */ - '[]': computed(function(key, value) { - return this; - }), - - // .......................................................... - // ENUMERABLE OBSERVERS - // - - /** - Registers an enumerable observer. Must implement `Ember.EnumerableObserver` - mixin. - - @method addEnumerableObserver - @param {Object} target - @param {Hash} [opts] - @return this - */ - addEnumerableObserver: function(target, opts) { - var willChange = (opts && opts.willChange) || 'enumerableWillChange'; - var didChange = (opts && opts.didChange) || 'enumerableDidChange'; - var hasObservers = get(this, 'hasEnumerableObservers'); - - if (!hasObservers) propertyWillChange(this, 'hasEnumerableObservers'); - addListener(this, '@enumerable:before', target, willChange); - addListener(this, '@enumerable:change', target, didChange); - if (!hasObservers) propertyDidChange(this, 'hasEnumerableObservers'); - return this; - }, - - /** - Removes a registered enumerable observer. - - @method removeEnumerableObserver - @param {Object} target - @param {Hash} [opts] - @return this - */ - removeEnumerableObserver: function(target, opts) { - var willChange = (opts && opts.willChange) || 'enumerableWillChange'; - var didChange = (opts && opts.didChange) || 'enumerableDidChange'; - - var hasObservers = get(this, 'hasEnumerableObservers'); - if (hasObservers) propertyWillChange(this, 'hasEnumerableObservers'); - removeListener(this, '@enumerable:before', target, willChange); - removeListener(this, '@enumerable:change', target, didChange); - if (hasObservers) propertyDidChange(this, 'hasEnumerableObservers'); - return this; - }, - - /** - Becomes true whenever the array currently has observers watching changes - on the array. - - @property hasEnumerableObservers - @type Boolean - */ - hasEnumerableObservers: computed(function() { - return hasListeners(this, '@enumerable:change') || hasListeners(this, '@enumerable:before'); - }), - - - /** - Invoke this method just before the contents of your enumerable will - change. You can either omit the parameters completely or pass the objects - to be removed or added if available or just a count. - - @method enumerableContentWillChange - @param {Ember.Enumerable|Number} removing An enumerable of the objects to - be removed or the number of items to be removed. - @param {Ember.Enumerable|Number} adding An enumerable of the objects to be - added or the number of items to be added. - @chainable - */ - enumerableContentWillChange: function(removing, adding) { - - var removeCnt, addCnt, hasDelta; - - if ('number' === typeof removing) removeCnt = removing; - else if (removing) removeCnt = get(removing, 'length'); - else removeCnt = removing = -1; - - if ('number' === typeof adding) addCnt = adding; - else if (adding) addCnt = get(adding,'length'); - else addCnt = adding = -1; - - hasDelta = addCnt<0 || removeCnt<0 || addCnt-removeCnt!==0; - - if (removing === -1) removing = null; - if (adding === -1) adding = null; - - propertyWillChange(this, '[]'); - if (hasDelta) propertyWillChange(this, 'length'); - sendEvent(this, '@enumerable:before', [this, removing, adding]); - - return this; - }, - - /** - Invoke this method when the contents of your enumerable has changed. - This will notify any observers watching for content changes. If you are - implementing an ordered enumerable (such as an array), also pass the - start and end values where the content changed so that it can be used to - notify range observers. - - @method enumerableContentDidChange - @param {Ember.Enumerable|Number} removing An enumerable of the objects to - be removed or the number of items to be removed. - @param {Ember.Enumerable|Number} adding An enumerable of the objects to - be added or the number of items to be added. - @chainable - */ - enumerableContentDidChange: function(removing, adding) { - var removeCnt, addCnt, hasDelta; - - if ('number' === typeof removing) removeCnt = removing; - else if (removing) removeCnt = get(removing, 'length'); - else removeCnt = removing = -1; - - if ('number' === typeof adding) addCnt = adding; - else if (adding) addCnt = get(adding, 'length'); - else addCnt = adding = -1; - - hasDelta = addCnt<0 || removeCnt<0 || addCnt-removeCnt!==0; - - if (removing === -1) removing = null; - if (adding === -1) adding = null; - - sendEvent(this, '@enumerable:change', [this, removing, adding]); - if (hasDelta) propertyDidChange(this, 'length'); - propertyDidChange(this, '[]'); - - return this ; - }, - - /** - Converts the enumerable into an array and sorts by the keys - specified in the argument. - - You may provide multiple arguments to sort by multiple properties. - - @method sortBy - @param {String} property name(s) to sort on - @return {Array} The sorted array. - @since 1.2.0 - */ - sortBy: function() { - var sortKeys = arguments; - return this.toArray().sort(function(a, b){ - for(var i = 0; i < sortKeys.length; i++) { - var key = sortKeys[i]; - var propA = get(a, key); - var propB = get(b, key); - // return 1 or -1 else continue to the next sortKey - var compareValue = compare(propA, propB); - if (compareValue) { return compareValue; } - } - return 0; - }); - } - }); - }); -enifed("ember-runtime/mixins/evented", - ["ember-metal/mixin","ember-metal/events","exports"], - function(__dependency1__, __dependency2__, __exports__) { - "use strict"; - var Mixin = __dependency1__.Mixin; - var addListener = __dependency2__.addListener; - var removeListener = __dependency2__.removeListener; - var hasListeners = __dependency2__.hasListeners; - var sendEvent = __dependency2__.sendEvent; - - /** - @module ember - @submodule ember-runtime - */ - - /** - This mixin allows for Ember objects to subscribe to and emit events. - - ```javascript - App.Person = Ember.Object.extend(Ember.Evented, { - greet: function() { - // ... - this.trigger('greet'); - } - }); - - var person = App.Person.create(); - - person.on('greet', function() { - console.log('Our person has greeted'); - }); - - person.greet(); - - // outputs: 'Our person has greeted' - ``` - - You can also chain multiple event subscriptions: - - ```javascript - person.on('greet', function() { - console.log('Our person has greeted'); - }).one('greet', function() { - console.log('Offer one-time special'); - }).off('event', this, forgetThis); - ``` - - @class Evented - @namespace Ember - */ - __exports__["default"] = Mixin.create({ - - /** - Subscribes to a named event with given function. - - ```javascript - person.on('didLoad', function() { - // fired once the person has loaded - }); - ``` - - An optional target can be passed in as the 2nd argument that will - be set as the "this" for the callback. This is a good way to give your - function access to the object triggering the event. When the target - parameter is used the callback becomes the third argument. - - @method on - @param {String} name The name of the event - @param {Object} [target] The "this" binding for the callback - @param {Function} method The callback to execute - @return this - */ - on: function(name, target, method) { - addListener(this, name, target, method); - return this; - }, - - /** - Subscribes a function to a named event and then cancels the subscription - after the first time the event is triggered. It is good to use ``one`` when - you only care about the first time an event has taken place. - - This function takes an optional 2nd argument that will become the "this" - value for the callback. If this argument is passed then the 3rd argument - becomes the function. - - @method one - @param {String} name The name of the event - @param {Object} [target] The "this" binding for the callback - @param {Function} method The callback to execute - @return this - */ - one: function(name, target, method) { - if (!method) { - method = target; - target = null; - } - - addListener(this, name, target, method, true); - return this; - }, - - /** - Triggers a named event for the object. Any additional arguments - will be passed as parameters to the functions that are subscribed to the - event. - - ```javascript - person.on('didEat', function(food) { - console.log('person ate some ' + food); - }); - - person.trigger('didEat', 'broccoli'); - - // outputs: person ate some broccoli - ``` - @method trigger - @param {String} name The name of the event - @param {Object...} args Optional arguments to pass on - */ - trigger: function(name) { - var length = arguments.length; - var args = new Array(length - 1); - - for (var i = 1; i < length; i++) { - args[i - 1] = arguments[i]; - } - - sendEvent(this, name, args); - }, - - /** - Cancels subscription for given name, target, and method. - - @method off - @param {String} name The name of the event - @param {Object} target The target of the subscription - @param {Function} method The function of the subscription - @return this - */ - off: function(name, target, method) { - removeListener(this, name, target, method); - return this; - }, - - /** - Checks to see if object has any subscriptions for named event. - - @method has - @param {String} name The name of the event - @return {Boolean} does the object have a subscription for event - */ - has: function(name) { - return hasListeners(this, name); - } - }); - }); -enifed("ember-runtime/mixins/freezable", - ["ember-metal/mixin","ember-metal/property_get","ember-metal/property_set","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __exports__) { - "use strict"; - /** - @module ember - @submodule ember-runtime - */ - - var Mixin = __dependency1__.Mixin; - var get = __dependency2__.get; - var set = __dependency3__.set; - - /** - The `Ember.Freezable` mixin implements some basic methods for marking an - object as frozen. Once an object is frozen it should be read only. No changes - may be made the internal state of the object. - - ## Enforcement - - To fully support freezing in your subclass, you must include this mixin and - override any method that might alter any property on the object to instead - raise an exception. You can check the state of an object by checking the - `isFrozen` property. - - Although future versions of JavaScript may support language-level freezing - object objects, that is not the case today. Even if an object is freezable, - it is still technically possible to modify the object, even though it could - break other parts of your application that do not expect a frozen object to - change. It is, therefore, very important that you always respect the - `isFrozen` property on all freezable objects. - - ## Example Usage - - The example below shows a simple object that implement the `Ember.Freezable` - protocol. - - ```javascript - Contact = Ember.Object.extend(Ember.Freezable, { - firstName: null, - lastName: null, - - // swaps the names - swapNames: function() { - if (this.get('isFrozen')) throw Ember.FROZEN_ERROR; - var tmp = this.get('firstName'); - this.set('firstName', this.get('lastName')); - this.set('lastName', tmp); - return this; - } - - }); - - c = Contact.create({ firstName: "John", lastName: "Doe" }); - c.swapNames(); // returns c - c.freeze(); - c.swapNames(); // EXCEPTION - ``` - - ## Copying - - Usually the `Ember.Freezable` protocol is implemented in cooperation with the - `Ember.Copyable` protocol, which defines a `frozenCopy()` method that will - return a frozen object, if the object implements this method as well. - - @class Freezable - @namespace Ember - @since Ember 0.9 - */ - var Freezable = Mixin.create({ - - /** - Set to `true` when the object is frozen. Use this property to detect - whether your object is frozen or not. - - @property isFrozen - @type Boolean - */ - isFrozen: false, - - /** - Freezes the object. Once this method has been called the object should - no longer allow any properties to be edited. - - @method freeze - @return {Object} receiver - */ - freeze: function() { - if (get(this, 'isFrozen')) return this; - set(this, 'isFrozen', true); - return this; - } - - }); - __exports__.Freezable = Freezable; - var FROZEN_ERROR = "Frozen object cannot be modified."; - __exports__.FROZEN_ERROR = FROZEN_ERROR; - }); -enifed("ember-runtime/mixins/mutable_array", - ["ember-metal/property_get","ember-metal/property_set","ember-metal/utils","ember-metal/error","ember-metal/mixin","ember-runtime/mixins/array","ember-runtime/mixins/mutable_enumerable","ember-runtime/mixins/enumerable","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __exports__) { - "use strict"; - /** - @module ember - @submodule ember-runtime - */ - - - // require('ember-runtime/mixins/array'); - // require('ember-runtime/mixins/mutable_enumerable'); - - // .......................................................... - // CONSTANTS - // - - var OUT_OF_RANGE_EXCEPTION = "Index out of range"; - var EMPTY = []; - - // .......................................................... - // HELPERS - // - - var get = __dependency1__.get; - var set = __dependency2__.set; - var isArray = __dependency3__.isArray; - var EmberError = __dependency4__["default"]; - var Mixin = __dependency5__.Mixin; - var required = __dependency5__.required; - var EmberArray = __dependency6__["default"]; - var MutableEnumerable = __dependency7__["default"]; - var Enumerable = __dependency8__["default"]; - /** - This mixin defines the API for modifying array-like objects. These methods - can be applied only to a collection that keeps its items in an ordered set. - It builds upon the Array mixin and adds methods to modify the array. - Concrete implementations of this class include ArrayProxy and ArrayController. - - It is important to use the methods in this class to modify arrays so that - changes are observable. This allows the binding system in Ember to function - correctly. - - - Note that an Array can change even if it does not implement this mixin. - For example, one might implement a SparseArray that cannot be directly - modified, but if its underlying enumerable changes, it will change also. - - @class MutableArray - @namespace Ember - @uses Ember.Array - @uses Ember.MutableEnumerable - */ - __exports__["default"] = Mixin.create(EmberArray, MutableEnumerable, { - - /** - __Required.__ You must implement this method to apply this mixin. - - This is one of the primitives you must implement to support `Ember.Array`. - You should replace amt objects started at idx with the objects in the - passed array. You should also call `this.enumerableContentDidChange()` - - @method replace - @param {Number} idx Starting index in the array to replace. If - idx >= length, then append to the end of the array. - @param {Number} amt Number of elements that should be removed from - the array, starting at *idx*. - @param {Array} objects An array of zero or more objects that should be - inserted into the array at *idx* - */ - replace: required(), - - /** - Remove all elements from the array. This is useful if you - want to reuse an existing array without having to recreate it. - - ```javascript - var colors = ["red", "green", "blue"]; - color.length(); // 3 - colors.clear(); // [] - colors.length(); // 0 - ``` - - @method clear - @return {Ember.Array} An empty Array. - */ - clear: function () { - var len = get(this, 'length'); - if (len === 0) return this; - this.replace(0, len, EMPTY); - return this; - }, - - /** - This will use the primitive `replace()` method to insert an object at the - specified index. - - ```javascript - var colors = ["red", "green", "blue"]; - colors.insertAt(2, "yellow"); // ["red", "green", "yellow", "blue"] - colors.insertAt(5, "orange"); // Error: Index out of range - ``` - - @method insertAt - @param {Number} idx index of insert the object at. - @param {Object} object object to insert - @return {Ember.Array} receiver - */ - insertAt: function(idx, object) { - if (idx > get(this, 'length')) throw new EmberError(OUT_OF_RANGE_EXCEPTION); - this.replace(idx, 0, [object]); - return this; - }, - - /** - Remove an object at the specified index using the `replace()` primitive - method. You can pass either a single index, or a start and a length. - - If you pass a start and length that is beyond the - length this method will throw an `OUT_OF_RANGE_EXCEPTION`. - - ```javascript - var colors = ["red", "green", "blue", "yellow", "orange"]; - colors.removeAt(0); // ["green", "blue", "yellow", "orange"] - colors.removeAt(2, 2); // ["green", "blue"] - colors.removeAt(4, 2); // Error: Index out of range - ``` - - @method removeAt - @param {Number} start index, start of range - @param {Number} len length of passing range - @return {Ember.Array} receiver - */ - removeAt: function(start, len) { - if ('number' === typeof start) { - - if ((start < 0) || (start >= get(this, 'length'))) { - throw new EmberError(OUT_OF_RANGE_EXCEPTION); - } - - // fast case - if (len === undefined) len = 1; - this.replace(start, len, EMPTY); - } - - return this; - }, - - /** - Push the object onto the end of the array. Works just like `push()` but it - is KVO-compliant. - - ```javascript - var colors = ["red", "green"]; - colors.pushObject("black"); // ["red", "green", "black"] - colors.pushObject(["yellow"]); // ["red", "green", ["yellow"]] - ``` - - @method pushObject - @param {*} obj object to push - @return object same object passed as a param - */ - pushObject: function(obj) { - this.insertAt(get(this, 'length'), obj); - return obj; - }, - - /** - Add the objects in the passed numerable to the end of the array. Defers - notifying observers of the change until all objects are added. - - ```javascript - var colors = ["red"]; - colors.pushObjects(["yellow", "orange"]); // ["red", "yellow", "orange"] - ``` - - @method pushObjects - @param {Ember.Enumerable} objects the objects to add - @return {Ember.Array} receiver - */ - pushObjects: function(objects) { - if (!(Enumerable.detect(objects) || isArray(objects))) { - throw new TypeError("Must pass Ember.Enumerable to Ember.MutableArray#pushObjects"); - } - this.replace(get(this, 'length'), 0, objects); - return this; - }, - - /** - Pop object from array or nil if none are left. Works just like `pop()` but - it is KVO-compliant. - - ```javascript - var colors = ["red", "green", "blue"]; - colors.popObject(); // "blue" - console.log(colors); // ["red", "green"] - ``` - - @method popObject - @return object - */ - popObject: function() { - var len = get(this, 'length'); - if (len === 0) return null; - - var ret = this.objectAt(len-1); - this.removeAt(len-1, 1); - return ret; - }, - - /** - Shift an object from start of array or nil if none are left. Works just - like `shift()` but it is KVO-compliant. - - ```javascript - var colors = ["red", "green", "blue"]; - colors.shiftObject(); // "red" - console.log(colors); // ["green", "blue"] - ``` - - @method shiftObject - @return object - */ - shiftObject: function() { - if (get(this, 'length') === 0) return null; - var ret = this.objectAt(0); - this.removeAt(0); - return ret; - }, - - /** - Unshift an object to start of array. Works just like `unshift()` but it is - KVO-compliant. - - ```javascript - var colors = ["red"]; - colors.unshiftObject("yellow"); // ["yellow", "red"] - colors.unshiftObject(["black"]); // [["black"], "yellow", "red"] - ``` - - @method unshiftObject - @param {*} obj object to unshift - @return object same object passed as a param - */ - unshiftObject: function(obj) { - this.insertAt(0, obj); - return obj; - }, - - /** - Adds the named objects to the beginning of the array. Defers notifying - observers until all objects have been added. - - ```javascript - var colors = ["red"]; - colors.unshiftObjects(["black", "white"]); // ["black", "white", "red"] - colors.unshiftObjects("yellow"); // Type Error: 'undefined' is not a function - ``` - - @method unshiftObjects - @param {Ember.Enumerable} objects the objects to add - @return {Ember.Array} receiver - */ - unshiftObjects: function(objects) { - this.replace(0, 0, objects); - return this; - }, - - /** - Reverse objects in the array. Works just like `reverse()` but it is - KVO-compliant. - - @method reverseObjects - @return {Ember.Array} receiver - */ - reverseObjects: function() { - var len = get(this, 'length'); - if (len === 0) return this; - var objects = this.toArray().reverse(); - this.replace(0, len, objects); - return this; - }, - - /** - Replace all the receiver's content with content of the argument. - If argument is an empty array receiver will be cleared. - - ```javascript - var colors = ["red", "green", "blue"]; - colors.setObjects(["black", "white"]); // ["black", "white"] - colors.setObjects([]); // [] - ``` - - @method setObjects - @param {Ember.Array} objects array whose content will be used for replacing - the content of the receiver - @return {Ember.Array} receiver with the new content - */ - setObjects: function(objects) { - if (objects.length === 0) return this.clear(); - - var len = get(this, 'length'); - this.replace(0, len, objects); - return this; - }, - - // .......................................................... - // IMPLEMENT Ember.MutableEnumerable - // - - /** - Remove all occurances of an object in the array. - - ```javascript - var cities = ["Chicago", "Berlin", "Lima", "Chicago"]; - cities.removeObject("Chicago"); // ["Berlin", "Lima"] - cities.removeObject("Lima"); // ["Berlin"] - cities.removeObject("Tokyo") // ["Berlin"] - ``` - - @method removeObject - @param {*} obj object to remove - @return {Ember.Array} receiver - */ - removeObject: function(obj) { - var loc = get(this, 'length') || 0; - while(--loc >= 0) { - var curObject = this.objectAt(loc); - if (curObject === obj) this.removeAt(loc); - } - return this; - }, - - /** - Push the object onto the end of the array if it is not already - present in the array. - - ```javascript - var cities = ["Chicago", "Berlin"]; - cities.addObject("Lima"); // ["Chicago", "Berlin", "Lima"] - cities.addObject("Berlin"); // ["Chicago", "Berlin", "Lima"] - ``` - - @method addObject - @param {*} obj object to add, if not already present - @return {Ember.Array} receiver - */ - addObject: function(obj) { - if (!this.contains(obj)) this.pushObject(obj); - return this; - } - - }); - }); -enifed("ember-runtime/mixins/mutable_enumerable", - ["ember-metal/enumerable_utils","ember-runtime/mixins/enumerable","ember-metal/mixin","ember-metal/property_events","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __exports__) { - "use strict"; - var forEach = __dependency1__.forEach; - var Enumerable = __dependency2__["default"]; - var Mixin = __dependency3__.Mixin; - var required = __dependency3__.required; - var beginPropertyChanges = __dependency4__.beginPropertyChanges; - var endPropertyChanges = __dependency4__.endPropertyChanges; - - /** - @module ember - @submodule ember-runtime - */ - - /** - This mixin defines the API for modifying generic enumerables. These methods - can be applied to an object regardless of whether it is ordered or - unordered. - - Note that an Enumerable can change even if it does not implement this mixin. - For example, a MappedEnumerable cannot be directly modified but if its - underlying enumerable changes, it will change also. - - ## Adding Objects - - To add an object to an enumerable, use the `addObject()` method. This - method will only add the object to the enumerable if the object is not - already present and is of a type supported by the enumerable. - - ```javascript - set.addObject(contact); - ``` - - ## Removing Objects - - To remove an object from an enumerable, use the `removeObject()` method. This - will only remove the object if it is present in the enumerable, otherwise - this method has no effect. - - ```javascript - set.removeObject(contact); - ``` - - ## Implementing In Your Own Code - - If you are implementing an object and want to support this API, just include - this mixin in your class and implement the required methods. In your unit - tests, be sure to apply the Ember.MutableEnumerableTests to your object. - - @class MutableEnumerable - @namespace Ember - @uses Ember.Enumerable - */ - __exports__["default"] = Mixin.create(Enumerable, { - - /** - __Required.__ You must implement this method to apply this mixin. - - Attempts to add the passed object to the receiver if the object is not - already present in the collection. If the object is present, this method - has no effect. - - If the passed object is of a type not supported by the receiver, - then this method should raise an exception. - - @method addObject - @param {Object} object The object to add to the enumerable. - @return {Object} the passed object - */ - addObject: required(Function), - - /** - Adds each object in the passed enumerable to the receiver. - - @method addObjects - @param {Ember.Enumerable} objects the objects to add. - @return {Object} receiver - */ - addObjects: function(objects) { - beginPropertyChanges(this); - forEach(objects, function(obj) { this.addObject(obj); }, this); - endPropertyChanges(this); - return this; - }, - - /** - __Required.__ You must implement this method to apply this mixin. - - Attempts to remove the passed object from the receiver collection if the - object is present in the collection. If the object is not present, - this method has no effect. - - If the passed object is of a type not supported by the receiver, - then this method should raise an exception. - - @method removeObject - @param {Object} object The object to remove from the enumerable. - @return {Object} the passed object - */ - removeObject: required(Function), - - - /** - Removes each object in the passed enumerable from the receiver. - - @method removeObjects - @param {Ember.Enumerable} objects the objects to remove - @return {Object} receiver - */ - removeObjects: function(objects) { - beginPropertyChanges(this); - for (var i = objects.length - 1; i >= 0; i--) { - this.removeObject(objects[i]); - } - endPropertyChanges(this); - return this; - } - }); - }); -enifed("ember-runtime/mixins/observable", - ["ember-metal/core","ember-metal/property_get","ember-metal/property_set","ember-metal/utils","ember-metal/get_properties","ember-metal/set_properties","ember-metal/mixin","ember-metal/events","ember-metal/property_events","ember-metal/observer","ember-metal/computed","ember-metal/is_none","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __dependency11__, __dependency12__, __exports__) { - "use strict"; - /** - @module ember - @submodule ember-runtime - */ - var Ember = __dependency1__["default"]; - // Ember.assert - - var get = __dependency2__.get; - var getWithDefault = __dependency2__.getWithDefault; - var set = __dependency3__.set; - var apply = __dependency4__.apply; - var getProperties = __dependency5__["default"]; - var setProperties = __dependency6__["default"]; - var Mixin = __dependency7__.Mixin; - var hasListeners = __dependency8__.hasListeners; - var beginPropertyChanges = __dependency9__.beginPropertyChanges; - var propertyWillChange = __dependency9__.propertyWillChange; - var propertyDidChange = __dependency9__.propertyDidChange; - var endPropertyChanges = __dependency9__.endPropertyChanges; - var addObserver = __dependency10__.addObserver; - var addBeforeObserver = __dependency10__.addBeforeObserver; - var removeObserver = __dependency10__.removeObserver; - var observersFor = __dependency10__.observersFor; - var cacheFor = __dependency11__.cacheFor; - var isNone = __dependency12__.isNone; - - - var slice = Array.prototype.slice; - /** - ## Overview - - This mixin provides properties and property observing functionality, core - features of the Ember object model. - - Properties and observers allow one object to observe changes to a - property on another object. This is one of the fundamental ways that - models, controllers and views communicate with each other in an Ember - application. - - Any object that has this mixin applied can be used in observer - operations. That includes `Ember.Object` and most objects you will - interact with as you write your Ember application. - - Note that you will not generally apply this mixin to classes yourself, - but you will use the features provided by this module frequently, so it - is important to understand how to use it. - - ## Using `get()` and `set()` - - Because of Ember's support for bindings and observers, you will always - access properties using the get method, and set properties using the - set method. This allows the observing objects to be notified and - computed properties to be handled properly. - - More documentation about `get` and `set` are below. - - ## Observing Property Changes - - You typically observe property changes simply by adding the `observes` - call to the end of your method declarations in classes that you write. - For example: - - ```javascript - Ember.Object.extend({ - valueObserver: function() { - // Executes whenever the "value" property changes - }.observes('value') - }); - ``` - - Although this is the most common way to add an observer, this capability - is actually built into the `Ember.Object` class on top of two methods - defined in this mixin: `addObserver` and `removeObserver`. You can use - these two methods to add and remove observers yourself if you need to - do so at runtime. - - To add an observer for a property, call: - - ```javascript - object.addObserver('propertyKey', targetObject, targetAction) - ``` - - This will call the `targetAction` method on the `targetObject` whenever - the value of the `propertyKey` changes. - - Note that if `propertyKey` is a computed property, the observer will be - called when any of the property dependencies are changed, even if the - resulting value of the computed property is unchanged. This is necessary - because computed properties are not computed until `get` is called. - - @class Observable - @namespace Ember - */ - __exports__["default"] = Mixin.create({ - - /** - Retrieves the value of a property from the object. - - This method is usually similar to using `object[keyName]` or `object.keyName`, - however it supports both computed properties and the unknownProperty - handler. - - Because `get` unifies the syntax for accessing all these kinds - of properties, it can make many refactorings easier, such as replacing a - simple property with a computed property, or vice versa. - - ### Computed Properties - - Computed properties are methods defined with the `property` modifier - declared at the end, such as: - - ```javascript - fullName: function() { - return this.get('firstName') + ' ' + this.get('lastName'); - }.property('firstName', 'lastName') - ``` - - When you call `get` on a computed property, the function will be - called and the return value will be returned instead of the function - itself. - - ### Unknown Properties - - Likewise, if you try to call `get` on a property whose value is - `undefined`, the `unknownProperty()` method will be called on the object. - If this method returns any value other than `undefined`, it will be returned - instead. This allows you to implement "virtual" properties that are - not defined upfront. - - @method get - @param {String} keyName The property to retrieve - @return {Object} The property value or undefined. - */ - get: function(keyName) { - return get(this, keyName); - }, - - /** - To get the values of multiple properties at once, call `getProperties` - with a list of strings or an array: - - ```javascript - record.getProperties('firstName', 'lastName', 'zipCode'); - // { firstName: 'John', lastName: 'Doe', zipCode: '10011' } - ``` - - is equivalent to: - - ```javascript - record.getProperties(['firstName', 'lastName', 'zipCode']); - // { firstName: 'John', lastName: 'Doe', zipCode: '10011' } - ``` - - @method getProperties - @param {String...|Array} list of keys to get - @return {Hash} - */ - getProperties: function() { - return apply(null, getProperties, [this].concat(slice.call(arguments))); - }, - - /** - Sets the provided key or path to the value. - - This method is generally very similar to calling `object[key] = value` or - `object.key = value`, except that it provides support for computed - properties, the `setUnknownProperty()` method and property observers. - - ### Computed Properties - - If you try to set a value on a key that has a computed property handler - defined (see the `get()` method for an example), then `set()` will call - that method, passing both the value and key instead of simply changing - the value itself. This is useful for those times when you need to - implement a property that is composed of one or more member - properties. - - ### Unknown Properties - - If you try to set a value on a key that is undefined in the target - object, then the `setUnknownProperty()` handler will be called instead. This - gives you an opportunity to implement complex "virtual" properties that - are not predefined on the object. If `setUnknownProperty()` returns - undefined, then `set()` will simply set the value on the object. - - ### Property Observers - - In addition to changing the property, `set()` will also register a property - change with the object. Unless you have placed this call inside of a - `beginPropertyChanges()` and `endPropertyChanges(),` any "local" observers - (i.e. observer methods declared on the same object), will be called - immediately. Any "remote" observers (i.e. observer methods declared on - another object) will be placed in a queue and called at a later time in a - coalesced manner. - - ### Chaining - - In addition to property changes, `set()` returns the value of the object - itself so you can do chaining like this: - - ```javascript - record.set('firstName', 'Charles').set('lastName', 'Jolley'); - ``` - - @method set - @param {String} keyName The property to set - @param {Object} value The value to set or `null`. - @return {Ember.Observable} - */ - set: function(keyName, value) { - set(this, keyName, value); - return this; - }, - - - /** - Sets a list of properties at once. These properties are set inside - a single `beginPropertyChanges` and `endPropertyChanges` batch, so - observers will be buffered. - - ```javascript - record.setProperties({ firstName: 'Charles', lastName: 'Jolley' }); - ``` - - @method setProperties - @param {Hash} hash the hash of keys and values to set - @return {Ember.Observable} - */ - setProperties: function(hash) { - return setProperties(this, hash); - }, - - /** - Begins a grouping of property changes. - - You can use this method to group property changes so that notifications - will not be sent until the changes are finished. If you plan to make a - large number of changes to an object at one time, you should call this - method at the beginning of the changes to begin deferring change - notifications. When you are done making changes, call - `endPropertyChanges()` to deliver the deferred change notifications and end - deferring. - - @method beginPropertyChanges - @return {Ember.Observable} - */ - beginPropertyChanges: function() { - beginPropertyChanges(); - return this; - }, - - /** - Ends a grouping of property changes. - - You can use this method to group property changes so that notifications - will not be sent until the changes are finished. If you plan to make a - large number of changes to an object at one time, you should call - `beginPropertyChanges()` at the beginning of the changes to defer change - notifications. When you are done making changes, call this method to - deliver the deferred change notifications and end deferring. - - @method endPropertyChanges - @return {Ember.Observable} - */ - endPropertyChanges: function() { - endPropertyChanges(); - return this; - }, - - /** - Notify the observer system that a property is about to change. - - Sometimes you need to change a value directly or indirectly without - actually calling `get()` or `set()` on it. In this case, you can use this - method and `propertyDidChange()` instead. Calling these two methods - together will notify all observers that the property has potentially - changed value. - - Note that you must always call `propertyWillChange` and `propertyDidChange` - as a pair. If you do not, it may get the property change groups out of - order and cause notifications to be delivered more often than you would - like. - - @method propertyWillChange - @param {String} keyName The property key that is about to change. - @return {Ember.Observable} - */ - propertyWillChange: function(keyName) { - propertyWillChange(this, keyName); - return this; - }, - - /** - Notify the observer system that a property has just changed. - - Sometimes you need to change a value directly or indirectly without - actually calling `get()` or `set()` on it. In this case, you can use this - method and `propertyWillChange()` instead. Calling these two methods - together will notify all observers that the property has potentially - changed value. - - Note that you must always call `propertyWillChange` and `propertyDidChange` - as a pair. If you do not, it may get the property change groups out of - order and cause notifications to be delivered more often than you would - like. - - @method propertyDidChange - @param {String} keyName The property key that has just changed. - @return {Ember.Observable} - */ - propertyDidChange: function(keyName) { - propertyDidChange(this, keyName); - return this; - }, - - /** - Convenience method to call `propertyWillChange` and `propertyDidChange` in - succession. - - @method notifyPropertyChange - @param {String} keyName The property key to be notified about. - @return {Ember.Observable} - */ - notifyPropertyChange: function(keyName) { - this.propertyWillChange(keyName); - this.propertyDidChange(keyName); - return this; - }, - - addBeforeObserver: function(key, target, method) { - addBeforeObserver(this, key, target, method); - }, - - /** - Adds an observer on a property. - - This is the core method used to register an observer for a property. - - Once you call this method, any time the key's value is set, your observer - will be notified. Note that the observers are triggered any time the - value is set, regardless of whether it has actually changed. Your - observer should be prepared to handle that. - - You can also pass an optional context parameter to this method. The - context will be passed to your observer method whenever it is triggered. - Note that if you add the same target/method pair on a key multiple times - with different context parameters, your observer will only be called once - with the last context you passed. - - ### Observer Methods - - Observer methods you pass should generally have the following signature if - you do not pass a `context` parameter: - - ```javascript - fooDidChange: function(sender, key, value, rev) { }; - ``` - - The sender is the object that changed. The key is the property that - changes. The value property is currently reserved and unused. The rev - is the last property revision of the object when it changed, which you can - use to detect if the key value has really changed or not. - - If you pass a `context` parameter, the context will be passed before the - revision like so: - - ```javascript - fooDidChange: function(sender, key, value, context, rev) { }; - ``` - - Usually you will not need the value, context or revision parameters at - the end. In this case, it is common to write observer methods that take - only a sender and key value as parameters or, if you aren't interested in - any of these values, to write an observer that has no parameters at all. - - @method addObserver - @param {String} key The key to observer - @param {Object} target The target object to invoke - @param {String|Function} method The method to invoke. - */ - addObserver: function(key, target, method) { - addObserver(this, key, target, method); - }, - - /** - Remove an observer you have previously registered on this object. Pass - the same key, target, and method you passed to `addObserver()` and your - target will no longer receive notifications. - - @method removeObserver - @param {String} key The key to observer - @param {Object} target The target object to invoke - @param {String|Function} method The method to invoke. - */ - removeObserver: function(key, target, method) { - removeObserver(this, key, target, method); - }, - - /** - Returns `true` if the object currently has observers registered for a - particular key. You can use this method to potentially defer performing - an expensive action until someone begins observing a particular property - on the object. - - @method hasObserverFor - @param {String} key Key to check - @return {Boolean} - */ - hasObserverFor: function(key) { - return hasListeners(this, key+':change'); - }, - - /** - Retrieves the value of a property, or a default value in the case that the - property returns `undefined`. - - ```javascript - person.getWithDefault('lastName', 'Doe'); - ``` - - @method getWithDefault - @param {String} keyName The name of the property to retrieve - @param {Object} defaultValue The value to return if the property value is undefined - @return {Object} The property value or the defaultValue. - */ - getWithDefault: function(keyName, defaultValue) { - return getWithDefault(this, keyName, defaultValue); - }, - - /** - Set the value of a property to the current value plus some amount. - - ```javascript - person.incrementProperty('age'); - team.incrementProperty('score', 2); - ``` - - @method incrementProperty - @param {String} keyName The name of the property to increment - @param {Number} increment The amount to increment by. Defaults to 1 - @return {Number} The new property value - */ - incrementProperty: function(keyName, increment) { - if (isNone(increment)) { increment = 1; } - Ember.assert("Must pass a numeric value to incrementProperty", (!isNaN(parseFloat(increment)) && isFinite(increment))); - set(this, keyName, (parseFloat(get(this, keyName)) || 0) + increment); - return get(this, keyName); - }, - - /** - Set the value of a property to the current value minus some amount. - - ```javascript - player.decrementProperty('lives'); - orc.decrementProperty('health', 5); - ``` - - @method decrementProperty - @param {String} keyName The name of the property to decrement - @param {Number} decrement The amount to decrement by. Defaults to 1 - @return {Number} The new property value - */ - decrementProperty: function(keyName, decrement) { - if (isNone(decrement)) { decrement = 1; } - Ember.assert("Must pass a numeric value to decrementProperty", (!isNaN(parseFloat(decrement)) && isFinite(decrement))); - set(this, keyName, (get(this, keyName) || 0) - decrement); - return get(this, keyName); - }, - - /** - Set the value of a boolean property to the opposite of it's - current value. - - ```javascript - starship.toggleProperty('warpDriveEngaged'); - ``` - - @method toggleProperty - @param {String} keyName The name of the property to toggle - @return {Object} The new property value - */ - toggleProperty: function(keyName) { - set(this, keyName, !get(this, keyName)); - return get(this, keyName); - }, - - /** - Returns the cached value of a computed property, if it exists. - This allows you to inspect the value of a computed property - without accidentally invoking it if it is intended to be - generated lazily. - - @method cacheFor - @param {String} keyName - @return {Object} The cached value of the computed property, if any - */ - cacheFor: function(keyName) { - return cacheFor(this, keyName); - }, - - // intended for debugging purposes - observersForKey: function(keyName) { - return observersFor(this, keyName); - } - }); - }); -enifed("ember-runtime/mixins/promise_proxy", - ["ember-metal/property_get","ember-metal/set_properties","ember-metal/computed","ember-metal/mixin","ember-metal/error","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __exports__) { - "use strict"; - var get = __dependency1__.get; - var setProperties = __dependency2__["default"]; - var computed = __dependency3__.computed; - var Mixin = __dependency4__.Mixin; - var EmberError = __dependency5__["default"]; - - var not = computed.not; - var or = computed.or; - - /** - @module ember - @submodule ember-runtime - */ - - function tap(proxy, promise) { - setProperties(proxy, { - isFulfilled: false, - isRejected: false - }); - - return promise.then(function(value) { - setProperties(proxy, { - content: value, - isFulfilled: true - }); - return value; - }, function(reason) { - setProperties(proxy, { - reason: reason, - isRejected: true - }); - throw reason; - }, "Ember: PromiseProxy"); - } - - /** - A low level mixin making ObjectProxy, ObjectController or ArrayController's promise aware. - - ```javascript - var ObjectPromiseController = Ember.ObjectController.extend(Ember.PromiseProxyMixin); - - var controller = ObjectPromiseController.create({ - promise: $.getJSON('/some/remote/data.json') - }); - - controller.then(function(json){ - // the json - }, function(reason) { - // the reason why you have no json - }); - ``` - - the controller has bindable attributes which - track the promises life cycle - - ```javascript - controller.get('isPending') //=> true - controller.get('isSettled') //=> false - controller.get('isRejected') //=> false - controller.get('isFulfilled') //=> false - ``` - - When the the $.getJSON completes, and the promise is fulfilled - with json, the life cycle attributes will update accordingly. - - ```javascript - controller.get('isPending') //=> false - controller.get('isSettled') //=> true - controller.get('isRejected') //=> false - controller.get('isFulfilled') //=> true - ``` - - As the controller is an ObjectController, and the json now its content, - all the json properties will be available directly from the controller. - - ```javascript - // Assuming the following json: - { - firstName: 'Stefan', - lastName: 'Penner' - } - - // both properties will accessible on the controller - controller.get('firstName') //=> 'Stefan' - controller.get('lastName') //=> 'Penner' - ``` - - If the controller is backing a template, the attributes are - bindable from within that template - - ```handlebars - {{#if isPending}} - loading... - {{else}} - firstName: {{firstName}} - lastName: {{lastName}} - {{/if}} - ``` - @class Ember.PromiseProxyMixin - */ - __exports__["default"] = Mixin.create({ - /** - If the proxied promise is rejected this will contain the reason - provided. - - @property reason - @default null - */ - reason: null, - - /** - Once the proxied promise has settled this will become `false`. - - @property isPending - @default true - */ - isPending: not('isSettled').readOnly(), - - /** - Once the proxied promise has settled this will become `true`. - - @property isSettled - @default false - */ - isSettled: or('isRejected', 'isFulfilled').readOnly(), - - /** - Will become `true` if the proxied promise is rejected. - - @property isRejected - @default false - */ - isRejected: false, - - /** - Will become `true` if the proxied promise is fulfilled. - - @property isFulfilled - @default false - */ - isFulfilled: false, - - /** - The promise whose fulfillment value is being proxied by this object. - - This property must be specified upon creation, and should not be - changed once created. - - Example: - - ```javascript - Ember.ObjectController.extend(Ember.PromiseProxyMixin).create({ - promise: - }); - ``` - - @property promise - */ - promise: computed(function(key, promise) { - if (arguments.length === 2) { - return tap(this, promise); - } else { - throw new EmberError("PromiseProxy's promise must be set"); - } - }), - - /** - An alias to the proxied promise's `then`. - - See RSVP.Promise.then. - - @method then - @param {Function} callback - @return {RSVP.Promise} - */ - then: promiseAlias('then'), - - /** - An alias to the proxied promise's `catch`. - - See RSVP.Promise.catch. - - @method catch - @param {Function} callback - @return {RSVP.Promise} - @since 1.3.0 - */ - 'catch': promiseAlias('catch'), - - /** - An alias to the proxied promise's `finally`. - - See RSVP.Promise.finally. - - @method finally - @param {Function} callback - @return {RSVP.Promise} - @since 1.3.0 - */ - 'finally': promiseAlias('finally') - - }); - - function promiseAlias(name) { - return function () { - var promise = get(this, 'promise'); - return promise[name].apply(promise, arguments); - }; - } - }); -enifed("ember-runtime/mixins/sortable", - ["ember-metal/core","ember-metal/property_get","ember-metal/property_set","ember-metal/enumerable_utils","ember-metal/mixin","ember-runtime/mixins/mutable_enumerable","ember-runtime/compare","ember-metal/observer","ember-metal/computed","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __exports__) { - "use strict"; - /** - @module ember - @submodule ember-runtime - */ - - var Ember = __dependency1__["default"]; - // Ember.assert, Ember.A - - var get = __dependency2__.get; - var set = __dependency3__.set; - var forEach = __dependency4__.forEach; - var Mixin = __dependency5__.Mixin; - var MutableEnumerable = __dependency6__["default"]; - var compare = __dependency7__["default"]; - var addObserver = __dependency8__.addObserver; - var removeObserver = __dependency8__.removeObserver; - var computed = __dependency9__.computed; - var beforeObserver = __dependency5__.beforeObserver; - var observer = __dependency5__.observer; - //ES6TODO: should we access these directly from their package or from how thier exposed in ember-metal? - - /** - `Ember.SortableMixin` provides a standard interface for array proxies - to specify a sort order and maintain this sorting when objects are added, - removed, or updated without changing the implicit order of their underlying - modelarray: - - ```javascript - songs = [ - {trackNumber: 4, title: 'Ob-La-Di, Ob-La-Da'}, - {trackNumber: 2, title: 'Back in the U.S.S.R.'}, - {trackNumber: 3, title: 'Glass Onion'}, - ]; - - songsController = Ember.ArrayController.create({ - model: songs, - sortProperties: ['trackNumber'], - sortAscending: true - }); - - songsController.get('firstObject'); // {trackNumber: 2, title: 'Back in the U.S.S.R.'} - - songsController.addObject({trackNumber: 1, title: 'Dear Prudence'}); - songsController.get('firstObject'); // {trackNumber: 1, title: 'Dear Prudence'} - ``` - - If you add or remove the properties to sort by or change the sort direction the model - sort order will be automatically updated. - - ```javascript - songsController.set('sortProperties', ['title']); - songsController.get('firstObject'); // {trackNumber: 2, title: 'Back in the U.S.S.R.'} - - songsController.toggleProperty('sortAscending'); - songsController.get('firstObject'); // {trackNumber: 4, title: 'Ob-La-Di, Ob-La-Da'} - ``` - - SortableMixin works by sorting the arrangedContent array, which is the array that - arrayProxy displays. Due to the fact that the underlying 'content' array is not changed, that - array will not display the sorted list: - - ```javascript - songsController.get('content').get('firstObject'); // Returns the unsorted original content - songsController.get('firstObject'); // Returns the sorted content. - ``` - - Although the sorted content can also be accessed through the arrangedContent property, - it is preferable to use the proxied class and not the arrangedContent array directly. - - @class SortableMixin - @namespace Ember - @uses Ember.MutableEnumerable - */ - __exports__["default"] = Mixin.create(MutableEnumerable, { - - /** - Specifies which properties dictate the arrangedContent's sort order. - - When specifying multiple properties the sorting will use properties - from the `sortProperties` array prioritized from first to last. - - @property {Array} sortProperties - */ - sortProperties: null, - - /** - Specifies the arrangedContent's sort direction. - Sorts the content in ascending order by default. Set to `false` to - use descending order. - - @property {Boolean} sortAscending - @default true - */ - sortAscending: true, - - /** - The function used to compare two values. You can override this if you - want to do custom comparisons. Functions must be of the type expected by - Array#sort, i.e. - return 0 if the two parameters are equal, - return a negative value if the first parameter is smaller than the second or - return a positive value otherwise: - - ```javascript - function(x,y) { // These are assumed to be integers - if (x === y) - return 0; - return x < y ? -1 : 1; - } - ``` - - @property sortFunction - @type {Function} - @default Ember.compare - */ - sortFunction: compare, - - orderBy: function(item1, item2) { - var result = 0; - var sortProperties = get(this, 'sortProperties'); - var sortAscending = get(this, 'sortAscending'); - var sortFunction = get(this, 'sortFunction'); - - Ember.assert("you need to define `sortProperties`", !!sortProperties); - - forEach(sortProperties, function(propertyName) { - if (result === 0) { - result = sortFunction.call(this, get(item1, propertyName), get(item2, propertyName)); - if ((result !== 0) && !sortAscending) { - result = (-1) * result; - } - } - }, this); - - return result; - }, - - destroy: function() { - var content = get(this, 'content'); - var sortProperties = get(this, 'sortProperties'); - - if (content && sortProperties) { - forEach(content, function(item) { - forEach(sortProperties, function(sortProperty) { - removeObserver(item, sortProperty, this, 'contentItemSortPropertyDidChange'); - }, this); - }, this); - } - - return this._super(); - }, - - isSorted: computed.notEmpty('sortProperties'), - - /** - Overrides the default arrangedContent from arrayProxy in order to sort by sortFunction. - Also sets up observers for each sortProperty on each item in the content Array. - - @property arrangedContent - */ - - arrangedContent: computed('content', 'sortProperties.@each', function(key, value) { - var content = get(this, 'content'); - var isSorted = get(this, 'isSorted'); - var sortProperties = get(this, 'sortProperties'); - var self = this; - - if (content && isSorted) { - content = content.slice(); - content.sort(function(item1, item2) { - return self.orderBy(item1, item2); - }); - forEach(content, function(item) { - forEach(sortProperties, function(sortProperty) { - addObserver(item, sortProperty, this, 'contentItemSortPropertyDidChange'); - }, this); - }, this); - return Ember.A(content); - } - - return content; - }), - - _contentWillChange: beforeObserver('content', function() { - var content = get(this, 'content'); - var sortProperties = get(this, 'sortProperties'); - - if (content && sortProperties) { - forEach(content, function(item) { - forEach(sortProperties, function(sortProperty) { - removeObserver(item, sortProperty, this, 'contentItemSortPropertyDidChange'); - }, this); - }, this); - } - - this._super(); - }), - - sortPropertiesWillChange: beforeObserver('sortProperties', function() { - this._lastSortAscending = undefined; - }), - - sortPropertiesDidChange: observer('sortProperties', function() { - this._lastSortAscending = undefined; - }), - - sortAscendingWillChange: beforeObserver('sortAscending', function() { - this._lastSortAscending = get(this, 'sortAscending'); - }), - - sortAscendingDidChange: observer('sortAscending', function() { - if (this._lastSortAscending !== undefined && get(this, 'sortAscending') !== this._lastSortAscending) { - var arrangedContent = get(this, 'arrangedContent'); - arrangedContent.reverseObjects(); - } - }), - - contentArrayWillChange: function(array, idx, removedCount, addedCount) { - var isSorted = get(this, 'isSorted'); - - if (isSorted) { - var arrangedContent = get(this, 'arrangedContent'); - var removedObjects = array.slice(idx, idx+removedCount); - var sortProperties = get(this, 'sortProperties'); - - forEach(removedObjects, function(item) { - arrangedContent.removeObject(item); - - forEach(sortProperties, function(sortProperty) { - removeObserver(item, sortProperty, this, 'contentItemSortPropertyDidChange'); - }, this); - }, this); - } - - return this._super(array, idx, removedCount, addedCount); - }, - - contentArrayDidChange: function(array, idx, removedCount, addedCount) { - var isSorted = get(this, 'isSorted'); - var sortProperties = get(this, 'sortProperties'); - - if (isSorted) { - var addedObjects = array.slice(idx, idx+addedCount); - - forEach(addedObjects, function(item) { - this.insertItemSorted(item); - - forEach(sortProperties, function(sortProperty) { - addObserver(item, sortProperty, this, 'contentItemSortPropertyDidChange'); - }, this); - }, this); - } - - return this._super(array, idx, removedCount, addedCount); - }, - - insertItemSorted: function(item) { - var arrangedContent = get(this, 'arrangedContent'); - var length = get(arrangedContent, 'length'); - - var idx = this._binarySearch(item, 0, length); - arrangedContent.insertAt(idx, item); - }, - - contentItemSortPropertyDidChange: function(item) { - var arrangedContent = get(this, 'arrangedContent'); - var oldIndex = arrangedContent.indexOf(item); - var leftItem = arrangedContent.objectAt(oldIndex - 1); - var rightItem = arrangedContent.objectAt(oldIndex + 1); - var leftResult = leftItem && this.orderBy(item, leftItem); - var rightResult = rightItem && this.orderBy(item, rightItem); - - if (leftResult < 0 || rightResult > 0) { - arrangedContent.removeObject(item); - this.insertItemSorted(item); - } - }, - - _binarySearch: function(item, low, high) { - var mid, midItem, res, arrangedContent; - - if (low === high) { - return low; - } - - arrangedContent = get(this, 'arrangedContent'); - - mid = low + Math.floor((high - low) / 2); - midItem = arrangedContent.objectAt(mid); - - res = this.orderBy(midItem, item); - - if (res < 0) { - return this._binarySearch(item, mid+1, high); - } else if (res > 0) { - return this._binarySearch(item, low, mid); - } - - return mid; - } - }); - }); -enifed("ember-runtime/mixins/target_action_support", - ["ember-metal/core","ember-metal/property_get","ember-metal/property_set","ember-metal/utils","ember-metal/mixin","ember-metal/computed","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __exports__) { - "use strict"; - /** - @module ember - @submodule ember-runtime - */ - var Ember = __dependency1__["default"]; - // Ember.lookup, Ember.assert - - var get = __dependency2__.get; - var set = __dependency3__.set; - var typeOf = __dependency4__.typeOf; - var Mixin = __dependency5__.Mixin; - var computed = __dependency6__.computed; - - /** - `Ember.TargetActionSupport` is a mixin that can be included in a class - to add a `triggerAction` method with semantics similar to the Handlebars - `{{action}}` helper. In normal Ember usage, the `{{action}}` helper is - usually the best choice. This mixin is most often useful when you are - doing more complex event handling in View objects. - - See also `Ember.ViewTargetActionSupport`, which has - view-aware defaults for target and actionContext. - - @class TargetActionSupport - @namespace Ember - @extends Ember.Mixin - */ - var TargetActionSupport = Mixin.create({ - target: null, - action: null, - actionContext: null, - - targetObject: computed(function() { - var target = get(this, 'target'); - - if (typeOf(target) === "string") { - var value = get(this, target); - if (value === undefined) { value = get(Ember.lookup, target); } - return value; - } else { - return target; - } - }).property('target'), - - actionContextObject: computed(function() { - var actionContext = get(this, 'actionContext'); - - if (typeOf(actionContext) === "string") { - var value = get(this, actionContext); - if (value === undefined) { value = get(Ember.lookup, actionContext); } - return value; - } else { - return actionContext; - } - }).property('actionContext'), - - /** - Send an `action` with an `actionContext` to a `target`. The action, actionContext - and target will be retrieved from properties of the object. For example: - - ```javascript - App.SaveButtonView = Ember.View.extend(Ember.TargetActionSupport, { - target: Ember.computed.alias('controller'), - action: 'save', - actionContext: Ember.computed.alias('context'), - click: function() { - this.triggerAction(); // Sends the `save` action, along with the current context - // to the current controller - } - }); - ``` - - The `target`, `action`, and `actionContext` can be provided as properties of - an optional object argument to `triggerAction` as well. - - ```javascript - App.SaveButtonView = Ember.View.extend(Ember.TargetActionSupport, { - click: function() { - this.triggerAction({ - action: 'save', - target: this.get('controller'), - actionContext: this.get('context') - }); // Sends the `save` action, along with the current context - // to the current controller - } - }); - ``` - - The `actionContext` defaults to the object you are mixing `TargetActionSupport` into. - But `target` and `action` must be specified either as properties or with the argument - to `triggerAction`, or a combination: - - ```javascript - App.SaveButtonView = Ember.View.extend(Ember.TargetActionSupport, { - target: Ember.computed.alias('controller'), - click: function() { - this.triggerAction({ - action: 'save' - }); // Sends the `save` action, along with a reference to `this`, - // to the current controller - } - }); - ``` - - @method triggerAction - @param opts {Hash} (optional, with the optional keys action, target and/or actionContext) - @return {Boolean} true if the action was sent successfully and did not return false - */ - triggerAction: function(opts) { - opts = opts || {}; - var action = opts.action || get(this, 'action'); - var target = opts.target || get(this, 'targetObject'); - var actionContext = opts.actionContext; - - function args(options, actionName) { - var ret = []; - if (actionName) { ret.push(actionName); } - - return ret.concat(options); - } - - if (typeof actionContext === 'undefined') { - actionContext = get(this, 'actionContextObject') || this; - } - - if (target && action) { - var ret; - - if (target.send) { - ret = target.send.apply(target, args(actionContext, action)); - } else { - Ember.assert("The action '" + action + "' did not exist on " + target, typeof target[action] === 'function'); - ret = target[action].apply(target, args(actionContext)); - } - - if (ret !== false) ret = true; - - return ret; - } else { - return false; - } - } - }); - - __exports__["default"] = TargetActionSupport; - }); -enifed("ember-runtime/system/application", - ["ember-runtime/system/namespace","exports"], - function(__dependency1__, __exports__) { - "use strict"; - var Namespace = __dependency1__["default"]; - - __exports__["default"] = Namespace.extend(); - }); -enifed("ember-runtime/system/array_proxy", - ["ember-metal/core","ember-metal/property_get","ember-metal/property_set","ember-metal/utils","ember-metal/computed","ember-metal/mixin","ember-metal/property_events","ember-metal/error","ember-runtime/system/object","ember-runtime/mixins/mutable_array","ember-runtime/mixins/enumerable","ember-runtime/system/string","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __dependency11__, __dependency12__, __exports__) { - "use strict"; - var Ember = __dependency1__["default"]; - // Ember.K, Ember.assert - var get = __dependency2__.get; - var set = __dependency3__.set; - var isArray = __dependency4__.isArray; - var apply = __dependency4__.apply; - var computed = __dependency5__.computed; - var beforeObserver = __dependency6__.beforeObserver; - var observer = __dependency6__.observer; - var beginPropertyChanges = __dependency7__.beginPropertyChanges; - var endPropertyChanges = __dependency7__.endPropertyChanges; - var EmberError = __dependency8__["default"]; - var EmberObject = __dependency9__["default"]; - var MutableArray = __dependency10__["default"]; - var Enumerable = __dependency11__["default"]; - var fmt = __dependency12__.fmt; - - /** - @module ember - @submodule ember-runtime - */ - - var OUT_OF_RANGE_EXCEPTION = "Index out of range"; - var EMPTY = []; - var alias = computed.alias; - var K = Ember.K; - - /** - An ArrayProxy wraps any other object that implements `Ember.Array` and/or - `Ember.MutableArray,` forwarding all requests. This makes it very useful for - a number of binding use cases or other cases where being able to swap - out the underlying array is useful. - - A simple example of usage: - - ```javascript - var pets = ['dog', 'cat', 'fish']; - var ap = Ember.ArrayProxy.create({ content: Ember.A(pets) }); - - ap.get('firstObject'); // 'dog' - ap.set('content', ['amoeba', 'paramecium']); - ap.get('firstObject'); // 'amoeba' - ``` - - This class can also be useful as a layer to transform the contents of - an array, as they are accessed. This can be done by overriding - `objectAtContent`: - - ```javascript - var pets = ['dog', 'cat', 'fish']; - var ap = Ember.ArrayProxy.create({ - content: Ember.A(pets), - objectAtContent: function(idx) { - return this.get('content').objectAt(idx).toUpperCase(); - } - }); - - ap.get('firstObject'); // . 'DOG' - ``` - - @class ArrayProxy - @namespace Ember - @extends Ember.Object - @uses Ember.MutableArray - */ - var ArrayProxy = EmberObject.extend(MutableArray, { - - /** - The content array. Must be an object that implements `Ember.Array` and/or - `Ember.MutableArray.` - - @property content - @type Ember.Array - */ - content: null, - - /** - The array that the proxy pretends to be. In the default `ArrayProxy` - implementation, this and `content` are the same. Subclasses of `ArrayProxy` - can override this property to provide things like sorting and filtering. - - @property arrangedContent - */ - arrangedContent: alias('content'), - - /** - Should actually retrieve the object at the specified index from the - content. You can override this method in subclasses to transform the - content item to something new. - - This method will only be called if content is non-`null`. - - @method objectAtContent - @param {Number} idx The index to retrieve. - @return {Object} the value or undefined if none found - */ - objectAtContent: function(idx) { - return get(this, 'arrangedContent').objectAt(idx); - }, - - /** - Should actually replace the specified objects on the content array. - You can override this method in subclasses to transform the content item - into something new. - - This method will only be called if content is non-`null`. - - @method replaceContent - @param {Number} idx The starting index - @param {Number} amt The number of items to remove from the content. - @param {Array} objects Optional array of objects to insert or null if no - objects. - @return {void} - */ - replaceContent: function(idx, amt, objects) { - get(this, 'content').replace(idx, amt, objects); - }, - - /** - Invoked when the content property is about to change. Notifies observers that the - entire array content will change. - - @private - @method _contentWillChange - */ - _contentWillChange: beforeObserver('content', function() { - this._teardownContent(); - }), - - _teardownContent: function() { - var content = get(this, 'content'); - - if (content) { - content.removeArrayObserver(this, { - willChange: 'contentArrayWillChange', - didChange: 'contentArrayDidChange' - }); - } - }, - - /** - Override to implement content array `willChange` observer. - - @method contentArrayWillChange - - @param {Ember.Array} contentArray the content array - @param {Number} start starting index of the change - @param {Number} removeCount count of items removed - @param {Number} addCount count of items added - - */ - contentArrayWillChange: K, - /** - Override to implement content array `didChange` observer. - - @method contentArrayDidChange - - @param {Ember.Array} contentArray the content array - @param {Number} start starting index of the change - @param {Number} removeCount count of items removed - @param {Number} addCount count of items added - */ - contentArrayDidChange: K, - - /** - Invoked when the content property changes. Notifies observers that the - entire array content has changed. - - @private - @method _contentDidChange - */ - _contentDidChange: observer('content', function() { - var content = get(this, 'content'); - - Ember.assert("Can't set ArrayProxy's content to itself", content !== this); - - this._setupContent(); - }), - - _setupContent: function() { - var content = get(this, 'content'); - - if (content) { - Ember.assert(fmt('ArrayProxy expects an Array or ' + - 'Ember.ArrayProxy, but you passed %@', [typeof content]), - isArray(content) || content.isDestroyed); - - content.addArrayObserver(this, { - willChange: 'contentArrayWillChange', - didChange: 'contentArrayDidChange' - }); - } - }, - - _arrangedContentWillChange: beforeObserver('arrangedContent', function() { - var arrangedContent = get(this, 'arrangedContent'); - var len = arrangedContent ? get(arrangedContent, 'length') : 0; - - this.arrangedContentArrayWillChange(this, 0, len, undefined); - this.arrangedContentWillChange(this); - - this._teardownArrangedContent(arrangedContent); - }), - - _arrangedContentDidChange: observer('arrangedContent', function() { - var arrangedContent = get(this, 'arrangedContent'); - var len = arrangedContent ? get(arrangedContent, 'length') : 0; - - Ember.assert("Can't set ArrayProxy's content to itself", arrangedContent !== this); - - this._setupArrangedContent(); - - this.arrangedContentDidChange(this); - this.arrangedContentArrayDidChange(this, 0, undefined, len); - }), - - _setupArrangedContent: function() { - var arrangedContent = get(this, 'arrangedContent'); - - if (arrangedContent) { - Ember.assert(fmt('ArrayProxy expects an Array or ' + - 'Ember.ArrayProxy, but you passed %@', [typeof arrangedContent]), - isArray(arrangedContent) || arrangedContent.isDestroyed); - - arrangedContent.addArrayObserver(this, { - willChange: 'arrangedContentArrayWillChange', - didChange: 'arrangedContentArrayDidChange' - }); - } - }, - - _teardownArrangedContent: function() { - var arrangedContent = get(this, 'arrangedContent'); - - if (arrangedContent) { - arrangedContent.removeArrayObserver(this, { - willChange: 'arrangedContentArrayWillChange', - didChange: 'arrangedContentArrayDidChange' - }); - } - }, - - arrangedContentWillChange: K, - arrangedContentDidChange: K, - - objectAt: function(idx) { - return get(this, 'content') && this.objectAtContent(idx); - }, - - length: computed(function() { - var arrangedContent = get(this, 'arrangedContent'); - return arrangedContent ? get(arrangedContent, 'length') : 0; - // No dependencies since Enumerable notifies length of change - }), - - _replace: function(idx, amt, objects) { - var content = get(this, 'content'); - Ember.assert('The content property of '+ this.constructor + ' should be set before modifying it', content); - if (content) this.replaceContent(idx, amt, objects); - return this; - }, - - replace: function() { - if (get(this, 'arrangedContent') === get(this, 'content')) { - apply(this, this._replace, arguments); - } else { - throw new EmberError("Using replace on an arranged ArrayProxy is not allowed."); - } - }, - - _insertAt: function(idx, object) { - if (idx > get(this, 'content.length')) throw new EmberError(OUT_OF_RANGE_EXCEPTION); - this._replace(idx, 0, [object]); - return this; - }, - - insertAt: function(idx, object) { - if (get(this, 'arrangedContent') === get(this, 'content')) { - return this._insertAt(idx, object); - } else { - throw new EmberError("Using insertAt on an arranged ArrayProxy is not allowed."); - } - }, - - removeAt: function(start, len) { - if ('number' === typeof start) { - var content = get(this, 'content'); - var arrangedContent = get(this, 'arrangedContent'); - var indices = []; - var i; - - if ((start < 0) || (start >= get(this, 'length'))) { - throw new EmberError(OUT_OF_RANGE_EXCEPTION); - } - - if (len === undefined) len = 1; - - // Get a list of indices in original content to remove - for (i=start; i= 0) { - var baseValue = this[keyName]; - - if (baseValue) { - if ('function' === typeof baseValue.concat) { - value = baseValue.concat(value); - } else { - value = makeArray(baseValue).concat(value); - } - } else { - value = makeArray(value); - } - } - - if (desc) { - desc.set(this, keyName, value); - } else { - if (typeof this.setUnknownProperty === 'function' && !(keyName in this)) { - this.setUnknownProperty(keyName, value); - } else { - - if (hasPropertyAccessors) { - defineProperty(this, keyName, null, value); // setup mandatory setter - } else { - this[keyName] = value; - } - } - } - } - } - } - finishPartial(this, m); - var length = arguments.length; - var args = new Array(length); - for (var x = 0; x < length; x++) { - args[x] = arguments[x]; - } - apply(this, this.init, args); - m.proto = proto; - finishChains(this); - sendEvent(this, "init"); - }; - - Class.toString = Mixin.prototype.toString; - Class.willReopen = function() { - if (wasApplied) { - Class.PrototypeMixin = Mixin.create(Class.PrototypeMixin); - } - - wasApplied = false; - }; - Class._initMixins = function(args) { initMixins = args; }; - Class._initProperties = function(args) { initProperties = args; }; - - Class.proto = function() { - var superclass = Class.superclass; - if (superclass) { superclass.proto(); } - - if (!wasApplied) { - wasApplied = true; - Class.PrototypeMixin.applyPartial(Class.prototype); - rewatch(Class.prototype); - } - - return this.prototype; - }; - - return Class; - - } - - /** - @class CoreObject - @namespace Ember - */ - var CoreObject = makeCtor(); - CoreObject.toString = function() { return "Ember.CoreObject"; }; - CoreObject.PrototypeMixin = Mixin.create({ - reopen: function() { - var length = arguments.length; - var args = new Array(length); - for (var i = 0; i < length; i++) { - args[i] = arguments[i]; - } - applyMixin(this, args, true); - return this; - }, - - /** - An overridable method called when objects are instantiated. By default, - does nothing unless it is overridden during class definition. - - Example: - - ```javascript - App.Person = Ember.Object.extend({ - init: function() { - alert('Name is ' + this.get('name')); - } - }); - - var steve = App.Person.create({ - name: "Steve" - }); - - // alerts 'Name is Steve'. - ``` - - NOTE: If you do override `init` for a framework class like `Ember.View` or - `Ember.ArrayController`, be sure to call `this._super()` in your - `init` declaration! If you don't, Ember may not have an opportunity to - do important setup work, and you'll see strange behavior in your - application. - - @method init - */ - init: function() {}, - - /** - Defines the properties that will be concatenated from the superclass - (instead of overridden). - - By default, when you extend an Ember class a property defined in - the subclass overrides a property with the same name that is defined - in the superclass. However, there are some cases where it is preferable - to build up a property's value by combining the superclass' property - value with the subclass' value. An example of this in use within Ember - is the `classNames` property of `Ember.View`. - - Here is some sample code showing the difference between a concatenated - property and a normal one: - - ```javascript - App.BarView = Ember.View.extend({ - someNonConcatenatedProperty: ['bar'], - classNames: ['bar'] - }); - - App.FooBarView = App.BarView.extend({ - someNonConcatenatedProperty: ['foo'], - classNames: ['foo'] - }); - - var fooBarView = App.FooBarView.create(); - fooBarView.get('someNonConcatenatedProperty'); // ['foo'] - fooBarView.get('classNames'); // ['ember-view', 'bar', 'foo'] - ``` - - This behavior extends to object creation as well. Continuing the - above example: - - ```javascript - var view = App.FooBarView.create({ - someNonConcatenatedProperty: ['baz'], - classNames: ['baz'] - }) - view.get('someNonConcatenatedProperty'); // ['baz'] - view.get('classNames'); // ['ember-view', 'bar', 'foo', 'baz'] - ``` - Adding a single property that is not an array will just add it in the array: - - ```javascript - var view = App.FooBarView.create({ - classNames: 'baz' - }) - view.get('classNames'); // ['ember-view', 'bar', 'foo', 'baz'] - ``` - - Using the `concatenatedProperties` property, we can tell to Ember that mix - the content of the properties. - - In `Ember.View` the `classNameBindings` and `attributeBindings` properties - are also concatenated, in addition to `classNames`. - - This feature is available for you to use throughout the Ember object model, - although typical app developers are likely to use it infrequently. Since - it changes expectations about behavior of properties, you should properly - document its usage in each individual concatenated property (to not - mislead your users to think they can override the property in a subclass). - - @property concatenatedProperties - @type Array - @default null - */ - concatenatedProperties: null, - - /** - Destroyed object property flag. - - if this property is `true` the observers and bindings were already - removed by the effect of calling the `destroy()` method. - - @property isDestroyed - @default false - */ - isDestroyed: false, - - /** - Destruction scheduled flag. The `destroy()` method has been called. - - The object stays intact until the end of the run loop at which point - the `isDestroyed` flag is set. - - @property isDestroying - @default false - */ - isDestroying: false, - - /** - Destroys an object by setting the `isDestroyed` flag and removing its - metadata, which effectively destroys observers and bindings. - - If you try to set a property on a destroyed object, an exception will be - raised. - - Note that destruction is scheduled for the end of the run loop and does not - happen immediately. It will set an isDestroying flag immediately. - - @method destroy - @return {Ember.Object} receiver - */ - destroy: function() { - if (this.isDestroying) { return; } - this.isDestroying = true; - - schedule('actions', this, this.willDestroy); - schedule('destroy', this, this._scheduledDestroy); - return this; - }, - - /** - Override to implement teardown. - - @method willDestroy - */ - willDestroy: K, - - /** - Invoked by the run loop to actually destroy the object. This is - scheduled for execution by the `destroy` method. - - @private - @method _scheduledDestroy - */ - _scheduledDestroy: function() { - if (this.isDestroyed) { return; } - destroy(this); - this.isDestroyed = true; - }, - - bind: function(to, from) { - if (!(from instanceof Binding)) { from = Binding.from(from); } - from.to(to).connect(this); - return from; - }, - - /** - Returns a string representation which attempts to provide more information - than Javascript's `toString` typically does, in a generic way for all Ember - objects. - - ```javascript - App.Person = Em.Object.extend() - person = App.Person.create() - person.toString() //=> "" - ``` - - If the object's class is not defined on an Ember namespace, it will - indicate it is a subclass of the registered superclass: - - ```javascript - Student = App.Person.extend() - student = Student.create() - student.toString() //=> "<(subclass of App.Person):ember1025>" - ``` - - If the method `toStringExtension` is defined, its return value will be - included in the output. - - ```javascript - App.Teacher = App.Person.extend({ - toStringExtension: function() { - return this.get('fullName'); - } - }); - teacher = App.Teacher.create() - teacher.toString(); //=> "" - ``` - - @method toString - @return {String} string representation - */ - toString: function toString() { - var hasToStringExtension = typeof this.toStringExtension === 'function'; - var extension = hasToStringExtension ? ":" + this.toStringExtension() : ''; - var ret = '<'+this.constructor.toString()+':'+guidFor(this)+extension+'>'; - - this.toString = makeToString(ret); - return ret; - } - }); - - CoreObject.PrototypeMixin.ownerConstructor = CoreObject; - - function makeToString(ret) { - return function() { return ret; }; - } - - if (Ember.config.overridePrototypeMixin) { - Ember.config.overridePrototypeMixin(CoreObject.PrototypeMixin); - } - - CoreObject.__super__ = null; - - var ClassMixin = Mixin.create({ - - ClassMixin: required(), - - PrototypeMixin: required(), - - isClass: true, - - isMethod: false, - - /** - Creates a new subclass. - - ```javascript - App.Person = Ember.Object.extend({ - say: function(thing) { - alert(thing); - } - }); - ``` - - This defines a new subclass of Ember.Object: `App.Person`. It contains one method: `say()`. - - You can also create a subclass from any existing class by calling its `extend()` method. For example, you might want to create a subclass of Ember's built-in `Ember.View` class: - - ```javascript - App.PersonView = Ember.View.extend({ - tagName: 'li', - classNameBindings: ['isAdministrator'] - }); - ``` - - When defining a subclass, you can override methods but still access the implementation of your parent class by calling the special `_super()` method: - - ```javascript - App.Person = Ember.Object.extend({ - say: function(thing) { - var name = this.get('name'); - alert(name + ' says: ' + thing); - } - }); - - App.Soldier = App.Person.extend({ - say: function(thing) { - this._super(thing + ", sir!"); - }, - march: function(numberOfHours) { - alert(this.get('name') + ' marches for ' + numberOfHours + ' hours.') - } - }); - - var yehuda = App.Soldier.create({ - name: "Yehuda Katz" - }); - - yehuda.say("Yes"); // alerts "Yehuda Katz says: Yes, sir!" - ``` - - The `create()` on line #17 creates an *instance* of the `App.Soldier` class. The `extend()` on line #8 creates a *subclass* of `App.Person`. Any instance of the `App.Person` class will *not* have the `march()` method. - - You can also pass `Mixin` classes to add additional properties to the subclass. - - ```javascript - App.Person = Ember.Object.extend({ - say: function(thing) { - alert(this.get('name') + ' says: ' + thing); - } - }); - - App.SingingMixin = Mixin.create({ - sing: function(thing){ - alert(this.get('name') + ' sings: la la la ' + thing); - } - }); - - App.BroadwayStar = App.Person.extend(App.SingingMixin, { - dance: function() { - alert(this.get('name') + ' dances: tap tap tap tap '); - } - }); - ``` - - The `App.BroadwayStar` class contains three methods: `say()`, `sing()`, and `dance()`. - - @method extend - @static - - @param {Mixin} [mixins]* One or more Mixin classes - @param {Object} [arguments]* Object containing values to use within the new class - */ - extend: function extend() { - var Class = makeCtor(); - var proto; - Class.ClassMixin = Mixin.create(this.ClassMixin); - Class.PrototypeMixin = Mixin.create(this.PrototypeMixin); - - Class.ClassMixin.ownerConstructor = Class; - Class.PrototypeMixin.ownerConstructor = Class; - - reopen.apply(Class.PrototypeMixin, arguments); - - Class.superclass = this; - Class.__super__ = this.prototype; - - proto = Class.prototype = o_create(this.prototype); - proto.constructor = Class; - generateGuid(proto); - meta(proto).proto = proto; // this will disable observers on prototype - - Class.ClassMixin.apply(Class); - return Class; - }, - - /** - Equivalent to doing `extend(arguments).create()`. - If possible use the normal `create` method instead. - - @method createWithMixins - @static - @param [arguments]* - */ - createWithMixins: function() { - var C = this; - var l= arguments.length; - if (l > 0) { - var args = new Array(l); - for (var i = 0; i < l; i++) { - args[i] = arguments[i]; - } - this._initMixins(args); - } - return new C(); - }, - - /** - Creates an instance of a class. Accepts either no arguments, or an object - containing values to initialize the newly instantiated object with. - - ```javascript - App.Person = Ember.Object.extend({ - helloWorld: function() { - alert("Hi, my name is " + this.get('name')); - } - }); - - var tom = App.Person.create({ - name: 'Tom Dale' - }); - - tom.helloWorld(); // alerts "Hi, my name is Tom Dale". - ``` - - `create` will call the `init` function if defined during - `Ember.AnyObject.extend` - - If no arguments are passed to `create`, it will not set values to the new - instance during initialization: - - ```javascript - var noName = App.Person.create(); - noName.helloWorld(); // alerts undefined - ``` - - NOTE: For performance reasons, you cannot declare methods or computed - properties during `create`. You should instead declare methods and computed - properties when using `extend` or use the `createWithMixins` shorthand. - - @method create - @static - @param [arguments]* - */ - create: function() { - var C = this; - var l = arguments.length; - if (l > 0) { - var args = new Array(l); - for (var i = 0; i < l; i++) { - args[i] = arguments[i]; - } - this._initProperties(args); - } - return new C(); - }, - - /** - Augments a constructor's prototype with additional - properties and functions: - - ```javascript - MyObject = Ember.Object.extend({ - name: 'an object' - }); - - o = MyObject.create(); - o.get('name'); // 'an object' - - MyObject.reopen({ - say: function(msg){ - console.log(msg); - } - }) - - o2 = MyObject.create(); - o2.say("hello"); // logs "hello" - - o.say("goodbye"); // logs "goodbye" - ``` - - To add functions and properties to the constructor itself, - see `reopenClass` - - @method reopen - */ - reopen: function() { - this.willReopen(); - - var l = arguments.length; - var args = new Array(l); - if (l > 0) { - for (var i = 0; i < l; i++) { - args[i] = arguments[i]; - } - } - - apply(this.PrototypeMixin, reopen, args); - return this; - }, - - /** - Augments a constructor's own properties and functions: - - ```javascript - MyObject = Ember.Object.extend({ - name: 'an object' - }); - - MyObject.reopenClass({ - canBuild: false - }); - - MyObject.canBuild; // false - o = MyObject.create(); - ``` - - In other words, this creates static properties and functions for the class. These are only available on the class - and not on any instance of that class. - - ```javascript - App.Person = Ember.Object.extend({ - name : "", - sayHello : function(){ - alert("Hello. My name is " + this.get('name')); - } - }); - - App.Person.reopenClass({ - species : "Homo sapiens", - createPerson: function(newPersonsName){ - return App.Person.create({ - name:newPersonsName - }); - } - }); - - var tom = App.Person.create({ - name : "Tom Dale" - }); - var yehuda = App.Person.createPerson("Yehuda Katz"); - - tom.sayHello(); // "Hello. My name is Tom Dale" - yehuda.sayHello(); // "Hello. My name is Yehuda Katz" - alert(App.Person.species); // "Homo sapiens" - ``` - - Note that `species` and `createPerson` are *not* valid on the `tom` and `yehuda` - variables. They are only valid on `App.Person`. - - To add functions and properties to instances of - a constructor by extending the constructor's prototype - see `reopen` - - @method reopenClass - */ - reopenClass: function() { - var l = arguments.length; - var args = new Array(l); - if (l > 0) { - for (var i = 0; i < l; i++) { - args[i] = arguments[i]; - } - } - - apply(this.ClassMixin, reopen, args); - applyMixin(this, arguments, false); - return this; - }, - - detect: function(obj) { - if ('function' !== typeof obj) { return false; } - while(obj) { - if (obj===this) { return true; } - obj = obj.superclass; - } - return false; - }, - - detectInstance: function(obj) { - return obj instanceof this; - }, - - /** - In some cases, you may want to annotate computed properties with additional - metadata about how they function or what values they operate on. For - example, computed property functions may close over variables that are then - no longer available for introspection. - - You can pass a hash of these values to a computed property like this: - - ```javascript - person: function() { - var personId = this.get('personId'); - return App.Person.create({ id: personId }); - }.property().meta({ type: App.Person }) - ``` - - Once you've done this, you can retrieve the values saved to the computed - property from your class like this: - - ```javascript - MyClass.metaForProperty('person'); - ``` - - This will return the original hash that was passed to `meta()`. - - @method metaForProperty - @param key {String} property name - */ - metaForProperty: function(key) { - var meta = this.proto()['__ember_meta__']; - var desc = meta && meta.descs[key]; - - Ember.assert("metaForProperty() could not find a computed property with key '"+key+"'.", !!desc && desc instanceof ComputedProperty); - return desc._meta || {}; - }, - - _computedProperties: Ember.computed(function() { - hasCachedComputedProperties = true; - var proto = this.proto(); - var descs = meta(proto).descs; - var property; - var properties = []; - - for (var name in descs) { - property = descs[name]; - - if (property instanceof ComputedProperty) { - properties.push({ - name: name, - meta: property._meta - }); - } - } - return properties; - }).readOnly(), - - /** - Iterate over each computed property for the class, passing its name - and any associated metadata (see `metaForProperty`) to the callback. - - @method eachComputedProperty - @param {Function} callback - @param {Object} binding - */ - eachComputedProperty: function(callback, binding) { - var property, name; - var empty = {}; - - var properties = get(this, '_computedProperties'); - - for (var i = 0, length = properties.length; i < length; i++) { - property = properties[i]; - name = property.name; - callback.call(binding || this, property.name, property.meta || empty); - } - } - }); - - ClassMixin.ownerConstructor = CoreObject; - - if (Ember.config.overrideClassMixin) { - Ember.config.overrideClassMixin(ClassMixin); - } - - CoreObject.ClassMixin = ClassMixin; - - ClassMixin.apply(CoreObject); - - CoreObject.reopen({ - didDefineProperty: function(proto, key, value) { - if (hasCachedComputedProperties === false) { return; } - if (value instanceof Ember.ComputedProperty) { - var cache = Ember.meta(this.constructor).cache; - - if (cache._computedProperties !== undefined) { - cache._computedProperties = undefined; - } - } - } - }); - - __exports__["default"] = CoreObject; - }); -enifed("ember-runtime/system/deferred", - ["ember-metal/core","ember-runtime/mixins/deferred","ember-metal/property_get","ember-runtime/system/object","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __exports__) { - "use strict"; - var Ember = __dependency1__["default"]; - var DeferredMixin = __dependency2__["default"]; - var get = __dependency3__.get; - var EmberObject = __dependency4__["default"]; - - var Deferred = EmberObject.extend(DeferredMixin, { - init: function() { - Ember.deprecate('Usage of Ember.Deferred is deprecated.'); - this._super(); - } - }); - - Deferred.reopenClass({ - promise: function(callback, binding) { - var deferred = Deferred.create(); - callback.call(binding, deferred); - return deferred; - } - }); - - __exports__["default"] = Deferred; - }); -enifed("ember-runtime/system/each_proxy", - ["ember-metal/core","ember-metal/property_get","ember-metal/property_set","ember-metal/utils","ember-metal/enumerable_utils","ember-metal/array","ember-runtime/mixins/array","ember-runtime/system/object","ember-metal/computed","ember-metal/observer","ember-metal/events","ember-metal/properties","ember-metal/property_events","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __dependency11__, __dependency12__, __dependency13__, __exports__) { - "use strict"; - /** - @module ember - @submodule ember-runtime - */ - - var Ember = __dependency1__["default"]; - // Ember.assert - - var get = __dependency2__.get; - var set = __dependency3__.set; - var guidFor = __dependency4__.guidFor; - var forEach = __dependency5__.forEach; - var indexOf = __dependency6__.indexOf; - var EmberArray = __dependency7__["default"]; - // ES6TODO: WAT? Circular dep? - var EmberObject = __dependency8__["default"]; - var computed = __dependency9__.computed; - var addObserver = __dependency10__.addObserver; - var addBeforeObserver = __dependency10__.addBeforeObserver; - var removeBeforeObserver = __dependency10__.removeBeforeObserver; - var removeObserver = __dependency10__.removeObserver; - var typeOf = __dependency4__.typeOf; - var watchedEvents = __dependency11__.watchedEvents; - var defineProperty = __dependency12__.defineProperty; - var beginPropertyChanges = __dependency13__.beginPropertyChanges; - var propertyDidChange = __dependency13__.propertyDidChange; - var propertyWillChange = __dependency13__.propertyWillChange; - var endPropertyChanges = __dependency13__.endPropertyChanges; - var changeProperties = __dependency13__.changeProperties; - - var EachArray = EmberObject.extend(EmberArray, { - - init: function(content, keyName, owner) { - this._super(); - this._keyName = keyName; - this._owner = owner; - this._content = content; - }, - - objectAt: function(idx) { - var item = this._content.objectAt(idx); - return item && get(item, this._keyName); - }, - - length: computed(function() { - var content = this._content; - return content ? get(content, 'length') : 0; - }) - - }); - - var IS_OBSERVER = /^.+:(before|change)$/; - - function addObserverForContentKey(content, keyName, proxy, idx, loc) { - var objects = proxy._objects; - var guid; - if (!objects) objects = proxy._objects = {}; - - while(--loc>=idx) { - var item = content.objectAt(loc); - if (item) { - Ember.assert('When using @each to observe the array ' + content + ', the array must return an object', typeOf(item) === 'instance' || typeOf(item) === 'object'); - addBeforeObserver(item, keyName, proxy, 'contentKeyWillChange'); - addObserver(item, keyName, proxy, 'contentKeyDidChange'); - - // keep track of the index each item was found at so we can map - // it back when the obj changes. - guid = guidFor(item); - if (!objects[guid]) objects[guid] = []; - objects[guid].push(loc); - } - } - } - - function removeObserverForContentKey(content, keyName, proxy, idx, loc) { - var objects = proxy._objects; - if (!objects) objects = proxy._objects = {}; - var indicies, guid; - - while(--loc>=idx) { - var item = content.objectAt(loc); - if (item) { - removeBeforeObserver(item, keyName, proxy, 'contentKeyWillChange'); - removeObserver(item, keyName, proxy, 'contentKeyDidChange'); - - guid = guidFor(item); - indicies = objects[guid]; - indicies[indexOf.call(indicies, loc)] = null; - } - } - } - - /** - This is the object instance returned when you get the `@each` property on an - array. It uses the unknownProperty handler to automatically create - EachArray instances for property names. - - @private - @class EachProxy - @namespace Ember - @extends Ember.Object - */ - var EachProxy = EmberObject.extend({ - - init: function(content) { - this._super(); - this._content = content; - content.addArrayObserver(this); - - // in case someone is already observing some keys make sure they are - // added - forEach(watchedEvents(this), function(eventName) { - this.didAddListener(eventName); - }, this); - }, - - /** - You can directly access mapped properties by simply requesting them. - The `unknownProperty` handler will generate an EachArray of each item. - - @method unknownProperty - @param keyName {String} - @param value {*} - */ - unknownProperty: function(keyName, value) { - var ret; - ret = new EachArray(this._content, keyName, this); - defineProperty(this, keyName, null, ret); - this.beginObservingContentKey(keyName); - return ret; - }, - - // .......................................................... - // ARRAY CHANGES - // Invokes whenever the content array itself changes. - - arrayWillChange: function(content, idx, removedCnt, addedCnt) { - var keys = this._keys; - var key, lim; - - lim = removedCnt>0 ? idx+removedCnt : -1; - beginPropertyChanges(this); - - for(key in keys) { - if (!keys.hasOwnProperty(key)) { continue; } - - if (lim>0) { removeObserverForContentKey(content, key, this, idx, lim); } - - propertyWillChange(this, key); - } - - propertyWillChange(this._content, '@each'); - endPropertyChanges(this); - }, - - arrayDidChange: function(content, idx, removedCnt, addedCnt) { - var keys = this._keys; - var lim; - - lim = addedCnt>0 ? idx+addedCnt : -1; - changeProperties(function() { - for(var key in keys) { - if (!keys.hasOwnProperty(key)) { continue; } - - if (lim>0) { addObserverForContentKey(content, key, this, idx, lim); } - - propertyDidChange(this, key); - } - - propertyDidChange(this._content, '@each'); - }, this); - }, - - // .......................................................... - // LISTEN FOR NEW OBSERVERS AND OTHER EVENT LISTENERS - // Start monitoring keys based on who is listening... - - didAddListener: function(eventName) { - if (IS_OBSERVER.test(eventName)) { - this.beginObservingContentKey(eventName.slice(0, -7)); - } - }, - - didRemoveListener: function(eventName) { - if (IS_OBSERVER.test(eventName)) { - this.stopObservingContentKey(eventName.slice(0, -7)); - } - }, - - // .......................................................... - // CONTENT KEY OBSERVING - // Actual watch keys on the source content. - - beginObservingContentKey: function(keyName) { - var keys = this._keys; - if (!keys) keys = this._keys = {}; - if (!keys[keyName]) { - keys[keyName] = 1; - var content = this._content; - var len = get(content, 'length'); - - addObserverForContentKey(content, keyName, this, 0, len); - } else { - keys[keyName]++; - } - }, - - stopObservingContentKey: function(keyName) { - var keys = this._keys; - if (keys && (keys[keyName]>0) && (--keys[keyName]<=0)) { - var content = this._content; - var len = get(content, 'length'); - - removeObserverForContentKey(content, keyName, this, 0, len); - } - }, - - contentKeyWillChange: function(obj, keyName) { - propertyWillChange(this, keyName); - }, - - contentKeyDidChange: function(obj, keyName) { - propertyDidChange(this, keyName); - } - }); - - __exports__.EachArray = EachArray; - __exports__.EachProxy = EachProxy; - }); -enifed("ember-runtime/system/lazy_load", - ["ember-metal/core","ember-metal/array","ember-runtime/system/native_array","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __exports__) { - "use strict"; - /*globals CustomEvent */ - - var Ember = __dependency1__["default"]; - // Ember.ENV.EMBER_LOAD_HOOKS - var forEach = __dependency2__.forEach; - // make sure Ember.A is setup. - - /** - @module ember - @submodule ember-runtime - */ - - var loadHooks = Ember.ENV.EMBER_LOAD_HOOKS || {}; - var loaded = {}; - - /** - Detects when a specific package of Ember (e.g. 'Ember.Handlebars') - has fully loaded and is available for extension. - - The provided `callback` will be called with the `name` passed - resolved from a string into the object: - - ``` javascript - Ember.onLoad('Ember.Handlebars' function(hbars) { - hbars.registerHelper(...); - }); - ``` - - @method onLoad - @for Ember - @param name {String} name of hook - @param callback {Function} callback to be called - */ - function onLoad(name, callback) { - var object; - - loadHooks[name] = loadHooks[name] || Ember.A(); - loadHooks[name].pushObject(callback); - - if (object = loaded[name]) { - callback(object); - } - } - - __exports__.onLoad = onLoad;/** - Called when an Ember.js package (e.g Ember.Handlebars) has finished - loading. Triggers any callbacks registered for this event. - - @method runLoadHooks - @for Ember - @param name {String} name of hook - @param object {Object} object to pass to callbacks - */ - function runLoadHooks(name, object) { - loaded[name] = object; - - if (typeof window === 'object' && typeof window.dispatchEvent === 'function' && typeof CustomEvent === "function") { - var event = new CustomEvent(name, {detail: object, name: name}); - window.dispatchEvent(event); - } - - if (loadHooks[name]) { - forEach.call(loadHooks[name], function(callback) { - callback(object); - }); - } - } - - __exports__.runLoadHooks = runLoadHooks; - }); -enifed("ember-runtime/system/namespace", - ["ember-metal/core","ember-metal/property_get","ember-metal/array","ember-metal/utils","ember-metal/mixin","ember-runtime/system/object","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __exports__) { - "use strict"; - /** - @module ember - @submodule ember-runtime - */ - - // Ember.lookup, Ember.BOOTED, Ember.deprecate, Ember.NAME_KEY, Ember.anyUnprocessedMixins - var Ember = __dependency1__["default"]; - var get = __dependency2__.get; - var indexOf = __dependency3__.indexOf; - var GUID_KEY = __dependency4__.GUID_KEY; - var guidFor = __dependency4__.guidFor; - var Mixin = __dependency5__.Mixin; - - var EmberObject = __dependency6__["default"]; - - /** - A Namespace is an object usually used to contain other objects or methods - such as an application or framework. Create a namespace anytime you want - to define one of these new containers. - - # Example Usage - - ```javascript - MyFramework = Ember.Namespace.create({ - VERSION: '1.0.0' - }); - ``` - - @class Namespace - @namespace Ember - @extends Ember.Object - */ - var Namespace = EmberObject.extend({ - isNamespace: true, - - init: function() { - Namespace.NAMESPACES.push(this); - Namespace.PROCESSED = false; - }, - - toString: function() { - var name = get(this, 'name') || get(this, 'modulePrefix'); - if (name) { return name; } - - findNamespaces(); - return this[NAME_KEY]; - }, - - nameClasses: function() { - processNamespace([this.toString()], this, {}); - }, - - destroy: function() { - var namespaces = Namespace.NAMESPACES; - var toString = this.toString(); - - if (toString) { - Ember.lookup[toString] = undefined; - delete Namespace.NAMESPACES_BY_ID[toString]; - } - namespaces.splice(indexOf.call(namespaces, this), 1); - this._super(); - } - }); - - Namespace.reopenClass({ - NAMESPACES: [Ember], - NAMESPACES_BY_ID: {}, - PROCESSED: false, - processAll: processAllNamespaces, - byName: function(name) { - if (!Ember.BOOTED) { - processAllNamespaces(); - } - - return NAMESPACES_BY_ID[name]; - } - }); - - var NAMESPACES_BY_ID = Namespace.NAMESPACES_BY_ID; - - var hasOwnProp = ({}).hasOwnProperty; - - function processNamespace(paths, root, seen) { - var idx = paths.length; - - NAMESPACES_BY_ID[paths.join('.')] = root; - - // Loop over all of the keys in the namespace, looking for classes - for(var key in root) { - if (!hasOwnProp.call(root, key)) { continue; } - var obj = root[key]; - - // If we are processing the `Ember` namespace, for example, the - // `paths` will start with `["Ember"]`. Every iteration through - // the loop will update the **second** element of this list with - // the key, so processing `Ember.View` will make the Array - // `['Ember', 'View']`. - paths[idx] = key; - - // If we have found an unprocessed class - if (obj && obj.toString === classToString) { - // Replace the class' `toString` with the dot-separated path - // and set its `NAME_KEY` - obj.toString = makeToString(paths.join('.')); - obj[NAME_KEY] = paths.join('.'); - - // Support nested namespaces - } else if (obj && obj.isNamespace) { - // Skip aliased namespaces - if (seen[guidFor(obj)]) { continue; } - seen[guidFor(obj)] = true; - - // Process the child namespace - processNamespace(paths, obj, seen); - } - } - - paths.length = idx; // cut out last item - } - - var STARTS_WITH_UPPERCASE = /^[A-Z]/; - - function tryIsNamespace(lookup, prop) { - try { - var obj = lookup[prop]; - return obj && obj.isNamespace && obj; - } catch (e) { - // continue - } - } - - function findNamespaces() { - var lookup = Ember.lookup; - var obj, isNamespace; - - if (Namespace.PROCESSED) { return; } - - for (var prop in lookup) { - // Only process entities that start with uppercase A-Z - if (!STARTS_WITH_UPPERCASE.test(prop)) { continue; } - - // Unfortunately, some versions of IE don't support window.hasOwnProperty - if (lookup.hasOwnProperty && !lookup.hasOwnProperty(prop)) { continue; } - - // At times we are not allowed to access certain properties for security reasons. - // There are also times where even if we can access them, we are not allowed to access their properties. - obj = tryIsNamespace(lookup, prop); - if (obj) { - obj[NAME_KEY] = prop; - } - } - } - - var NAME_KEY = Ember.NAME_KEY = GUID_KEY + '_name'; - - function superClassString(mixin) { - var superclass = mixin.superclass; - if (superclass) { - if (superclass[NAME_KEY]) { return superclass[NAME_KEY]; } - else { return superClassString(superclass); } - } else { - return; - } - } - - function classToString() { - if (!Ember.BOOTED && !this[NAME_KEY]) { - processAllNamespaces(); - } - - var ret; - - if (this[NAME_KEY]) { - ret = this[NAME_KEY]; - } else if (this._toString) { - ret = this._toString; - } else { - var str = superClassString(this); - if (str) { - ret = "(subclass of " + str + ")"; - } else { - ret = "(unknown mixin)"; - } - this.toString = makeToString(ret); - } - - return ret; - } - - function processAllNamespaces() { - var unprocessedNamespaces = !Namespace.PROCESSED; - var unprocessedMixins = Ember.anyUnprocessedMixins; - - if (unprocessedNamespaces) { - findNamespaces(); - Namespace.PROCESSED = true; - } - - if (unprocessedNamespaces || unprocessedMixins) { - var namespaces = Namespace.NAMESPACES; - var namespace; - - for (var i=0, l=namespaces.length; i 0) { - NativeArray = NativeArray.without.apply(NativeArray, ignore); - } - - /** - Creates an `Ember.NativeArray` from an Array like object. - Does not modify the original object. Ember.A is not needed if - `Ember.EXTEND_PROTOTYPES` is `true` (the default value). However, - it is recommended that you use Ember.A when creating addons for - ember or when you can not guarantee that `Ember.EXTEND_PROTOTYPES` - will be `true`. - - Example - - ```js - var Pagination = Ember.CollectionView.extend({ - tagName: 'ul', - classNames: ['pagination'], - - init: function() { - this._super(); - if (!this.get('content')) { - this.set('content', Ember.A()); - } - } - }); - ``` - - @method A - @for Ember - @return {Ember.NativeArray} - */ - var A = function(arr) { - if (arr === undefined) { arr = []; } - return EmberArray.detect(arr) ? arr : NativeArray.apply(arr); - }; - - /** - Activates the mixin on the Array.prototype if not already applied. Calling - this method more than once is safe. This will be called when ember is loaded - unless you have `Ember.EXTEND_PROTOTYPES` or `Ember.EXTEND_PROTOTYPES.Array` - set to `false`. - - Example - - ```js - if (Ember.EXTEND_PROTOTYPES === true || Ember.EXTEND_PROTOTYPES.Array) { - Ember.NativeArray.activate(); - } - ``` - - @method activate - @for Ember.NativeArray - @static - @return {void} - */ - NativeArray.activate = function() { - NativeArray.apply(Array.prototype); - - A = function(arr) { return arr || []; }; - }; - - if (Ember.EXTEND_PROTOTYPES === true || Ember.EXTEND_PROTOTYPES.Array) { - NativeArray.activate(); - } - - Ember.A = A; // ES6TODO: Setting A onto the object returned by ember-metal/core to avoid circles - __exports__.A = A; - __exports__.NativeArray = NativeArray; - __exports__["default"] = NativeArray; - }); -enifed("ember-runtime/system/object", - ["ember-runtime/system/core_object","ember-runtime/mixins/observable","exports"], - function(__dependency1__, __dependency2__, __exports__) { - "use strict"; - /** - @module ember - @submodule ember-runtime - */ - - var CoreObject = __dependency1__["default"]; - var Observable = __dependency2__["default"]; - - /** - `Ember.Object` is the main base class for all Ember objects. It is a subclass - of `Ember.CoreObject` with the `Ember.Observable` mixin applied. For details, - see the documentation for each of these. - - @class Object - @namespace Ember - @extends Ember.CoreObject - @uses Ember.Observable - */ - var EmberObject = CoreObject.extend(Observable); - EmberObject.toString = function() { - return "Ember.Object"; - }; - - __exports__["default"] = EmberObject; - }); -enifed("ember-runtime/system/object_proxy", - ["ember-runtime/system/object","ember-runtime/mixins/-proxy","exports"], - function(__dependency1__, __dependency2__, __exports__) { - "use strict"; - var EmberObject = __dependency1__["default"]; - var _ProxyMixin = __dependency2__["default"]; - - /** - `Ember.ObjectProxy` forwards all properties not defined by the proxy itself - to a proxied `content` object. - - ```javascript - object = Ember.Object.create({ - name: 'Foo' - }); - - proxy = Ember.ObjectProxy.create({ - content: object - }); - - // Access and change existing properties - proxy.get('name') // 'Foo' - proxy.set('name', 'Bar'); - object.get('name') // 'Bar' - - // Create new 'description' property on `object` - proxy.set('description', 'Foo is a whizboo baz'); - object.get('description') // 'Foo is a whizboo baz' - ``` - - While `content` is unset, setting a property to be delegated will throw an - Error. - - ```javascript - proxy = Ember.ObjectProxy.create({ - content: null, - flag: null - }); - proxy.set('flag', true); - proxy.get('flag'); // true - proxy.get('foo'); // undefined - proxy.set('foo', 'data'); // throws Error - ``` - - Delegated properties can be bound to and will change when content is updated. - - Computed properties on the proxy itself can depend on delegated properties. - - ```javascript - ProxyWithComputedProperty = Ember.ObjectProxy.extend({ - fullName: function () { - var firstName = this.get('firstName'), - lastName = this.get('lastName'); - if (firstName && lastName) { - return firstName + ' ' + lastName; - } - return firstName || lastName; - }.property('firstName', 'lastName') - }); - - proxy = ProxyWithComputedProperty.create(); - - proxy.get('fullName'); // undefined - proxy.set('content', { - firstName: 'Tom', lastName: 'Dale' - }); // triggers property change for fullName on proxy - - proxy.get('fullName'); // 'Tom Dale' - ``` - - @class ObjectProxy - @namespace Ember - @extends Ember.Object - @extends Ember._ProxyMixin - */ - - __exports__["default"] = EmberObject.extend(_ProxyMixin); - }); -enifed("ember-runtime/system/set", - ["ember-metal/core","ember-metal/property_get","ember-metal/property_set","ember-metal/utils","ember-metal/is_none","ember-runtime/system/string","ember-runtime/system/core_object","ember-runtime/mixins/mutable_enumerable","ember-runtime/mixins/enumerable","ember-runtime/mixins/copyable","ember-runtime/mixins/freezable","ember-metal/error","ember-metal/property_events","ember-metal/mixin","ember-metal/computed","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __dependency11__, __dependency12__, __dependency13__, __dependency14__, __dependency15__, __exports__) { - "use strict"; - /** - @module ember - @submodule ember-runtime - */ - var Ember = __dependency1__["default"]; - // Ember.isNone, Ember.A - - var get = __dependency2__.get; - var set = __dependency3__.set; - var guidFor = __dependency4__.guidFor; - var isNone = __dependency5__.isNone; - var fmt = __dependency6__.fmt; - var CoreObject = __dependency7__["default"]; - var MutableEnumerable = __dependency8__["default"]; - var Enumerable = __dependency9__["default"]; - var Copyable = __dependency10__["default"]; - var Freezable = __dependency11__.Freezable; - var FROZEN_ERROR = __dependency11__.FROZEN_ERROR; - var EmberError = __dependency12__["default"]; - var propertyWillChange = __dependency13__.propertyWillChange; - var propertyDidChange = __dependency13__.propertyDidChange; - var aliasMethod = __dependency14__.aliasMethod; - var computed = __dependency15__.computed; - - /** - An unordered collection of objects. - - A Set works a bit like an array except that its items are not ordered. You - can create a set to efficiently test for membership for an object. You can - also iterate through a set just like an array, even accessing objects by - index, however there is no guarantee as to their order. - - All Sets are observable via the Enumerable Observer API - which works - on any enumerable object including both Sets and Arrays. - - ## Creating a Set - - You can create a set like you would most objects using - `new Ember.Set()`. Most new sets you create will be empty, but you can - also initialize the set with some content by passing an array or other - enumerable of objects to the constructor. - - Finally, you can pass in an existing set and the set will be copied. You - can also create a copy of a set by calling `Ember.Set#copy()`. - - ```javascript - // creates a new empty set - var foundNames = new Ember.Set(); - - // creates a set with four names in it. - var names = new Ember.Set(["Charles", "Tom", "Juan", "Alex"]); // :P - - // creates a copy of the names set. - var namesCopy = new Ember.Set(names); - - // same as above. - var anotherNamesCopy = names.copy(); - ``` - - ## Adding/Removing Objects - - You generally add or remove objects from a set using `add()` or - `remove()`. You can add any type of object including primitives such as - numbers, strings, and booleans. - - Unlike arrays, objects can only exist one time in a set. If you call `add()` - on a set with the same object multiple times, the object will only be added - once. Likewise, calling `remove()` with the same object multiple times will - remove the object the first time and have no effect on future calls until - you add the object to the set again. - - NOTE: You cannot add/remove `null` or `undefined` to a set. Any attempt to do - so will be ignored. - - In addition to add/remove you can also call `push()`/`pop()`. Push behaves - just like `add()` but `pop()`, unlike `remove()` will pick an arbitrary - object, remove it and return it. This is a good way to use a set as a job - queue when you don't care which order the jobs are executed in. - - ## Testing for an Object - - To test for an object's presence in a set you simply call - `Ember.Set#contains()`. - - ## Observing changes - - When using `Ember.Set`, you can observe the `"[]"` property to be - alerted whenever the content changes. You can also add an enumerable - observer to the set to be notified of specific objects that are added and - removed from the set. See [Ember.Enumerable](/api/classes/Ember.Enumerable.html) - for more information on enumerables. - - This is often unhelpful. If you are filtering sets of objects, for instance, - it is very inefficient to re-filter all of the items each time the set - changes. It would be better if you could just adjust the filtered set based - on what was changed on the original set. The same issue applies to merging - sets, as well. - - ## Other Methods - - `Ember.Set` primary implements other mixin APIs. For a complete reference - on the methods you will use with `Ember.Set`, please consult these mixins. - The most useful ones will be `Ember.Enumerable` and - `Ember.MutableEnumerable` which implement most of the common iterator - methods you are used to on Array. - - Note that you can also use the `Ember.Copyable` and `Ember.Freezable` - APIs on `Ember.Set` as well. Once a set is frozen it can no longer be - modified. The benefit of this is that when you call `frozenCopy()` on it, - Ember will avoid making copies of the set. This allows you to write - code that can know with certainty when the underlying set data will or - will not be modified. - - @class Set - @namespace Ember - @extends Ember.CoreObject - @uses Ember.MutableEnumerable - @uses Ember.Copyable - @uses Ember.Freezable - @since Ember 0.9 - */ - __exports__["default"] = CoreObject.extend(MutableEnumerable, Copyable, Freezable, { - - // .......................................................... - // IMPLEMENT ENUMERABLE APIS - // - - /** - This property will change as the number of objects in the set changes. - - @property length - @type number - @default 0 - */ - length: 0, - - /** - Clears the set. This is useful if you want to reuse an existing set - without having to recreate it. - - ```javascript - var colors = new Ember.Set(["red", "green", "blue"]); - colors.length; // 3 - colors.clear(); - colors.length; // 0 - ``` - - @method clear - @return {Ember.Set} An empty Set - */ - clear: function() { - if (this.isFrozen) { throw new EmberError(FROZEN_ERROR); } - - var len = get(this, 'length'); - if (len === 0) { return this; } - - var guid; - - this.enumerableContentWillChange(len, 0); - propertyWillChange(this, 'firstObject'); - propertyWillChange(this, 'lastObject'); - - for (var i=0; i < len; i++) { - guid = guidFor(this[i]); - delete this[guid]; - delete this[i]; - } - - set(this, 'length', 0); - - propertyDidChange(this, 'firstObject'); - propertyDidChange(this, 'lastObject'); - this.enumerableContentDidChange(len, 0); - - return this; - }, - - /** - Returns true if the passed object is also an enumerable that contains the - same objects as the receiver. - - ```javascript - var colors = ["red", "green", "blue"], - same_colors = new Ember.Set(colors); - - same_colors.isEqual(colors); // true - same_colors.isEqual(["purple", "brown"]); // false - ``` - - @method isEqual - @param {Ember.Set} obj the other object. - @return {Boolean} - */ - isEqual: function(obj) { - // fail fast - if (!Enumerable.detect(obj)) return false; - - var loc = get(this, 'length'); - if (get(obj, 'length') !== loc) return false; - - while(--loc >= 0) { - if (!obj.contains(this[loc])) return false; - } - - return true; - }, - - /** - Adds an object to the set. Only non-`null` objects can be added to a set - and those can only be added once. If the object is already in the set or - the passed value is null this method will have no effect. - - This is an alias for `Ember.MutableEnumerable.addObject()`. - - ```javascript - var colors = new Ember.Set(); - colors.add("blue"); // ["blue"] - colors.add("blue"); // ["blue"] - colors.add("red"); // ["blue", "red"] - colors.add(null); // ["blue", "red"] - colors.add(undefined); // ["blue", "red"] - ``` - - @method add - @param {Object} obj The object to add. - @return {Ember.Set} The set itself. - */ - add: aliasMethod('addObject'), - - /** - Removes the object from the set if it is found. If you pass a `null` value - or an object that is already not in the set, this method will have no - effect. This is an alias for `Ember.MutableEnumerable.removeObject()`. - - ```javascript - var colors = new Ember.Set(["red", "green", "blue"]); - colors.remove("red"); // ["blue", "green"] - colors.remove("purple"); // ["blue", "green"] - colors.remove(null); // ["blue", "green"] - ``` - - @method remove - @param {Object} obj The object to remove - @return {Ember.Set} The set itself. - */ - remove: aliasMethod('removeObject'), - - /** - Removes the last element from the set and returns it, or `null` if it's empty. - - ```javascript - var colors = new Ember.Set(["green", "blue"]); - colors.pop(); // "blue" - colors.pop(); // "green" - colors.pop(); // null - ``` - - @method pop - @return {Object} The removed object from the set or null. - */ - pop: function() { - if (get(this, 'isFrozen')) throw new EmberError(FROZEN_ERROR); - var obj = this.length > 0 ? this[this.length-1] : null; - this.remove(obj); - return obj; - }, - - /** - Inserts the given object on to the end of the set. It returns - the set itself. - - This is an alias for `Ember.MutableEnumerable.addObject()`. - - ```javascript - var colors = new Ember.Set(); - colors.push("red"); // ["red"] - colors.push("green"); // ["red", "green"] - colors.push("blue"); // ["red", "green", "blue"] - ``` - - @method push - @return {Ember.Set} The set itself. - */ - push: aliasMethod('addObject'), - - /** - Removes the last element from the set and returns it, or `null` if it's empty. - - This is an alias for `Ember.Set.pop()`. - - ```javascript - var colors = new Ember.Set(["green", "blue"]); - colors.shift(); // "blue" - colors.shift(); // "green" - colors.shift(); // null - ``` - - @method shift - @return {Object} The removed object from the set or null. - */ - shift: aliasMethod('pop'), - - /** - Inserts the given object on to the end of the set. It returns - the set itself. - - This is an alias of `Ember.Set.push()` - - ```javascript - var colors = new Ember.Set(); - colors.unshift("red"); // ["red"] - colors.unshift("green"); // ["red", "green"] - colors.unshift("blue"); // ["red", "green", "blue"] - ``` - - @method unshift - @return {Ember.Set} The set itself. - */ - unshift: aliasMethod('push'), - - /** - Adds each object in the passed enumerable to the set. - - This is an alias of `Ember.MutableEnumerable.addObjects()` - - ```javascript - var colors = new Ember.Set(); - colors.addEach(["red", "green", "blue"]); // ["red", "green", "blue"] - ``` - - @method addEach - @param {Ember.Enumerable} objects the objects to add. - @return {Ember.Set} The set itself. - */ - addEach: aliasMethod('addObjects'), - - /** - Removes each object in the passed enumerable to the set. - - This is an alias of `Ember.MutableEnumerable.removeObjects()` - - ```javascript - var colors = new Ember.Set(["red", "green", "blue"]); - colors.removeEach(["red", "blue"]); // ["green"] - ``` - - @method removeEach - @param {Ember.Enumerable} objects the objects to remove. - @return {Ember.Set} The set itself. - */ - removeEach: aliasMethod('removeObjects'), - - // .......................................................... - // PRIVATE ENUMERABLE SUPPORT - // - - init: function(items) { - Ember.deprecate('Ember.Set is deprecated and will be removed in a future release.'); - this._super(); - if (items) this.addObjects(items); - }, - - // implement Ember.Enumerable - nextObject: function(idx) { - return this[idx]; - }, - - // more optimized version - firstObject: computed(function() { - return this.length > 0 ? this[0] : undefined; - }), - - // more optimized version - lastObject: computed(function() { - return this.length > 0 ? this[this.length-1] : undefined; - }), - - // implements Ember.MutableEnumerable - addObject: function(obj) { - if (get(this, 'isFrozen')) throw new EmberError(FROZEN_ERROR); - if (isNone(obj)) return this; // nothing to do - - var guid = guidFor(obj); - var idx = this[guid]; - var len = get(this, 'length'); - var added; - - if (idx>=0 && idx=0 && idx=0; - }, - - copy: function() { - var C = this.constructor, ret = new C(), loc = get(this, 'length'); - set(ret, 'length', loc); - while(--loc>=0) { - ret[loc] = this[loc]; - ret[guidFor(this[loc])] = loc; - } - return ret; - }, - - toString: function() { - var len = this.length, idx, array = []; - for(idx = 0; idx < len; idx++) { - array[idx] = this[idx]; - } - return fmt("Ember.Set<%@>", [array.join(',')]); - } - }); - }); -enifed("ember-runtime/system/string", - ["ember-metal/core","ember-metal/utils","ember-metal/cache","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __exports__) { - "use strict"; - /** - @module ember - @submodule ember-runtime - */ - var Ember = __dependency1__["default"]; - // Ember.STRINGS, Ember.FEATURES - var isArray = __dependency2__.isArray; - var emberInspect = __dependency2__.inspect; - - var Cache = __dependency3__["default"]; - - var STRING_DASHERIZE_REGEXP = (/[ _]/g); - - var STRING_DASHERIZE_CACHE = new Cache(1000, function(key) { - return decamelize(key).replace(STRING_DASHERIZE_REGEXP, '-'); - }); - - var CAMELIZE_CACHE = new Cache(1000, function(key) { - return key.replace(STRING_CAMELIZE_REGEXP, function(match, separator, chr) { - return chr ? chr.toUpperCase() : ''; - }).replace(/^([A-Z])/, function(match, separator, chr) { - return match.toLowerCase(); - }); - }); - - var CLASSIFY_CACHE = new Cache(1000, function(str) { - var parts = str.split("."); - var out = []; - - for (var i=0, l=parts.length; i 2) { - cachedFormats = new Array(arguments.length - 1); - - for (var i = 1, l = arguments.length; i < l; i++) { - cachedFormats[i - 1] = arguments[i]; - } - } - - // first, replace any ORDERED replacements. - var idx = 0; // the current index for non-numerical replacements - return str.replace(/%@([0-9]+)?/g, function(s, argIndex) { - argIndex = (argIndex) ? parseInt(argIndex, 10) - 1 : idx++; - s = cachedFormats[argIndex]; - return (s === null) ? '(null)' : (s === undefined) ? '' : emberInspect(s); - }); - } - - function loc(str, formats) { - if (!isArray(formats) || arguments.length > 2) { - formats = Array.prototype.slice.call(arguments, 1); - } - - str = Ember.STRINGS[str] || str; - return fmt(str, formats); - } - - function w(str) { - return str.split(/\s+/); - } - - function decamelize(str) { - return DECAMELIZE_CACHE.get(str); - } - - function dasherize(str) { - return STRING_DASHERIZE_CACHE.get(str); - } - - function camelize(str) { - return CAMELIZE_CACHE.get(str); - } - - function classify(str) { - return CLASSIFY_CACHE.get(str); - } - - function underscore(str) { - return UNDERSCORE_CACHE.get(str); - } - - function capitalize(str) { - return CAPITALIZE_CACHE.get(str); - } - - /** - Defines the hash of localized strings for the current language. Used by - the `Ember.String.loc()` helper. To localize, add string values to this - hash. - - @property STRINGS - @for Ember - @type Hash - */ - Ember.STRINGS = {}; - - /** - Defines string helper methods including string formatting and localization. - Unless `Ember.EXTEND_PROTOTYPES.String` is `false` these methods will also be - added to the `String.prototype` as well. - - @class String - @namespace Ember - @static - */ - __exports__["default"] = { - /** - Apply formatting options to the string. This will look for occurrences - of "%@" in your string and substitute them with the arguments you pass into - this method. If you want to control the specific order of replacement, - you can add a number after the key as well to indicate which argument - you want to insert. - - Ordered insertions are most useful when building loc strings where values - you need to insert may appear in different orders. - - ```javascript - "Hello %@ %@".fmt('John', 'Doe'); // "Hello John Doe" - "Hello %@2, %@1".fmt('John', 'Doe'); // "Hello Doe, John" - ``` - - @method fmt - @param {String} str The string to format - @param {Array} formats An array of parameters to interpolate into string. - @return {String} formatted string - */ - fmt: fmt, - - /** - Formats the passed string, but first looks up the string in the localized - strings hash. This is a convenient way to localize text. See - `Ember.String.fmt()` for more information on formatting. - - Note that it is traditional but not required to prefix localized string - keys with an underscore or other character so you can easily identify - localized strings. - - ```javascript - Ember.STRINGS = { - '_Hello World': 'Bonjour le monde', - '_Hello %@ %@': 'Bonjour %@ %@' - }; - - Ember.String.loc("_Hello World"); // 'Bonjour le monde'; - Ember.String.loc("_Hello %@ %@", ["John", "Smith"]); // "Bonjour John Smith"; - ``` - - @method loc - @param {String} str The string to format - @param {Array} formats Optional array of parameters to interpolate into string. - @return {String} formatted string - */ - loc: loc, - - /** - Splits a string into separate units separated by spaces, eliminating any - empty strings in the process. This is a convenience method for split that - is mostly useful when applied to the `String.prototype`. - - ```javascript - Ember.String.w("alpha beta gamma").forEach(function(key) { - console.log(key); - }); - - // > alpha - // > beta - // > gamma - ``` - - @method w - @param {String} str The string to split - @return {Array} array containing the split strings - */ - w: w, - - /** - Converts a camelized string into all lower case separated by underscores. - - ```javascript - 'innerHTML'.decamelize(); // 'inner_html' - 'action_name'.decamelize(); // 'action_name' - 'css-class-name'.decamelize(); // 'css-class-name' - 'my favorite items'.decamelize(); // 'my favorite items' - ``` - - @method decamelize - @param {String} str The string to decamelize. - @return {String} the decamelized string. - */ - decamelize: decamelize, - - /** - Replaces underscores, spaces, or camelCase with dashes. - - ```javascript - 'innerHTML'.dasherize(); // 'inner-html' - 'action_name'.dasherize(); // 'action-name' - 'css-class-name'.dasherize(); // 'css-class-name' - 'my favorite items'.dasherize(); // 'my-favorite-items' - ``` - - @method dasherize - @param {String} str The string to dasherize. - @return {String} the dasherized string. - */ - dasherize: dasherize, - - /** - Returns the lowerCamelCase form of a string. - - ```javascript - 'innerHTML'.camelize(); // 'innerHTML' - 'action_name'.camelize(); // 'actionName' - 'css-class-name'.camelize(); // 'cssClassName' - 'my favorite items'.camelize(); // 'myFavoriteItems' - 'My Favorite Items'.camelize(); // 'myFavoriteItems' - ``` - - @method camelize - @param {String} str The string to camelize. - @return {String} the camelized string. - */ - camelize: camelize, - - /** - Returns the UpperCamelCase form of a string. - - ```javascript - 'innerHTML'.classify(); // 'InnerHTML' - 'action_name'.classify(); // 'ActionName' - 'css-class-name'.classify(); // 'CssClassName' - 'my favorite items'.classify(); // 'MyFavoriteItems' - ``` - - @method classify - @param {String} str the string to classify - @return {String} the classified string - */ - classify: classify, - - /** - More general than decamelize. Returns the lower\_case\_and\_underscored - form of a string. - - ```javascript - 'innerHTML'.underscore(); // 'inner_html' - 'action_name'.underscore(); // 'action_name' - 'css-class-name'.underscore(); // 'css_class_name' - 'my favorite items'.underscore(); // 'my_favorite_items' - ``` - - @method underscore - @param {String} str The string to underscore. - @return {String} the underscored string. - */ - underscore: underscore, - - /** - Returns the Capitalized form of a string - - ```javascript - 'innerHTML'.capitalize() // 'InnerHTML' - 'action_name'.capitalize() // 'Action_name' - 'css-class-name'.capitalize() // 'Css-class-name' - 'my favorite items'.capitalize() // 'My favorite items' - ``` - - @method capitalize - @param {String} str The string to capitalize. - @return {String} The capitalized string. - */ - capitalize: capitalize - }; - - __exports__.fmt = fmt; - __exports__.loc = loc; - __exports__.w = w; - __exports__.decamelize = decamelize; - __exports__.dasherize = dasherize; - __exports__.camelize = camelize; - __exports__.classify = classify; - __exports__.underscore = underscore; - __exports__.capitalize = capitalize; - }); -enifed("ember-runtime/system/subarray", - ["ember-metal/property_get","ember-metal/error","ember-metal/enumerable_utils","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __exports__) { - "use strict"; - var get = __dependency1__.get; - var EmberError = __dependency2__["default"]; - var EnumerableUtils = __dependency3__["default"]; - - var RETAIN = 'r'; - var FILTER = 'f'; - - function Operation(type, count) { - this.type = type; - this.count = count; - } - - __exports__["default"] = SubArray; - - /** - An `Ember.SubArray` tracks an array in a way similar to, but more specialized - than, `Ember.TrackedArray`. It is useful for keeping track of the indexes of - items within a filtered array. - - @class SubArray - @namespace Ember - */ - function SubArray (length) { - if (arguments.length < 1) { length = 0; } - - if (length > 0) { - this._operations = [new Operation(RETAIN, length)]; - } else { - this._operations = []; - } - } - - - SubArray.prototype = { - /** - Track that an item was added to the tracked array. - - @method addItem - - @param {Number} index The index of the item in the tracked array. - @param {Boolean} match `true` iff the item is included in the subarray. - - @return {number} The index of the item in the subarray. - */ - addItem: function(index, match) { - var returnValue = -1; - var itemType = match ? RETAIN : FILTER; - var self = this; - - this._findOperation(index, function(operation, operationIndex, rangeStart, rangeEnd, seenInSubArray) { - var newOperation, splitOperation; - - if (itemType === operation.type) { - ++operation.count; - } else if (index === rangeStart) { - // insert to the left of `operation` - self._operations.splice(operationIndex, 0, new Operation(itemType, 1)); - } else { - newOperation = new Operation(itemType, 1); - splitOperation = new Operation(operation.type, rangeEnd - index + 1); - operation.count = index - rangeStart; - - self._operations.splice(operationIndex + 1, 0, newOperation, splitOperation); - } - - if (match) { - if (operation.type === RETAIN) { - returnValue = seenInSubArray + (index - rangeStart); - } else { - returnValue = seenInSubArray; - } - } - - self._composeAt(operationIndex); - }, function(seenInSubArray) { - self._operations.push(new Operation(itemType, 1)); - - if (match) { - returnValue = seenInSubArray; - } - - self._composeAt(self._operations.length-1); - }); - - return returnValue; - }, - - /** - Track that an item was removed from the tracked array. - - @method removeItem - - @param {Number} index The index of the item in the tracked array. - - @return {number} The index of the item in the subarray, or `-1` if the item - was not in the subarray. - */ - removeItem: function(index) { - var returnValue = -1; - var self = this; - - this._findOperation(index, function (operation, operationIndex, rangeStart, rangeEnd, seenInSubArray) { - if (operation.type === RETAIN) { - returnValue = seenInSubArray + (index - rangeStart); - } - - if (operation.count > 1) { - --operation.count; - } else { - self._operations.splice(operationIndex, 1); - self._composeAt(operationIndex); - } - }, function() { - throw new EmberError("Can't remove an item that has never been added."); - }); - - return returnValue; - }, - - - _findOperation: function (index, foundCallback, notFoundCallback) { - var seenInSubArray = 0; - var operationIndex, len, operation, rangeStart, rangeEnd; - - // OPTIMIZE: change to balanced tree - // find leftmost operation to the right of `index` - for (operationIndex = rangeStart = 0, len = this._operations.length; operationIndex < len; rangeStart = rangeEnd + 1, ++operationIndex) { - operation = this._operations[operationIndex]; - rangeEnd = rangeStart + operation.count - 1; - - if (index >= rangeStart && index <= rangeEnd) { - foundCallback(operation, operationIndex, rangeStart, rangeEnd, seenInSubArray); - return; - } else if (operation.type === RETAIN) { - seenInSubArray += operation.count; - } - } - - notFoundCallback(seenInSubArray); - }, - - _composeAt: function(index) { - var op = this._operations[index]; - var otherOp; - - if (!op) { - // Composing out of bounds is a no-op, as when removing the last operation - // in the list. - return; - } - - if (index > 0) { - otherOp = this._operations[index-1]; - if (otherOp.type === op.type) { - op.count += otherOp.count; - this._operations.splice(index-1, 1); - --index; - } - } - - if (index < this._operations.length-1) { - otherOp = this._operations[index+1]; - if (otherOp.type === op.type) { - op.count += otherOp.count; - this._operations.splice(index+1, 1); - } - } - }, - - toString: function () { - var str = ""; - EnumerableUtils.forEach(this._operations, function (operation) { - str += " " + operation.type + ":" + operation.count; - }); - return str.substring(1); - } - }; - }); -enifed("ember-runtime/system/tracked_array", - ["ember-metal/property_get","ember-metal/enumerable_utils","exports"], - function(__dependency1__, __dependency2__, __exports__) { - "use strict"; - var get = __dependency1__.get; - var forEach = __dependency2__.forEach; - - var RETAIN = 'r'; - var INSERT = 'i'; - var DELETE = 'd'; - - __exports__["default"] = TrackedArray; - - /** - An `Ember.TrackedArray` tracks array operations. It's useful when you want to - lazily compute the indexes of items in an array after they've been shifted by - subsequent operations. - - @class TrackedArray - @namespace Ember - @param {Array} [items=[]] The array to be tracked. This is used just to get - the initial items for the starting state of retain:n. - */ - function TrackedArray(items) { - if (arguments.length < 1) { items = []; } - - var length = get(items, 'length'); - - if (length) { - this._operations = [new ArrayOperation(RETAIN, length, items)]; - } else { - this._operations = []; - } - } - - TrackedArray.RETAIN = RETAIN; - TrackedArray.INSERT = INSERT; - TrackedArray.DELETE = DELETE; - - TrackedArray.prototype = { - - /** - Track that `newItems` were added to the tracked array at `index`. - - @method addItems - @param index - @param newItems - */ - addItems: function (index, newItems) { - var count = get(newItems, 'length'); - if (count < 1) { return; } - - var match = this._findArrayOperation(index); - var arrayOperation = match.operation; - var arrayOperationIndex = match.index; - var arrayOperationRangeStart = match.rangeStart; - var composeIndex, splitIndex, splitItems, splitArrayOperation, newArrayOperation; - - newArrayOperation = new ArrayOperation(INSERT, count, newItems); - - if (arrayOperation) { - if (!match.split) { - // insert left of arrayOperation - this._operations.splice(arrayOperationIndex, 0, newArrayOperation); - composeIndex = arrayOperationIndex; - } else { - this._split(arrayOperationIndex, index - arrayOperationRangeStart, newArrayOperation); - composeIndex = arrayOperationIndex + 1; - } - } else { - // insert at end - this._operations.push(newArrayOperation); - composeIndex = arrayOperationIndex; - } - - this._composeInsert(composeIndex); - }, - - /** - Track that `count` items were removed at `index`. - - @method removeItems - @param index - @param count - */ - removeItems: function (index, count) { - if (count < 1) { return; } - - var match = this._findArrayOperation(index); - var arrayOperation = match.operation; - var arrayOperationIndex = match.index; - var arrayOperationRangeStart = match.rangeStart; - var newArrayOperation, composeIndex; - - newArrayOperation = new ArrayOperation(DELETE, count); - if (!match.split) { - // insert left of arrayOperation - this._operations.splice(arrayOperationIndex, 0, newArrayOperation); - composeIndex = arrayOperationIndex; - } else { - this._split(arrayOperationIndex, index - arrayOperationRangeStart, newArrayOperation); - composeIndex = arrayOperationIndex + 1; - } - - return this._composeDelete(composeIndex); - }, - - /** - Apply all operations, reducing them to retain:n, for `n`, the number of - items in the array. - - `callback` will be called for each operation and will be passed the following arguments: - - * {array} items The items for the given operation - * {number} offset The computed offset of the items, ie the index in the - array of the first item for this operation. - * {string} operation The type of the operation. One of - `Ember.TrackedArray.{RETAIN, DELETE, INSERT}` - - @method apply - @param {Function} callback - */ - apply: function (callback) { - var items = []; - var offset = 0; - - forEach(this._operations, function (arrayOperation, operationIndex) { - callback(arrayOperation.items, offset, arrayOperation.type, operationIndex); - - if (arrayOperation.type !== DELETE) { - offset += arrayOperation.count; - items = items.concat(arrayOperation.items); - } - }); - - this._operations = [new ArrayOperation(RETAIN, items.length, items)]; - }, - - /** - Return an `ArrayOperationMatch` for the operation that contains the item at `index`. - - @method _findArrayOperation - - @param {Number} index the index of the item whose operation information - should be returned. - @private - */ - _findArrayOperation: function (index) { - var split = false; - var arrayOperationIndex, arrayOperation, - arrayOperationRangeStart, arrayOperationRangeEnd, - len; - - // OPTIMIZE: we could search these faster if we kept a balanced tree. - // find leftmost arrayOperation to the right of `index` - for (arrayOperationIndex = arrayOperationRangeStart = 0, len = this._operations.length; arrayOperationIndex < len; ++arrayOperationIndex) { - arrayOperation = this._operations[arrayOperationIndex]; - - if (arrayOperation.type === DELETE) { continue; } - - arrayOperationRangeEnd = arrayOperationRangeStart + arrayOperation.count - 1; - - if (index === arrayOperationRangeStart) { - break; - } else if (index > arrayOperationRangeStart && index <= arrayOperationRangeEnd) { - split = true; - break; - } else { - arrayOperationRangeStart = arrayOperationRangeEnd + 1; - } - } - - return new ArrayOperationMatch(arrayOperation, arrayOperationIndex, split, arrayOperationRangeStart); - }, - - _split: function (arrayOperationIndex, splitIndex, newArrayOperation) { - var arrayOperation = this._operations[arrayOperationIndex]; - var splitItems = arrayOperation.items.slice(splitIndex); - var splitArrayOperation = new ArrayOperation(arrayOperation.type, splitItems.length, splitItems); - - // truncate LHS - arrayOperation.count = splitIndex; - arrayOperation.items = arrayOperation.items.slice(0, splitIndex); - - this._operations.splice(arrayOperationIndex + 1, 0, newArrayOperation, splitArrayOperation); - }, - - // see SubArray for a better implementation. - _composeInsert: function (index) { - var newArrayOperation = this._operations[index]; - var leftArrayOperation = this._operations[index-1]; // may be undefined - var rightArrayOperation = this._operations[index+1]; // may be undefined - var leftOp = leftArrayOperation && leftArrayOperation.type; - var rightOp = rightArrayOperation && rightArrayOperation.type; - - if (leftOp === INSERT) { - // merge left - leftArrayOperation.count += newArrayOperation.count; - leftArrayOperation.items = leftArrayOperation.items.concat(newArrayOperation.items); - - if (rightOp === INSERT) { - // also merge right (we have split an insert with an insert) - leftArrayOperation.count += rightArrayOperation.count; - leftArrayOperation.items = leftArrayOperation.items.concat(rightArrayOperation.items); - this._operations.splice(index, 2); - } else { - // only merge left - this._operations.splice(index, 1); - } - } else if (rightOp === INSERT) { - // merge right - newArrayOperation.count += rightArrayOperation.count; - newArrayOperation.items = newArrayOperation.items.concat(rightArrayOperation.items); - this._operations.splice(index + 1, 1); - } - }, - - _composeDelete: function (index) { - var arrayOperation = this._operations[index]; - var deletesToGo = arrayOperation.count; - var leftArrayOperation = this._operations[index-1]; // may be undefined - var leftOp = leftArrayOperation && leftArrayOperation.type; - var nextArrayOperation; - var nextOp; - var nextCount; - var removeNewAndNextOp = false; - var removedItems = []; - - if (leftOp === DELETE) { - arrayOperation = leftArrayOperation; - index -= 1; - } - - for (var i = index + 1; deletesToGo > 0; ++i) { - nextArrayOperation = this._operations[i]; - nextOp = nextArrayOperation.type; - nextCount = nextArrayOperation.count; - - if (nextOp === DELETE) { - arrayOperation.count += nextCount; - continue; - } - - if (nextCount > deletesToGo) { - // d:2 {r,i}:5 we reduce the retain or insert, but it stays - removedItems = removedItems.concat(nextArrayOperation.items.splice(0, deletesToGo)); - nextArrayOperation.count -= deletesToGo; - - // In the case where we truncate the last arrayOperation, we don't need to - // remove it; also the deletesToGo reduction is not the entirety of - // nextCount - i -= 1; - nextCount = deletesToGo; - - deletesToGo = 0; - } else { - if (nextCount === deletesToGo) { - // Handle edge case of d:2 i:2 in which case both operations go away - // during composition. - removeNewAndNextOp = true; - } - removedItems = removedItems.concat(nextArrayOperation.items); - deletesToGo -= nextCount; - } - - if (nextOp === INSERT) { - // d:2 i:3 will result in delete going away - arrayOperation.count -= nextCount; - } - } - - if (arrayOperation.count > 0) { - // compose our new delete with possibly several operations to the right of - // disparate types - this._operations.splice(index+1, i-1-index); - } else { - // The delete operation can go away; it has merely reduced some other - // operation, as in d:3 i:4; it may also have eliminated that operation, - // as in d:3 i:3. - this._operations.splice(index, removeNewAndNextOp ? 2 : 1); - } - - return removedItems; - }, - - toString: function () { - var str = ""; - forEach(this._operations, function (operation) { - str += " " + operation.type + ":" + operation.count; - }); - return str.substring(1); - } - }; - - /** - Internal data structure to represent an array operation. - - @method ArrayOperation - @private - @param {String} type The type of the operation. One of - `Ember.TrackedArray.{RETAIN, INSERT, DELETE}` - @param {Number} count The number of items in this operation. - @param {Array} items The items of the operation, if included. RETAIN and - INSERT include their items, DELETE does not. - */ - function ArrayOperation (operation, count, items) { - this.type = operation; // RETAIN | INSERT | DELETE - this.count = count; - this.items = items; - } - - /** - Internal data structure used to include information when looking up operations - by item index. - - @method ArrayOperationMatch - @private - @param {ArrayOperation} operation - @param {Number} index The index of `operation` in the array of operations. - @param {Boolean} split Whether or not the item index searched for would - require a split for a new operation type. - @param {Number} rangeStart The index of the first item in the operation, - with respect to the tracked array. The index of the last item can be computed - from `rangeStart` and `operation.count`. - */ - function ArrayOperationMatch(operation, index, split, rangeStart) { - this.operation = operation; - this.index = index; - this.split = split; - this.rangeStart = rangeStart; - } - }); -enifed("ember-testing", - ["ember-metal/core","ember-testing/initializers","ember-testing/support","ember-testing/setup_for_testing","ember-testing/test","ember-testing/adapters/adapter","ember-testing/adapters/qunit","ember-testing/helpers"], - function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__) { - "use strict"; - var Ember = __dependency1__["default"]; - - // to setup initializer - // to handle various edge cases - - var setupForTesting = __dependency4__["default"]; - var Test = __dependency5__["default"]; - var Adapter = __dependency6__["default"]; - var QUnitAdapter = __dependency7__["default"]; - // adds helpers to helpers object in Test - - /** - Ember Testing - - @module ember - @submodule ember-testing - @requires ember-application - */ - - Ember.Test = Test; - Ember.Test.Adapter = Adapter; - Ember.Test.QUnitAdapter = QUnitAdapter; - Ember.setupForTesting = setupForTesting; - }); -enifed("ember-testing/adapters/adapter", - ["ember-metal/core","ember-metal/utils","ember-runtime/system/object","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __exports__) { - "use strict"; - var Ember = __dependency1__["default"]; - // Ember.K - var inspect = __dependency2__.inspect; - var EmberObject = __dependency3__["default"]; - - /** - @module ember - @submodule ember-testing - */ - - /** - The primary purpose of this class is to create hooks that can be implemented - by an adapter for various test frameworks. - - @class Adapter - @namespace Ember.Test - */ - var Adapter = EmberObject.extend({ - /** - This callback will be called whenever an async operation is about to start. - - Override this to call your framework's methods that handle async - operations. - - @public - @method asyncStart - */ - asyncStart: Ember.K, - - /** - This callback will be called whenever an async operation has completed. - - @public - @method asyncEnd - */ - asyncEnd: Ember.K, - - /** - Override this method with your testing framework's false assertion. - This function is called whenever an exception occurs causing the testing - promise to fail. - - QUnit example: - - ```javascript - exception: function(error) { - ok(false, error); - }; - ``` - - @public - @method exception - @param {String} error The exception to be raised. - */ - exception: function(error) { - throw error; - } - }); - - __exports__["default"] = Adapter; - }); -enifed("ember-testing/adapters/qunit", - ["ember-testing/adapters/adapter","ember-metal/utils","exports"], - function(__dependency1__, __dependency2__, __exports__) { - "use strict"; - var Adapter = __dependency1__["default"]; - var inspect = __dependency2__.inspect; - - /** - This class implements the methods defined by Ember.Test.Adapter for the - QUnit testing framework. - - @class QUnitAdapter - @namespace Ember.Test - @extends Ember.Test.Adapter - */ - __exports__["default"] = Adapter.extend({ - asyncStart: function() { - QUnit.stop(); - }, - asyncEnd: function() { - QUnit.start(); - }, - exception: function(error) { - ok(false, inspect(error)); - } - }); - }); -enifed("ember-testing/helpers", - ["ember-metal/property_get","ember-metal/error","ember-metal/run_loop","ember-views/system/jquery","ember-testing/test"], - function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__) { - "use strict"; - var get = __dependency1__.get; - var EmberError = __dependency2__["default"]; - var run = __dependency3__["default"]; - var jQuery = __dependency4__["default"]; - var Test = __dependency5__["default"]; - - /** - * @module ember - * @submodule ember-testing - */ - - var helper = Test.registerHelper; - var asyncHelper = Test.registerAsyncHelper; - var countAsync = 0; - - function currentRouteName(app){ - var appController = app.__container__.lookup('controller:application'); - - return get(appController, 'currentRouteName'); - } - - function currentPath(app){ - var appController = app.__container__.lookup('controller:application'); - - return get(appController, 'currentPath'); - } - - function currentURL(app){ - var router = app.__container__.lookup('router:main'); - - return get(router, 'location').getURL(); - } - - function visit(app, url) { - var router = app.__container__.lookup('router:main'); - router.location.setURL(url); - - if (app._readinessDeferrals > 0) { - router['initialURL'] = url; - run(app, 'advanceReadiness'); - delete router['initialURL']; - } else { - run(app, app.handleURL, url); - } - - return app.testHelpers.wait(); - } - - function click(app, selector, context) { - var $el = app.testHelpers.findWithAssert(selector, context); - run($el, 'mousedown'); - - if ($el.is(':input')) { - var type = $el.prop('type'); - if (type !== 'checkbox' && type !== 'radio' && type !== 'hidden') { - run($el, function(){ - // Firefox does not trigger the `focusin` event if the window - // does not have focus. If the document doesn't have focus just - // use trigger('focusin') instead. - if (!document.hasFocus || document.hasFocus()) { - this.focus(); - } else { - this.trigger('focusin'); - } - }); - } - } - - run($el, 'mouseup'); - run($el, 'click'); - - return app.testHelpers.wait(); - } - - function triggerEvent(app, selector, contextOrType, typeOrOptions, possibleOptions){ - var arity = arguments.length; - var context, type, options; - - if (arity === 3) { - // context and options are optional, so this is - // app, selector, type - context = null; - type = contextOrType; - options = {}; - } else if (arity === 4) { - // context and options are optional, so this is - if (typeof typeOrOptions === "object") { // either - // app, selector, type, options - context = null; - type = contextOrType; - options = typeOrOptions; - } else { // or - // app, selector, context, type - context = contextOrType; - type = typeOrOptions; - options = {}; - } - } else { - context = contextOrType; - type = typeOrOptions; - options = possibleOptions; - } - - var $el = app.testHelpers.findWithAssert(selector, context); - - var event = jQuery.Event(type, options); - - run($el, 'trigger', event); - - return app.testHelpers.wait(); - } - - function keyEvent(app, selector, contextOrType, typeOrKeyCode, keyCode) { - var context, type; - - if (typeof keyCode === 'undefined') { - context = null; - keyCode = typeOrKeyCode; - type = contextOrType; - } else { - context = contextOrType; - type = typeOrKeyCode; - } - - return app.testHelpers.triggerEvent(selector, context, type, { keyCode: keyCode, which: keyCode }); - } - - function fillIn(app, selector, contextOrText, text) { - var $el, context; - if (typeof text === 'undefined') { - text = contextOrText; - } else { - context = contextOrText; - } - $el = app.testHelpers.findWithAssert(selector, context); - run(function() { - $el.val(text).change(); - }); - return app.testHelpers.wait(); - } - - function findWithAssert(app, selector, context) { - var $el = app.testHelpers.find(selector, context); - if ($el.length === 0) { - throw new EmberError("Element " + selector + " not found."); - } - return $el; - } - - function find(app, selector, context) { - var $el; - context = context || get(app, 'rootElement'); - $el = app.$(selector, context); - - return $el; - } - - function andThen(app, callback) { - return app.testHelpers.wait(callback(app)); - } - - function wait(app, value) { - return Test.promise(function(resolve) { - // If this is the first async promise, kick off the async test - if (++countAsync === 1) { - Test.adapter.asyncStart(); - } - - // Every 10ms, poll for the async thing to have finished - var watcher = setInterval(function() { - // 1. If the router is loading, keep polling - var routerIsLoading = !!app.__container__.lookup('router:main').router.activeTransition; - if (routerIsLoading) { return; } - - // 2. If there are pending Ajax requests, keep polling - if (Test.pendingAjaxRequests) { return; } - - // 3. If there are scheduled timers or we are inside of a run loop, keep polling - if (run.hasScheduledTimers() || run.currentRunLoop) { return; } - if (Test.waiters && Test.waiters.any(function(waiter) { - var context = waiter[0]; - var callback = waiter[1]; - return !callback.call(context); - })) { return; } - // Stop polling - clearInterval(watcher); - - // If this is the last async promise, end the async test - if (--countAsync === 0) { - Test.adapter.asyncEnd(); - } - - // Synchronously resolve the promise - run(null, resolve, value); - }, 10); - }); - - } - - - /** - * Loads a route, sets up any controllers, and renders any templates associated - * with the route as though a real user had triggered the route change while - * using your app. - * - * Example: - * - * ```javascript - * visit('posts/index').then(function() { - * // assert something - * }); - * ``` - * - * @method visit - * @param {String} url the name of the route - * @return {RSVP.Promise} - */ - asyncHelper('visit', visit); - - /** - * Clicks an element and triggers any actions triggered by the element's `click` - * event. - * - * Example: - * - * ```javascript - * click('.some-jQuery-selector').then(function() { - * // assert something - * }); - * ``` - * - * @method click - * @param {String} selector jQuery selector for finding element on the DOM - * @return {RSVP.Promise} - */ - asyncHelper('click', click); - - /** - * Simulates a key event, e.g. `keypress`, `keydown`, `keyup` with the desired keyCode - * - * Example: - * - * ```javascript - * keyEvent('.some-jQuery-selector', 'keypress', 13).then(function() { - * // assert something - * }); - * ``` - * - * @method keyEvent - * @param {String} selector jQuery selector for finding element on the DOM - * @param {String} type the type of key event, e.g. `keypress`, `keydown`, `keyup` - * @param {Number} keyCode the keyCode of the simulated key event - * @return {RSVP.Promise} - * @since 1.5.0 - */ - asyncHelper('keyEvent', keyEvent); - - /** - * Fills in an input element with some text. - * - * Example: - * - * ```javascript - * fillIn('#email', 'you@example.com').then(function() { - * // assert something - * }); - * ``` - * - * @method fillIn - * @param {String} selector jQuery selector finding an input element on the DOM - * to fill text with - * @param {String} text text to place inside the input element - * @return {RSVP.Promise} - */ - asyncHelper('fillIn', fillIn); - - /** - * Finds an element in the context of the app's container element. A simple alias - * for `app.$(selector)`. - * - * Example: - * - * ```javascript - * var $el = find('.my-selector'); - * ``` - * - * @method find - * @param {String} selector jQuery string selector for element lookup - * @return {Object} jQuery object representing the results of the query - */ - helper('find', find); - - /** - * Like `find`, but throws an error if the element selector returns no results. - * - * Example: - * - * ```javascript - * var $el = findWithAssert('.doesnt-exist'); // throws error - * ``` - * - * @method findWithAssert - * @param {String} selector jQuery selector string for finding an element within - * the DOM - * @return {Object} jQuery object representing the results of the query - * @throws {Error} throws error if jQuery object returned has a length of 0 - */ - helper('findWithAssert', findWithAssert); - - /** - Causes the run loop to process any pending events. This is used to ensure that - any async operations from other helpers (or your assertions) have been processed. - - This is most often used as the return value for the helper functions (see 'click', - 'fillIn','visit',etc). - - Example: - - ```javascript - Ember.Test.registerAsyncHelper('loginUser', function(app, username, password) { - visit('secured/path/here') - .fillIn('#username', username) - .fillIn('#password', username) - .click('.submit') - - return app.testHelpers.wait(); - }); - - @method wait - @param {Object} value The value to be returned. - @return {RSVP.Promise} - */ - asyncHelper('wait', wait); - asyncHelper('andThen', andThen); - - - /** - Returns the currently active route name. - - Example: - - ```javascript - function validateRouteName(){ - equal(currentRouteName(), 'some.path', "correct route was transitioned into."); - } - - visit('/some/path').then(validateRouteName) - ``` - - @method currentRouteName - @return {Object} The name of the currently active route. - @since 1.5.0 - */ - helper('currentRouteName', currentRouteName); - - /** - Returns the current path. - - Example: - - ```javascript - function validateURL(){ - equal(currentPath(), 'some.path.index', "correct path was transitioned into."); - } - - click('#some-link-id').then(validateURL); - ``` - - @method currentPath - @return {Object} The currently active path. - @since 1.5.0 - */ - helper('currentPath', currentPath); - - /** - Returns the current URL. - - Example: - - ```javascript - function validateURL(){ - equal(currentURL(), '/some/path', "correct URL was transitioned into."); - } - - click('#some-link-id').then(validateURL); - ``` - - @method currentURL - @return {Object} The currently active URL. - @since 1.5.0 - */ - helper('currentURL', currentURL); - - /** - Triggers the given DOM event on the element identified by the provided selector. - - Example: - - ```javascript - triggerEvent('#some-elem-id', 'blur'); - ``` - - This is actually used internally by the `keyEvent` helper like so: - - ```javascript - triggerEvent('#some-elem-id', 'keypress', { keyCode: 13 }); - ``` - - @method triggerEvent - @param {String} selector jQuery selector for finding element on the DOM - @param {String} [context] jQuery selector that will limit the selector - argument to find only within the context's children - @param {String} type The event type to be triggered. - @param {Object} [options] The options to be passed to jQuery.Event. - @return {RSVP.Promise} - @since 1.5.0 - */ - asyncHelper('triggerEvent', triggerEvent); - }); -enifed("ember-testing/initializers", - ["ember-runtime/system/lazy_load"], - function(__dependency1__) { - "use strict"; - var onLoad = __dependency1__.onLoad; - - var name = 'deferReadiness in `testing` mode'; - - onLoad('Ember.Application', function(Application) { - if (!Application.initializers[name]) { - Application.initializer({ - name: name, - - initialize: function(container, application){ - if (application.testing) { - application.deferReadiness(); - } - } - }); - } - }); - }); -enifed("ember-testing/setup_for_testing", - ["ember-metal/core","ember-testing/adapters/qunit","ember-views/system/jquery","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __exports__) { - "use strict"; - var Ember = __dependency1__["default"]; - // import Test from "ember-testing/test"; // ES6TODO: fix when cycles are supported - var QUnitAdapter = __dependency2__["default"]; - var jQuery = __dependency3__["default"]; - - var Test, requests; - - function incrementAjaxPendingRequests(_, xhr){ - requests.push(xhr); - Test.pendingAjaxRequests = requests.length; - } - - function decrementAjaxPendingRequests(_, xhr){ - for (var i=0;i') - .css({ position: 'absolute', left: '-1000px', top: '-1000px' }) - .appendTo('body') - .on('click', handler) - .trigger('click') - .remove(); - } - - $(function() { - /* - Determine whether a checkbox checked using jQuery's "click" method will have - the correct value for its checked property. - - If we determine that the current jQuery version exhibits this behavior, - patch it to work correctly as in the commit for the actual fix: - https://github.com/jquery/jquery/commit/1fb2f92. - */ - testCheckboxClick(function() { - if (!this.checked && !$.event.special.click) { - $.event.special.click = { - // For checkbox, fire native event so checked state will be right - trigger: function() { - if ($.nodeName( this, "input" ) && this.type === "checkbox" && this.click) { - this.click(); - return false; - } - } - }; - } - }); - - // Try again to verify that the patch took effect or blow up. - testCheckboxClick(function() { - Ember.warn("clicked checkboxes should be checked! the jQuery patch didn't work", this.checked); - }); - }); - }); -enifed("ember-testing/test", - ["ember-metal/core","ember-metal/run_loop","ember-metal/platform","ember-runtime/compare","ember-runtime/ext/rsvp","ember-testing/setup_for_testing","ember-application/system/application","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __exports__) { - "use strict"; - var Ember = __dependency1__["default"]; - var emberRun = __dependency2__["default"]; - var create = __dependency3__.create; - var compare = __dependency4__["default"]; - var RSVP = __dependency5__["default"]; - var setupForTesting = __dependency6__["default"]; - var EmberApplication = __dependency7__["default"]; - - /** - @module ember - @submodule ember-testing - */ - var slice = [].slice; - var helpers = {}; - var injectHelpersCallbacks = []; - - /** - This is a container for an assortment of testing related functionality: - - * Choose your default test adapter (for your framework of choice). - * Register/Unregister additional test helpers. - * Setup callbacks to be fired when the test helpers are injected into - your application. - - @class Test - @namespace Ember - */ - var Test = { - /** - Hash containing all known test helpers. - - @property _helpers - @private - @since 1.7.0 - */ - _helpers: helpers, - - /** - `registerHelper` is used to register a test helper that will be injected - when `App.injectTestHelpers` is called. - - The helper method will always be called with the current Application as - the first parameter. - - For example: - - ```javascript - Ember.Test.registerHelper('boot', function(app) { - Ember.run(app, app.advanceReadiness); - }); - ``` - - This helper can later be called without arguments because it will be - called with `app` as the first parameter. - - ```javascript - App = Ember.Application.create(); - App.injectTestHelpers(); - boot(); - ``` - - @public - @method registerHelper - @param {String} name The name of the helper method to add. - @param {Function} helperMethod - @param options {Object} - */ - registerHelper: function(name, helperMethod) { - helpers[name] = { - method: helperMethod, - meta: { wait: false } - }; - }, - - /** - `registerAsyncHelper` is used to register an async test helper that will be injected - when `App.injectTestHelpers` is called. - - The helper method will always be called with the current Application as - the first parameter. - - For example: - - ```javascript - Ember.Test.registerAsyncHelper('boot', function(app) { - Ember.run(app, app.advanceReadiness); - }); - ``` - - The advantage of an async helper is that it will not run - until the last async helper has completed. All async helpers - after it will wait for it complete before running. - - - For example: - - ```javascript - Ember.Test.registerAsyncHelper('deletePost', function(app, postId) { - click('.delete-' + postId); - }); - - // ... in your test - visit('/post/2'); - deletePost(2); - visit('/post/3'); - deletePost(3); - ``` - - @public - @method registerAsyncHelper - @param {String} name The name of the helper method to add. - @param {Function} helperMethod - @since 1.2.0 - */ - registerAsyncHelper: function(name, helperMethod) { - helpers[name] = { - method: helperMethod, - meta: { wait: true } - }; - }, - - /** - Remove a previously added helper method. - - Example: - - ```javascript - Ember.Test.unregisterHelper('wait'); - ``` - - @public - @method unregisterHelper - @param {String} name The helper to remove. - */ - unregisterHelper: function(name) { - delete helpers[name]; - delete Test.Promise.prototype[name]; - }, - - /** - Used to register callbacks to be fired whenever `App.injectTestHelpers` - is called. - - The callback will receive the current application as an argument. - - Example: - - ```javascript - Ember.Test.onInjectHelpers(function() { - Ember.$(document).ajaxSend(function() { - Test.pendingAjaxRequests++; - }); - - Ember.$(document).ajaxComplete(function() { - Test.pendingAjaxRequests--; - }); - }); - ``` - - @public - @method onInjectHelpers - @param {Function} callback The function to be called. - */ - onInjectHelpers: function(callback) { - injectHelpersCallbacks.push(callback); - }, - - /** - This returns a thenable tailored for testing. It catches failed - `onSuccess` callbacks and invokes the `Ember.Test.adapter.exception` - callback in the last chained then. - - This method should be returned by async helpers such as `wait`. - - @public - @method promise - @param {Function} resolver The function used to resolve the promise. - */ - promise: function(resolver) { - return new Test.Promise(resolver); - }, - - /** - Used to allow ember-testing to communicate with a specific testing - framework. - - You can manually set it before calling `App.setupForTesting()`. - - Example: - - ```javascript - Ember.Test.adapter = MyCustomAdapter.create() - ``` - - If you do not set it, ember-testing will default to `Ember.Test.QUnitAdapter`. - - @public - @property adapter - @type {Class} The adapter to be used. - @default Ember.Test.QUnitAdapter - */ - adapter: null, - - /** - Replacement for `Ember.RSVP.resolve` - The only difference is this uses - an instance of `Ember.Test.Promise` - - @public - @method resolve - @param {Mixed} The value to resolve - @since 1.2.0 - */ - resolve: function(val) { - return Test.promise(function(resolve) { - return resolve(val); - }); - }, - - /** - This allows ember-testing to play nicely with other asynchronous - events, such as an application that is waiting for a CSS3 - transition or an IndexDB transaction. - - For example: - - ```javascript - Ember.Test.registerWaiter(function() { - return myPendingTransactions() == 0; - }); - ``` - The `context` argument allows you to optionally specify the `this` - with which your callback will be invoked. - - For example: - - ```javascript - Ember.Test.registerWaiter(MyDB, MyDB.hasPendingTransactions); - ``` - - @public - @method registerWaiter - @param {Object} context (optional) - @param {Function} callback - @since 1.2.0 - */ - registerWaiter: function(context, callback) { - if (arguments.length === 1) { - callback = context; - context = null; - } - if (!this.waiters) { - this.waiters = Ember.A(); - } - this.waiters.push([context, callback]); - }, - /** - `unregisterWaiter` is used to unregister a callback that was - registered with `registerWaiter`. - - @public - @method unregisterWaiter - @param {Object} context (optional) - @param {Function} callback - @since 1.2.0 - */ - unregisterWaiter: function(context, callback) { - var pair; - if (!this.waiters) { return; } - if (arguments.length === 1) { - callback = context; - context = null; - } - pair = [context, callback]; - this.waiters = Ember.A(this.waiters.filter(function(elt) { - return compare(elt, pair)!==0; - })); - } - }; - - function helper(app, name) { - var fn = helpers[name].method; - var meta = helpers[name].meta; - - return function() { - var args = slice.call(arguments); - var lastPromise = Test.lastPromise; - - args.unshift(app); - - // some helpers are not async and - // need to return a value immediately. - // example: `find` - if (!meta.wait) { - return fn.apply(app, args); - } - - if (!lastPromise) { - // It's the first async helper in current context - lastPromise = fn.apply(app, args); - } else { - // wait for last helper's promise to resolve - // and then execute - run(function() { - lastPromise = Test.resolve(lastPromise).then(function() { - return fn.apply(app, args); - }); - }); - } - - return lastPromise; - }; - } - - function run(fn) { - if (!emberRun.currentRunLoop) { - emberRun(fn); - } else { - fn(); - } - } - - EmberApplication.reopen({ - /** - This property contains the testing helpers for the current application. These - are created once you call `injectTestHelpers` on your `Ember.Application` - instance. The included helpers are also available on the `window` object by - default, but can be used from this object on the individual application also. - - @property testHelpers - @type {Object} - @default {} - */ - testHelpers: {}, - - /** - This property will contain the original methods that were registered - on the `helperContainer` before `injectTestHelpers` is called. - - When `removeTestHelpers` is called, these methods are restored to the - `helperContainer`. - - @property originalMethods - @type {Object} - @default {} - @private - @since 1.3.0 - */ - originalMethods: {}, - - - /** - This property indicates whether or not this application is currently in - testing mode. This is set when `setupForTesting` is called on the current - application. - - @property testing - @type {Boolean} - @default false - @since 1.3.0 - */ - testing: false, - - /** - This hook defers the readiness of the application, so that you can start - the app when your tests are ready to run. It also sets the router's - location to 'none', so that the window's location will not be modified - (preventing both accidental leaking of state between tests and interference - with your testing framework). - - Example: - - ``` - App.setupForTesting(); - ``` - - @method setupForTesting - */ - setupForTesting: function() { - setupForTesting(); - - this.testing = true; - - this.Router.reopen({ - location: 'none' - }); - }, - - /** - This will be used as the container to inject the test helpers into. By - default the helpers are injected into `window`. - - @property helperContainer - @type {Object} The object to be used for test helpers. - @default window - @since 1.2.0 - */ - helperContainer: window, - - /** - This injects the test helpers into the `helperContainer` object. If an object is provided - it will be used as the helperContainer. If `helperContainer` is not set it will default - to `window`. If a function of the same name has already been defined it will be cached - (so that it can be reset if the helper is removed with `unregisterHelper` or - `removeTestHelpers`). - - Any callbacks registered with `onInjectHelpers` will be called once the - helpers have been injected. - - Example: - ``` - App.injectTestHelpers(); - ``` - - @method injectTestHelpers - */ - injectTestHelpers: function(helperContainer) { - if (helperContainer) { this.helperContainer = helperContainer; } - - this.testHelpers = {}; - for (var name in helpers) { - this.originalMethods[name] = this.helperContainer[name]; - this.testHelpers[name] = this.helperContainer[name] = helper(this, name); - protoWrap(Test.Promise.prototype, name, helper(this, name), helpers[name].meta.wait); - } - - for(var i = 0, l = injectHelpersCallbacks.length; i < l; i++) { - injectHelpersCallbacks[i](this); - } - }, - - /** - This removes all helpers that have been registered, and resets and functions - that were overridden by the helpers. - - Example: - - ```javascript - App.removeTestHelpers(); - ``` - - @public - @method removeTestHelpers - */ - removeTestHelpers: function() { - for (var name in helpers) { - this.helperContainer[name] = this.originalMethods[name]; - delete this.testHelpers[name]; - delete this.originalMethods[name]; - } - } - }); - - // This method is no longer needed - // But still here for backwards compatibility - // of helper chaining - function protoWrap(proto, name, callback, isAsync) { - proto[name] = function() { - var args = arguments; - if (isAsync) { - return callback.apply(this, args); - } else { - return this.then(function() { - return callback.apply(this, args); - }); - } - }; - } - - Test.Promise = function() { - RSVP.Promise.apply(this, arguments); - Test.lastPromise = this; - }; - - Test.Promise.prototype = create(RSVP.Promise.prototype); - Test.Promise.prototype.constructor = Test.Promise; - - // Patch `then` to isolate async methods - // specifically `Ember.Test.lastPromise` - var originalThen = RSVP.Promise.prototype.then; - Test.Promise.prototype.then = function(onSuccess, onFailure) { - return originalThen.call(this, function(val) { - return isolate(onSuccess, val); - }, onFailure); - }; - - // This method isolates nested async methods - // so that they don't conflict with other last promises. - // - // 1. Set `Ember.Test.lastPromise` to null - // 2. Invoke method - // 3. Return the last promise created during method - // 4. Restore `Ember.Test.lastPromise` to original value - function isolate(fn, val) { - var value, lastPromise; - - // Reset lastPromise for nested helpers - Test.lastPromise = null; - - value = fn(val); - - lastPromise = Test.lastPromise; - - // If the method returned a promise - // return that promise. If not, - // return the last async helper's promise - if ((value && (value instanceof Test.Promise)) || !lastPromise) { - return value; - } else { - run(function() { - lastPromise = Test.resolve(lastPromise).then(function() { - return value; - }); - }); - return lastPromise; - } - } - - __exports__["default"] = Test; - }); -enifed("ember-views", - ["ember-runtime","ember-views/system/jquery","ember-views/system/utils","ember-views/system/render_buffer","ember-views/system/ext","ember-views/views/states","ember-views/views/core_view","ember-views/views/view","ember-views/views/container_view","ember-views/views/collection_view","ember-views/views/component","ember-views/system/event_dispatcher","ember-views/mixins/view_target_action_support","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __dependency11__, __dependency12__, __dependency13__, __exports__) { - "use strict"; - /** - Ember Views - - @module ember - @submodule ember-views - @requires ember-runtime - @main ember-views - */ - - // BEGIN IMPORTS - var Ember = __dependency1__["default"]; - var jQuery = __dependency2__["default"]; - var isSimpleClick = __dependency3__.isSimpleClick; - var RenderBuffer = __dependency4__["default"]; - // for the side effect of extending Ember.run.queues - var cloneStates = __dependency6__.cloneStates; - var states = __dependency6__.states; - - var CoreView = __dependency7__["default"]; - var View = __dependency8__["default"]; - var ContainerView = __dependency9__["default"]; - var CollectionView = __dependency10__["default"]; - var Component = __dependency11__["default"]; - - var EventDispatcher = __dependency12__["default"]; - var ViewTargetActionSupport = __dependency13__["default"]; - // END IMPORTS - - /** - Alias for jQuery - - @method $ - @for Ember - */ - - // BEGIN EXPORTS - Ember.$ = jQuery; - - Ember.ViewTargetActionSupport = ViewTargetActionSupport; - Ember.RenderBuffer = RenderBuffer; - - var ViewUtils = Ember.ViewUtils = {}; - ViewUtils.isSimpleClick = isSimpleClick; - - Ember.CoreView = CoreView; - Ember.View = View; - Ember.View.states = states; - Ember.View.cloneStates = cloneStates; - - Ember.ContainerView = ContainerView; - Ember.CollectionView = CollectionView; - Ember.Component = Component; - Ember.EventDispatcher = EventDispatcher; - // END EXPORTS - - __exports__["default"] = Ember; - }); -enifed("ember-views/mixins/component_template_deprecation", - ["ember-metal/core","ember-metal/property_get","ember-metal/mixin","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __exports__) { - "use strict"; - var Ember = __dependency1__["default"]; - // Ember.deprecate - var get = __dependency2__.get; - var Mixin = __dependency3__.Mixin; - - /** - The ComponentTemplateDeprecation mixin is used to provide a useful - deprecation warning when using either `template` or `templateName` with - a component. The `template` and `templateName` properties specified at - extend time are moved to `layout` and `layoutName` respectively. - - `Ember.ComponentTemplateDeprecation` is used internally by Ember in - `Ember.Component`. - - @class ComponentTemplateDeprecation - @namespace Ember - */ - __exports__["default"] = Mixin.create({ - /** - @private - - Moves `templateName` to `layoutName` and `template` to `layout` at extend - time if a layout is not also specified. - - Note that this currently modifies the mixin themselves, which is technically - dubious but is practically of little consequence. This may change in the - future. - - @method willMergeMixin - @since 1.4.0 - */ - willMergeMixin: function(props) { - // must call _super here to ensure that the ActionHandler - // mixin is setup properly (moves actions -> _actions) - // - // Calling super is only OK here since we KNOW that - // there is another Mixin loaded first. - this._super.apply(this, arguments); - - var deprecatedProperty, replacementProperty; - var layoutSpecified = (props.layoutName || props.layout || get(this, 'layoutName')); - - if (props.templateName && !layoutSpecified) { - deprecatedProperty = 'templateName'; - replacementProperty = 'layoutName'; - - props.layoutName = props.templateName; - delete props['templateName']; - } - - if (props.template && !layoutSpecified) { - deprecatedProperty = 'template'; - replacementProperty = 'layout'; - - props.layout = props.template; - delete props['template']; - } - - if (deprecatedProperty) { - Ember.deprecate('Do not specify ' + deprecatedProperty + ' on a Component, use ' + replacementProperty + ' instead.', false); - } - } - }); - }); -enifed("ember-views/mixins/view_target_action_support", - ["ember-metal/mixin","ember-runtime/mixins/target_action_support","ember-metal/computed","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __exports__) { - "use strict"; - var Mixin = __dependency1__.Mixin; - var TargetActionSupport = __dependency2__["default"]; - - // ES6TODO: computed should have its own export path so you can do import {defaultTo} from computed - var computed = __dependency3__.computed; - var alias = computed.alias; - - /** - `Ember.ViewTargetActionSupport` is a mixin that can be included in a - view class to add a `triggerAction` method with semantics similar to - the Handlebars `{{action}}` helper. It provides intelligent defaults - for the action's target: the view's controller; and the context that is - sent with the action: the view's context. - - Note: In normal Ember usage, the `{{action}}` helper is usually the best - choice. This mixin is most often useful when you are doing more complex - event handling in custom View subclasses. - - For example: - - ```javascript - App.SaveButtonView = Ember.View.extend(Ember.ViewTargetActionSupport, { - action: 'save', - click: function() { - this.triggerAction(); // Sends the `save` action, along with the current context - // to the current controller - } - }); - ``` - - The `action` can be provided as properties of an optional object argument - to `triggerAction` as well. - - ```javascript - App.SaveButtonView = Ember.View.extend(Ember.ViewTargetActionSupport, { - click: function() { - this.triggerAction({ - action: 'save' - }); // Sends the `save` action, along with the current context - // to the current controller - } - }); - ``` - - @class ViewTargetActionSupport - @namespace Ember - @extends Ember.TargetActionSupport - */ - __exports__["default"] = Mixin.create(TargetActionSupport, { - /** - @property target - */ - target: alias('controller'), - /** - @property actionContext - */ - actionContext: alias('context') - }); - }); -enifed("ember-views/system/action_manager", - ["exports"], - function(__exports__) { - "use strict"; - /** - @module ember - @submodule ember-views - */ - - function ActionManager() {} - - /** - Global action id hash. - - @private - @property registeredActions - @type Object - */ - ActionManager.registeredActions = {}; - - __exports__["default"] = ActionManager; - }); -enifed("ember-views/system/event_dispatcher", - ["ember-metal/core","ember-metal/property_get","ember-metal/property_set","ember-metal/is_none","ember-metal/run_loop","ember-metal/utils","ember-runtime/system/string","ember-runtime/system/object","ember-views/system/jquery","ember-views/system/action_manager","ember-views/views/view","ember-metal/merge","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __dependency11__, __dependency12__, __exports__) { - "use strict"; - /** - @module ember - @submodule ember-views - */ - var Ember = __dependency1__["default"]; - // Ember.assert - - var get = __dependency2__.get; - var set = __dependency3__.set; - var isNone = __dependency4__.isNone; - var run = __dependency5__["default"]; - var typeOf = __dependency6__.typeOf; - var fmt = __dependency7__.fmt; - var EmberObject = __dependency8__["default"]; - var jQuery = __dependency9__["default"]; - var ActionManager = __dependency10__["default"]; - var View = __dependency11__["default"]; - var merge = __dependency12__["default"]; - - //ES6TODO: - // find a better way to do Ember.View.views without global state - - /** - `Ember.EventDispatcher` handles delegating browser events to their - corresponding `Ember.Views.` For example, when you click on a view, - `Ember.EventDispatcher` ensures that that view's `mouseDown` method gets - called. - - @class EventDispatcher - @namespace Ember - @private - @extends Ember.Object - */ - __exports__["default"] = EmberObject.extend({ - - /** - The set of events names (and associated handler function names) to be setup - and dispatched by the `EventDispatcher`. Custom events can added to this list at setup - time, generally via the `Ember.Application.customEvents` hash. Only override this - default set to prevent the EventDispatcher from listening on some events all together. - - This set will be modified by `setup` to also include any events added at that time. - - @property events - @type Object - */ - events: { - touchstart : 'touchStart', - touchmove : 'touchMove', - touchend : 'touchEnd', - touchcancel : 'touchCancel', - keydown : 'keyDown', - keyup : 'keyUp', - keypress : 'keyPress', - mousedown : 'mouseDown', - mouseup : 'mouseUp', - contextmenu : 'contextMenu', - click : 'click', - dblclick : 'doubleClick', - mousemove : 'mouseMove', - focusin : 'focusIn', - focusout : 'focusOut', - mouseenter : 'mouseEnter', - mouseleave : 'mouseLeave', - submit : 'submit', - input : 'input', - change : 'change', - dragstart : 'dragStart', - drag : 'drag', - dragenter : 'dragEnter', - dragleave : 'dragLeave', - dragover : 'dragOver', - drop : 'drop', - dragend : 'dragEnd' - }, - - /** - The root DOM element to which event listeners should be attached. Event - listeners will be attached to the document unless this is overridden. - - Can be specified as a DOMElement or a selector string. - - The default body is a string since this may be evaluated before document.body - exists in the DOM. - - @private - @property rootElement - @type DOMElement - @default 'body' - */ - rootElement: 'body', - - /** - It enables events to be dispatched to the view's `eventManager.` When present, - this object takes precedence over handling of events on the view itself. - - Note that most Ember applications do not use this feature. If your app also - does not use it, consider setting this property to false to gain some performance - improvement by allowing the EventDispatcher to skip the search for the - `eventManager` on the view tree. - - ```javascript - var EventDispatcher = Em.EventDispatcher.extend({ - events: { - click : 'click', - focusin : 'focusIn', - focusout : 'focusOut', - change : 'change' - }, - canDispatchToEventManager: false - }); - container.register('event_dispatcher:main', EventDispatcher); - ``` - - @property canDispatchToEventManager - @type boolean - @default 'true' - @since 1.7.0 - */ - canDispatchToEventManager: true, - - /** - Sets up event listeners for standard browser events. - - This will be called after the browser sends a `DOMContentReady` event. By - default, it will set up all of the listeners on the document body. If you - would like to register the listeners on a different element, set the event - dispatcher's `root` property. - - @private - @method setup - @param addedEvents {Hash} - */ - setup: function(addedEvents, rootElement) { - var event, events = get(this, 'events'); - - merge(events, addedEvents || {}); - - if (!isNone(rootElement)) { - set(this, 'rootElement', rootElement); - } - - rootElement = jQuery(get(this, 'rootElement')); - - Ember.assert(fmt('You cannot use the same root element (%@) multiple times in an Ember.Application', [rootElement.selector || rootElement[0].tagName]), !rootElement.is('.ember-application')); - Ember.assert('You cannot make a new Ember.Application using a root element that is a descendent of an existing Ember.Application', !rootElement.closest('.ember-application').length); - Ember.assert('You cannot make a new Ember.Application using a root element that is an ancestor of an existing Ember.Application', !rootElement.find('.ember-application').length); - - rootElement.addClass('ember-application'); - - Ember.assert('Unable to add "ember-application" class to rootElement. Make sure you set rootElement to the body or an element in the body.', rootElement.is('.ember-application')); - - for (event in events) { - if (events.hasOwnProperty(event)) { - this.setupHandler(rootElement, event, events[event]); - } - } - }, - - /** - Registers an event listener on the rootElement. If the given event is - triggered, the provided event handler will be triggered on the target view. - - If the target view does not implement the event handler, or if the handler - returns `false`, the parent view will be called. The event will continue to - bubble to each successive parent view until it reaches the top. - - @private - @method setupHandler - @param {Element} rootElement - @param {String} event the browser-originated event to listen to - @param {String} eventName the name of the method to call on the view - */ - setupHandler: function(rootElement, event, eventName) { - var self = this; - - rootElement.on(event + '.ember', '.ember-view', function(evt, triggeringManager) { - var view = View.views[this.id]; - var result = true; - - var manager = self.canDispatchToEventManager ? self._findNearestEventManager(view, eventName) : null; - - if (manager && manager !== triggeringManager) { - result = self._dispatchEvent(manager, evt, eventName, view); - } else if (view) { - result = self._bubbleEvent(view, evt, eventName); - } - - return result; - }); - - rootElement.on(event + '.ember', '[data-ember-action]', function(evt) { - var actionId = jQuery(evt.currentTarget).attr('data-ember-action'); - var action = ActionManager.registeredActions[actionId]; - - // We have to check for action here since in some cases, jQuery will trigger - // an event on `removeChild` (i.e. focusout) after we've already torn down the - // action handlers for the view. - if (action && action.eventName === eventName) { - return action.handler(evt); - } - }); - }, - - _findNearestEventManager: function(view, eventName) { - var manager = null; - - while (view) { - manager = get(view, 'eventManager'); - if (manager && manager[eventName]) { break; } - - view = get(view, 'parentView'); - } - - return manager; - }, - - _dispatchEvent: function(object, evt, eventName, view) { - var result = true; - - var handler = object[eventName]; - if (typeOf(handler) === 'function') { - result = run(object, handler, evt, view); - // Do not preventDefault in eventManagers. - evt.stopPropagation(); - } - else { - result = this._bubbleEvent(view, evt, eventName); - } - - return result; - }, - - _bubbleEvent: function(view, evt, eventName) { - return run(view, view.handleEvent, eventName, evt); - }, - - destroy: function() { - var rootElement = get(this, 'rootElement'); - jQuery(rootElement).off('.ember', '**').removeClass('ember-application'); - return this._super(); - }, - - toString: function() { - return '(EventDispatcher)'; - } - }); - }); -enifed("ember-views/system/ext", - ["ember-metal/run_loop"], - function(__dependency1__) { - "use strict"; - /** - @module ember - @submodule ember-views - */ - - var run = __dependency1__["default"]; - - // Add a new named queue for rendering views that happens - // after bindings have synced, and a queue for scheduling actions - // that that should occur after view rendering. - var queues = run.queues; - run._addQueue('render', 'actions'); - run._addQueue('afterRender', 'render'); - }); -enifed("ember-views/system/jquery", - ["ember-metal/core","ember-runtime/system/string","ember-metal/enumerable_utils","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __exports__) { - "use strict"; - var Ember = __dependency1__["default"]; - // Ember.assert - var w = __dependency2__.w; - - // ES6TODO: the functions on EnumerableUtils need their own exports - var forEach = __dependency3__.forEach; - - /** - Ember Views - - @module ember - @submodule ember-views - @requires ember-runtime - @main ember-views - */ - - var jQuery = (Ember.imports && Ember.imports.jQuery) || (this && this.jQuery); - if (!jQuery && typeof eriuqer === 'function') { - jQuery = eriuqer('jquery'); - } - - Ember.assert("Ember Views require jQuery between 1.7 and 2.1", jQuery && (jQuery().jquery.match(/^((1\.(7|8|9|10|11))|(2\.(0|1)))(\.\d+)?(pre|rc\d?)?/) || Ember.ENV.FORCE_JQUERY)); - - /** - @module ember - @submodule ember-views - */ - if (jQuery) { - // http://www.whatwg.org/specs/web-apps/current-work/multipage/dnd.html#dndevents - var dragEvents = w('dragstart drag dragenter dragleave dragover drop dragend'); - - // Copies the `dataTransfer` property from a browser event object onto the - // jQuery event object for the specified events - forEach(dragEvents, function(eventName) { - jQuery.event.fixHooks[eventName] = { props: ['dataTransfer'] }; - }); - } - - __exports__["default"] = jQuery; - }); -enifed("ember-views/system/render_buffer", - ["ember-views/system/jquery","morph","ember-metal/core","ember-metal/platform","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __exports__) { - "use strict"; - /** - @module ember - @submodule ember-views - */ - - var jQuery = __dependency1__["default"]; - var DOMHelper = __dependency2__.DOMHelper; - var Ember = __dependency3__["default"]; - var create = __dependency4__.create; - - // The HTML spec allows for "omitted start tags". These tags are optional - // when their intended child is the first thing in the parent tag. For - // example, this is a tbody start tag: - // - // - // - // - // - // The tbody may be omitted, and the browser will accept and render: - // - //
    - // - // - // However, the omitted start tag will still be added to the DOM. Here - // we test the string and context to see if the browser is about to - // perform this cleanup, but with a special allowance for disregarding - // - ``` - - And associate it by name using a view's `templateName` property: - - ```javascript - AView = Ember.View.extend({ - templateName: 'some-template' - }); - ``` - - If you have nested resources, your Handlebars template will look like this: - - ```html - - ``` - - And `templateName` property: - - ```javascript - AView = Ember.View.extend({ - templateName: 'posts/new' - }); - ``` - - Using a value for `templateName` that does not have a Handlebars template - with a matching `data-template-name` attribute will throw an error. - - For views classes that may have a template later defined (e.g. as the block - portion of a `{{view}}` Handlebars helper call in another template or in - a subclass), you can provide a `defaultTemplate` property set to compiled - template function. If a template is not later provided for the view instance - the `defaultTemplate` value will be used: - - ```javascript - AView = Ember.View.extend({ - defaultTemplate: Ember.Handlebars.compile('I was the default'), - template: null, - templateName: null - }); - ``` - - Will result in instances with an HTML representation of: - - ```html -
    I was the default
    - ``` - - If a `template` or `templateName` is provided it will take precedence over - `defaultTemplate`: - - ```javascript - AView = Ember.View.extend({ - defaultTemplate: Ember.Handlebars.compile('I was the default') - }); - - aView = AView.create({ - template: Ember.Handlebars.compile('I was the template, not default') - }); - ``` - - Will result in the following HTML representation when rendered: - - ```html -
    I was the template, not default
    - ``` - - ## View Context - - The default context of the compiled template is the view's controller: - - ```javascript - AView = Ember.View.extend({ - template: Ember.Handlebars.compile('Hello {{excitedGreeting}}') - }); - - aController = Ember.Object.create({ - firstName: 'Barry', - excitedGreeting: function() { - return this.get("content.firstName") + "!!!" - }.property() - }); - - aView = AView.create({ - controller: aController - }); - ``` - - Will result in an HTML representation of: - - ```html -
    Hello Barry!!!
    - ``` - - A context can also be explicitly supplied through the view's `context` - property. If the view has neither `context` nor `controller` properties, the - `parentView`'s context will be used. - - ## Layouts - - Views can have a secondary template that wraps their main template. Like - primary templates, layouts can be any function that accepts an optional - context parameter and returns a string of HTML that will be inserted inside - view's tag. Views whose HTML element is self closing (e.g. ``) - cannot have a layout and this property will be ignored. - - Most typically in Ember a layout will be a compiled `Ember.Handlebars` - template. - - A view's layout can be set directly with the `layout` property or reference - an existing Handlebars template by name with the `layoutName` property. - - A template used as a layout must contain a single use of the Handlebars - `{{yield}}` helper. The HTML contents of a view's rendered `template` will be - inserted at this location: - - ```javascript - AViewWithLayout = Ember.View.extend({ - layout: Ember.Handlebars.compile("
    {{yield}}
    "), - template: Ember.Handlebars.compile("I got wrapped") - }); - ``` - - Will result in view instances with an HTML representation of: - - ```html -
    -
    - I got wrapped -
    -
    - ``` - - See [Ember.Handlebars.helpers.yield](/api/classes/Ember.Handlebars.helpers.html#method_yield) - for more information. - - ## Responding to Browser Events - - Views can respond to user-initiated events in one of three ways: method - implementation, through an event manager, and through `{{action}}` helper use - in their template or layout. - - ### Method Implementation - - Views can respond to user-initiated events by implementing a method that - matches the event name. A `jQuery.Event` object will be passed as the - argument to this method. - - ```javascript - AView = Ember.View.extend({ - click: function(event) { - // will be called when when an instance's - // rendered element is clicked - } - }); - ``` - - ### Event Managers - - Views can define an object as their `eventManager` property. This object can - then implement methods that match the desired event names. Matching events - that occur on the view's rendered HTML or the rendered HTML of any of its DOM - descendants will trigger this method. A `jQuery.Event` object will be passed - as the first argument to the method and an `Ember.View` object as the - second. The `Ember.View` will be the view whose rendered HTML was interacted - with. This may be the view with the `eventManager` property or one of its - descendent views. - - ```javascript - AView = Ember.View.extend({ - eventManager: Ember.Object.create({ - doubleClick: function(event, view) { - // will be called when when an instance's - // rendered element or any rendering - // of this views's descendent - // elements is clicked - } - }) - }); - ``` - - An event defined for an event manager takes precedence over events of the - same name handled through methods on the view. - - ```javascript - AView = Ember.View.extend({ - mouseEnter: function(event) { - // will never trigger. - }, - eventManager: Ember.Object.create({ - mouseEnter: function(event, view) { - // takes precedence over AView#mouseEnter - } - }) - }); - ``` - - Similarly a view's event manager will take precedence for events of any views - rendered as a descendent. A method name that matches an event name will not - be called if the view instance was rendered inside the HTML representation of - a view that has an `eventManager` property defined that handles events of the - name. Events not handled by the event manager will still trigger method calls - on the descendent. - - ```javascript - var App = Ember.Application.create(); - App.OuterView = Ember.View.extend({ - template: Ember.Handlebars.compile("outer {{#view 'inner'}}inner{{/view}} outer"), - eventManager: Ember.Object.create({ - mouseEnter: function(event, view) { - // view might be instance of either - // OuterView or InnerView depending on - // where on the page the user interaction occured - } - }) - }); - - App.InnerView = Ember.View.extend({ - click: function(event) { - // will be called if rendered inside - // an OuterView because OuterView's - // eventManager doesn't handle click events - }, - mouseEnter: function(event) { - // will never be called if rendered inside - // an OuterView. - } - }); - ``` - - ### Handlebars `{{action}}` Helper - - See [Handlebars.helpers.action](/api/classes/Ember.Handlebars.helpers.html#method_action). - - ### Event Names - - All of the event handling approaches described above respond to the same set - of events. The names of the built-in events are listed below. (The hash of - built-in events exists in `Ember.EventDispatcher`.) Additional, custom events - can be registered by using `Ember.Application.customEvents`. - - Touch events: - - * `touchStart` - * `touchMove` - * `touchEnd` - * `touchCancel` - - Keyboard events - - * `keyDown` - * `keyUp` - * `keyPress` - - Mouse events - - * `mouseDown` - * `mouseUp` - * `contextMenu` - * `click` - * `doubleClick` - * `mouseMove` - * `focusIn` - * `focusOut` - * `mouseEnter` - * `mouseLeave` - - Form events: - - * `submit` - * `change` - * `focusIn` - * `focusOut` - * `input` - - HTML5 drag and drop events: - - * `dragStart` - * `drag` - * `dragEnter` - * `dragLeave` - * `dragOver` - * `dragEnd` - * `drop` - - ## Handlebars `{{view}}` Helper - - Other `Ember.View` instances can be included as part of a view's template by - using the `{{view}}` Handlebars helper. See [Ember.Handlebars.helpers.view](/api/classes/Ember.Handlebars.helpers.html#method_view) - for additional information. - - @class View - @namespace Ember - @extends Ember.CoreView - */ - var View = CoreView.extend({ - - concatenatedProperties: ['classNames', 'classNameBindings', 'attributeBindings'], - - /** - @property isView - @type Boolean - @default true - @static - */ - isView: true, - - // .......................................................... - // TEMPLATE SUPPORT - // - - /** - The name of the template to lookup if no template is provided. - - By default `Ember.View` will lookup a template with this name in - `Ember.TEMPLATES` (a shared global object). - - @property templateName - @type String - @default null - */ - templateName: null, - - /** - The name of the layout to lookup if no layout is provided. - - By default `Ember.View` will lookup a template with this name in - `Ember.TEMPLATES` (a shared global object). - - @property layoutName - @type String - @default null - */ - layoutName: null, - - /** - Used to identify this view during debugging - - @property instrumentDisplay - @type String - */ - instrumentDisplay: computed(function() { - if (this.helperName) { - return '{{' + this.helperName + '}}'; - } - }), - - /** - The template used to render the view. This should be a function that - accepts an optional context parameter and returns a string of HTML that - will be inserted into the DOM relative to its parent view. - - In general, you should set the `templateName` property instead of setting - the template yourself. - - @property template - @type Function - */ - template: computed('templateName', function(key, value) { - if (value !== undefined) { return value; } - - var templateName = get(this, 'templateName'); - var template = this.templateForName(templateName, 'template'); - - Ember.assert("You specified the templateName " + templateName + " for " + this + ", but it did not exist.", !templateName || template); - - return template || get(this, 'defaultTemplate'); - }), - - /** - The controller managing this view. If this property is set, it will be - made available for use by the template. - - @property controller - @type Object - */ - controller: computed('_parentView', function(key) { - var parentView = get(this, '_parentView'); - return parentView ? get(parentView, 'controller') : null; - }), - - /** - A view may contain a layout. A layout is a regular template but - supersedes the `template` property during rendering. It is the - responsibility of the layout template to retrieve the `template` - property from the view (or alternatively, call `Handlebars.helpers.yield`, - `{{yield}}`) to render it in the correct location. - - This is useful for a view that has a shared wrapper, but which delegates - the rendering of the contents of the wrapper to the `template` property - on a subclass. - - @property layout - @type Function - */ - layout: computed(function(key) { - var layoutName = get(this, 'layoutName'); - var layout = this.templateForName(layoutName, 'layout'); - - Ember.assert("You specified the layoutName " + layoutName + " for " + this + ", but it did not exist.", !layoutName || layout); - - return layout || get(this, 'defaultLayout'); - }).property('layoutName'), - - _yield: function(context, options) { - var template = get(this, 'template'); - if (template) { template(context, options); } - }, - - templateForName: function(name, type) { - if (!name) { return; } - Ember.assert("templateNames are not allowed to contain periods: "+name, name.indexOf('.') === -1); - - if (!this.container) { - throw new EmberError('Container was not found when looking up a views template. ' + - 'This is most likely due to manually instantiating an Ember.View. ' + - 'See: http://git.io/EKPpnA'); - } - - return this.container.lookup('template:' + name); - }, - - /** - The object from which templates should access properties. - - This object will be passed to the template function each time the render - method is called, but it is up to the individual function to decide what - to do with it. - - By default, this will be the view's controller. - - @property context - @type Object - */ - context: computed(function(key, value) { - if (arguments.length === 2) { - set(this, '_context', value); - return value; - } else { - return get(this, '_context'); - } - })["volatile"](), - - /** - Private copy of the view's template context. This can be set directly - by Handlebars without triggering the observer that causes the view - to be re-rendered. - - The context of a view is looked up as follows: - - 1. Supplied context (usually by Handlebars) - 2. Specified controller - 3. `parentView`'s context (for a child of a ContainerView) - - The code in Handlebars that overrides the `_context` property first - checks to see whether the view has a specified controller. This is - something of a hack and should be revisited. - - @property _context - @private - */ - _context: computed(function(key) { - var parentView, controller; - - if (controller = get(this, 'controller')) { - return controller; - } - - parentView = this._parentView; - if (parentView) { - return get(parentView, '_context'); - } - - return null; - }), - - /** - If a value that affects template rendering changes, the view should be - re-rendered to reflect the new value. - - @method _contextDidChange - @private - */ - _contextDidChange: observer('context', function() { - this.rerender(); - }), - - /** - If `false`, the view will appear hidden in DOM. - - @property isVisible - @type Boolean - @default null - */ - isVisible: true, - - /** - Array of child views. You should never edit this array directly. - Instead, use `appendChild` and `removeFromParent`. - - @property childViews - @type Array - @default [] - @private - */ - childViews: childViewsProperty, - - _childViews: EMPTY_ARRAY, - - // When it's a virtual view, we need to notify the parent that their - // childViews will change. - _childViewsWillChange: beforeObserver('childViews', function() { - if (this.isVirtual) { - var parentView = get(this, 'parentView'); - if (parentView) { propertyWillChange(parentView, 'childViews'); } - } - }), - - // When it's a virtual view, we need to notify the parent that their - // childViews did change. - _childViewsDidChange: observer('childViews', function() { - if (this.isVirtual) { - var parentView = get(this, 'parentView'); - if (parentView) { propertyDidChange(parentView, 'childViews'); } - } - }), - - /** - Return the nearest ancestor that is an instance of the provided - class. - - @method nearestInstanceOf - @param {Class} klass Subclass of Ember.View (or Ember.View itself) - @return Ember.View - @deprecated - */ - nearestInstanceOf: function(klass) { - Ember.deprecate("nearestInstanceOf is deprecated and will be removed from future releases. Use nearestOfType."); - var view = get(this, 'parentView'); - - while (view) { - if (view instanceof klass) { return view; } - view = get(view, 'parentView'); - } - }, - - /** - Return the nearest ancestor that is an instance of the provided - class or mixin. - - @method nearestOfType - @param {Class,Mixin} klass Subclass of Ember.View (or Ember.View itself), - or an instance of Ember.Mixin. - @return Ember.View - */ - nearestOfType: function(klass) { - var view = get(this, 'parentView'); - var isOfType = klass instanceof Mixin ? - function(view) { return klass.detect(view); } : - function(view) { return klass.detect(view.constructor); }; - - while (view) { - if (isOfType(view)) { return view; } - view = get(view, 'parentView'); - } - }, - - /** - Return the nearest ancestor that has a given property. - - @method nearestWithProperty - @param {String} property A property name - @return Ember.View - */ - nearestWithProperty: function(property) { - var view = get(this, 'parentView'); - - while (view) { - if (property in view) { return view; } - view = get(view, 'parentView'); - } - }, - - /** - Return the nearest ancestor whose parent is an instance of - `klass`. - - @method nearestChildOf - @param {Class} klass Subclass of Ember.View (or Ember.View itself) - @return Ember.View - */ - nearestChildOf: function(klass) { - var view = get(this, 'parentView'); - - while (view) { - if (get(view, 'parentView') instanceof klass) { return view; } - view = get(view, 'parentView'); - } - }, - - /** - When the parent view changes, recursively invalidate `controller` - - @method _parentViewDidChange - @private - */ - _parentViewDidChange: observer('_parentView', function() { - if (this.isDestroying) { return; } - - this.trigger('parentViewDidChange'); - - if (get(this, 'parentView.controller') && !get(this, 'controller')) { - this.notifyPropertyChange('controller'); - } - }), - - _controllerDidChange: observer('controller', function() { - if (this.isDestroying) { return; } - - this.rerender(); - - this.forEachChildView(function(view) { - view.propertyDidChange('controller'); - }); - }), - - cloneKeywords: function() { - var templateData = get(this, 'templateData'); - - var keywords = templateData ? copy(templateData.keywords) : {}; - set(keywords, 'view', this.isVirtual ? keywords.view : this); - set(keywords, '_view', this); - set(keywords, 'controller', get(this, 'controller')); - - return keywords; - }, - - /** - Called on your view when it should push strings of HTML into a - `Ember.RenderBuffer`. Most users will want to override the `template` - or `templateName` properties instead of this method. - - By default, `Ember.View` will look for a function in the `template` - property and invoke it with the value of `context`. The value of - `context` will be the view's controller unless you override it. - - @method render - @param {Ember.RenderBuffer} buffer The render buffer - */ - render: function(buffer) { - // If this view has a layout, it is the responsibility of the - // the layout to render the view's template. Otherwise, render the template - // directly. - var template = get(this, 'layout') || get(this, 'template'); - - if (template) { - var context = get(this, 'context'); - var keywords = this.cloneKeywords(); - var output; - - var data = { - view: this, - buffer: buffer, - isRenderData: true, - keywords: keywords, - insideGroup: get(this, 'templateData.insideGroup') - }; - - // Invoke the template with the provided template context, which - // is the view's controller by default. A hash of data is also passed that provides - // the template with access to the view and render buffer. - - Ember.assert('template must be a function. Did you mean to call Ember.Handlebars.compile("...") or specify templateName instead?', typeof template === 'function'); - // The template should write directly to the render buffer instead - // of returning a string. - output = template(context, { data: data }); - - // If the template returned a string instead of writing to the buffer, - // push the string onto the buffer. - if (output !== undefined) { buffer.push(output); } - } - }, - - /** - Renders the view again. This will work regardless of whether the - view is already in the DOM or not. If the view is in the DOM, the - rendering process will be deferred to give bindings a chance - to synchronize. - - If children were added during the rendering process using `appendChild`, - `rerender` will remove them, because they will be added again - if needed by the next `render`. - - In general, if the display of your view changes, you should modify - the DOM element directly instead of manually calling `rerender`, which can - be slow. - - @method rerender - */ - rerender: function() { - return this.currentState.rerender(this); - }, - - /** - Iterates over the view's `classNameBindings` array, inserts the value - of the specified property into the `classNames` array, then creates an - observer to update the view's element if the bound property ever changes - in the future. - - @method _applyClassNameBindings - @private - */ - _applyClassNameBindings: function(classBindings) { - var classNames = this.classNames; - var elem, newClass, dasherizedClass; - - // Loop through all of the configured bindings. These will be either - // property names ('isUrgent') or property paths relative to the view - // ('content.isUrgent') - forEach(classBindings, function(binding) { - - Ember.assert("classNameBindings must not have spaces in them. Multiple class name bindings can be provided as elements of an array, e.g. ['foo', ':bar']", binding.indexOf(' ') === -1); - - // Variable in which the old class value is saved. The observer function - // closes over this variable, so it knows which string to remove when - // the property changes. - var oldClass; - // Extract just the property name from bindings like 'foo:bar' - var parsedPath = View._parsePropertyPath(binding); - - // Set up an observer on the context. If the property changes, toggle the - // class name. - var observer = function() { - // Get the current value of the property - newClass = this._classStringForProperty(binding); - elem = this.$(); - - // If we had previously added a class to the element, remove it. - if (oldClass) { - elem.removeClass(oldClass); - // Also remove from classNames so that if the view gets rerendered, - // the class doesn't get added back to the DOM. - classNames.removeObject(oldClass); - } - - // If necessary, add a new class. Make sure we keep track of it so - // it can be removed in the future. - if (newClass) { - elem.addClass(newClass); - oldClass = newClass; - } else { - oldClass = null; - } - }; - - // Get the class name for the property at its current value - dasherizedClass = this._classStringForProperty(binding); - - if (dasherizedClass) { - // Ensure that it gets into the classNames array - // so it is displayed when we render. - addObject(classNames, dasherizedClass); - - // Save a reference to the class name so we can remove it - // if the observer fires. Remember that this variable has - // been closed over by the observer. - oldClass = dasherizedClass; - } - - this.registerObserver(this, parsedPath.path, observer); - // Remove className so when the view is rerendered, - // the className is added based on binding reevaluation - this.one('willClearRender', function() { - if (oldClass) { - classNames.removeObject(oldClass); - oldClass = null; - } - }); - - }, this); - }, - - _unspecifiedAttributeBindings: null, - - /** - Iterates through the view's attribute bindings, sets up observers for each, - then applies the current value of the attributes to the passed render buffer. - - @method _applyAttributeBindings - @param {Ember.RenderBuffer} buffer - @private - */ - _applyAttributeBindings: function(buffer, attributeBindings) { - var attributeValue; - var unspecifiedAttributeBindings = this._unspecifiedAttributeBindings = this._unspecifiedAttributeBindings || {}; - - forEach(attributeBindings, function(binding) { - var split = binding.split(':'); - var property = split[0]; - var attributeName = split[1] || property; - - Ember.assert('You cannot use class as an attributeBinding, use classNameBindings instead.', attributeName !== 'class'); - - if (property in this) { - this._setupAttributeBindingObservation(property, attributeName); - - // Determine the current value and add it to the render buffer - // if necessary. - attributeValue = get(this, property); - View.applyAttributeBindings(buffer, attributeName, attributeValue); - } else { - unspecifiedAttributeBindings[property] = attributeName; - } - }, this); - - // Lazily setup setUnknownProperty after attributeBindings are initially applied - this.setUnknownProperty = this._setUnknownProperty; - }, - - _setupAttributeBindingObservation: function(property, attributeName) { - var attributeValue, elem; - - // Create an observer to add/remove/change the attribute if the - // JavaScript property changes. - var observer = function() { - elem = this.$(); - - attributeValue = get(this, property); - - View.applyAttributeBindings(elem, attributeName, attributeValue); - }; - - this.registerObserver(this, property, observer); - }, - - /** - We're using setUnknownProperty as a hook to setup attributeBinding observers for - properties that aren't defined on a view at initialization time. - - Note: setUnknownProperty will only be called once for each property. - - @method setUnknownProperty - @param key - @param value - @private - */ - setUnknownProperty: null, // Gets defined after initialization by _applyAttributeBindings - - _setUnknownProperty: function(key, value) { - var attributeName = this._unspecifiedAttributeBindings && this._unspecifiedAttributeBindings[key]; - if (attributeName) { - this._setupAttributeBindingObservation(key, attributeName); - } - - defineProperty(this, key); - return set(this, key, value); - }, - - /** - Given a property name, returns a dasherized version of that - property name if the property evaluates to a non-falsy value. - - For example, if the view has property `isUrgent` that evaluates to true, - passing `isUrgent` to this method will return `"is-urgent"`. - - @method _classStringForProperty - @param property - @private - */ - _classStringForProperty: function(property) { - var parsedPath = View._parsePropertyPath(property); - var path = parsedPath.path; - - var val = get(this, path); - if (val === undefined && isGlobalPath(path)) { - val = get(Ember.lookup, path); - } - - return View._classStringForValue(path, val, parsedPath.className, parsedPath.falsyClassName); - }, - - // .......................................................... - // ELEMENT SUPPORT - // - - /** - Returns the current DOM element for the view. - - @property element - @type DOMElement - */ - element: null, - - /** - Returns a jQuery object for this view's element. If you pass in a selector - string, this method will return a jQuery object, using the current element - as its buffer. - - For example, calling `view.$('li')` will return a jQuery object containing - all of the `li` elements inside the DOM element of this view. - - @method $ - @param {String} [selector] a jQuery-compatible selector string - @return {jQuery} the jQuery object for the DOM node - */ - $: function(sel) { - return this.currentState.$(this, sel); - }, - - mutateChildViews: function(callback) { - var childViews = this._childViews; - var idx = childViews.length; - var view; - - while(--idx >= 0) { - view = childViews[idx]; - callback(this, view, idx); - } - - return this; - }, - - forEachChildView: function(callback) { - var childViews = this._childViews; - - if (!childViews) { return this; } - - var len = childViews.length; - var view, idx; - - for (idx = 0; idx < len; idx++) { - view = childViews[idx]; - callback(view); - } - - return this; - }, - - /** - Appends the view's element to the specified parent element. - - If the view does not have an HTML representation yet, `createElement()` - will be called automatically. - - Note that this method just schedules the view to be appended; the DOM - element will not be appended to the given element until all bindings have - finished synchronizing. - - This is not typically a function that you will need to call directly when - building your application. You might consider using `Ember.ContainerView` - instead. If you do need to use `appendTo`, be sure that the target element - you are providing is associated with an `Ember.Application` and does not - have an ancestor element that is associated with an Ember view. - - @method appendTo - @param {String|DOMElement|jQuery} A selector, element, HTML string, or jQuery object - @return {Ember.View} receiver - */ - appendTo: function(selector) { - var target = jQuery(selector); - - Ember.assert("You tried to append to (" + selector + ") but that isn't in the DOM", target.length > 0); - Ember.assert("You cannot append to an existing Ember.View. Consider using Ember.ContainerView instead.", !target.is('.ember-view') && !target.parents().is('.ember-view')); - - this.constructor.renderer.appendTo(this, target[0]); - - return this; - }, - - /** - Replaces the content of the specified parent element with this view's - element. If the view does not have an HTML representation yet, - `createElement()` will be called automatically. - - Note that this method just schedules the view to be appended; the DOM - element will not be appended to the given element until all bindings have - finished synchronizing - - @method replaceIn - @param {String|DOMElement|jQuery} target A selector, element, HTML string, or jQuery object - @return {Ember.View} received - */ - replaceIn: function(selector) { - var target = jQuery(selector); - - Ember.assert("You tried to replace in (" + selector + ") but that isn't in the DOM", target.length > 0); - Ember.assert("You cannot replace an existing Ember.View. Consider using Ember.ContainerView instead.", !target.is('.ember-view') && !target.parents().is('.ember-view')); - - this.constructor.renderer.replaceIn(this, target[0]); - - return this; - }, - - /** - Appends the view's element to the document body. If the view does - not have an HTML representation yet, `createElement()` will be called - automatically. - - If your application uses the `rootElement` property, you must append - the view within that element. Rendering views outside of the `rootElement` - is not supported. - - Note that this method just schedules the view to be appended; the DOM - element will not be appended to the document body until all bindings have - finished synchronizing. - - @method append - @return {Ember.View} receiver - */ - append: function() { - return this.appendTo(document.body); - }, - - /** - Removes the view's element from the element to which it is attached. - - @method remove - @return {Ember.View} receiver - */ - remove: function() { - // What we should really do here is wait until the end of the run loop - // to determine if the element has been re-appended to a different - // element. - // In the interim, we will just re-render if that happens. It is more - // important than elements get garbage collected. - if (!this.removedFromDOM) { this.destroyElement(); } - }, - - elementId: null, - - /** - Attempts to discover the element in the parent element. The default - implementation looks for an element with an ID of `elementId` (or the - view's guid if `elementId` is null). You can override this method to - provide your own form of lookup. For example, if you want to discover your - element using a CSS class name instead of an ID. - - @method findElementInParentElement - @param {DOMElement} parentElement The parent's DOM element - @return {DOMElement} The discovered element - */ - findElementInParentElement: function(parentElem) { - var id = "#" + this.elementId; - return jQuery(id)[0] || jQuery(id, parentElem)[0]; - }, - - /** - Creates a DOM representation of the view and all of its child views by - recursively calling the `render()` method. - - After the element has been inserted into the DOM, `didInsertElement` will - be called on this view and all of its child views. - - @method createElement - @return {Ember.View} receiver - */ - createElement: function() { - if (this.element) { return this; } - - this._didCreateElementWithoutMorph = true; - this.constructor.renderer.renderTree(this); - - return this; - }, - - /** - Called when a view is going to insert an element into the DOM. - - @event willInsertElement - */ - willInsertElement: Ember.K, - - /** - Called when the element of the view has been inserted into the DOM - or after the view was re-rendered. Override this function to do any - set up that requires an element in the document body. - - When a view has children, didInsertElement will be called on the - child view(s) first, bubbling upwards through the hierarchy. - - @event didInsertElement - */ - didInsertElement: Ember.K, - - /** - Called when the view is about to rerender, but before anything has - been torn down. This is a good opportunity to tear down any manual - observers you have installed based on the DOM state - - @event willClearRender - */ - willClearRender: Ember.K, - - /** - Destroys any existing element along with the element for any child views - as well. If the view does not currently have a element, then this method - will do nothing. - - If you implement `willDestroyElement()` on your view, then this method will - be invoked on your view before your element is destroyed to give you a - chance to clean up any event handlers, etc. - - If you write a `willDestroyElement()` handler, you can assume that your - `didInsertElement()` handler was called earlier for the same element. - - You should not call or override this method yourself, but you may - want to implement the above callbacks. - - @method destroyElement - @return {Ember.View} receiver - */ - destroyElement: function() { - return this.currentState.destroyElement(this); - }, - - /** - Called when the element of the view is going to be destroyed. Override - this function to do any teardown that requires an element, like removing - event listeners. - - Please note: any property changes made during this event will have no - effect on object observers. - - @event willDestroyElement - */ - willDestroyElement: Ember.K, - - /** - Called when the parentView property has changed. - - @event parentViewDidChange - */ - parentViewDidChange: Ember.K, - - instrumentName: 'view', - - instrumentDetails: function(hash) { - hash.template = get(this, 'templateName'); - this._super(hash); - }, - - beforeRender: function(buffer) {}, - - afterRender: function(buffer) {}, - - applyAttributesToBuffer: function(buffer) { - // Creates observers for all registered class name and attribute bindings, - // then adds them to the element. - var classNameBindings = get(this, 'classNameBindings'); - if (classNameBindings.length) { - this._applyClassNameBindings(classNameBindings); - } - - // Pass the render buffer so the method can apply attributes directly. - // This isn't needed for class name bindings because they use the - // existing classNames infrastructure. - var attributeBindings = get(this, 'attributeBindings'); - if (attributeBindings.length) { - this._applyAttributeBindings(buffer, attributeBindings); - } - - buffer.setClasses(this.classNames); - buffer.id(this.elementId); - - var role = get(this, 'ariaRole'); - if (role) { - buffer.attr('role', role); - } - - if (get(this, 'isVisible') === false) { - buffer.style('display', 'none'); - } - }, - - // .......................................................... - // STANDARD RENDER PROPERTIES - // - - /** - Tag name for the view's outer element. The tag name is only used when an - element is first created. If you change the `tagName` for an element, you - must destroy and recreate the view element. - - By default, the render buffer will use a `
    ` tag for views. - - @property tagName - @type String - @default null - */ - - // We leave this null by default so we can tell the difference between - // the default case and a user-specified tag. - tagName: null, - - /** - The WAI-ARIA role of the control represented by this view. For example, a - button may have a role of type 'button', or a pane may have a role of - type 'alertdialog'. This property is used by assistive software to help - visually challenged users navigate rich web applications. - - The full list of valid WAI-ARIA roles is available at: - [http://www.w3.org/TR/wai-aria/roles#roles_categorization](http://www.w3.org/TR/wai-aria/roles#roles_categorization) - - @property ariaRole - @type String - @default null - */ - ariaRole: null, - - /** - Standard CSS class names to apply to the view's outer element. This - property automatically inherits any class names defined by the view's - superclasses as well. - - @property classNames - @type Array - @default ['ember-view'] - */ - classNames: ['ember-view'], - - /** - A list of properties of the view to apply as class names. If the property - is a string value, the value of that string will be applied as a class - name. - - ```javascript - // Applies the 'high' class to the view element - Ember.View.extend({ - classNameBindings: ['priority'] - priority: 'high' - }); - ``` - - If the value of the property is a Boolean, the name of that property is - added as a dasherized class name. - - ```javascript - // Applies the 'is-urgent' class to the view element - Ember.View.extend({ - classNameBindings: ['isUrgent'] - isUrgent: true - }); - ``` - - If you would prefer to use a custom value instead of the dasherized - property name, you can pass a binding like this: - - ```javascript - // Applies the 'urgent' class to the view element - Ember.View.extend({ - classNameBindings: ['isUrgent:urgent'] - isUrgent: true - }); - ``` - - This list of properties is inherited from the view's superclasses as well. - - @property classNameBindings - @type Array - @default [] - */ - classNameBindings: EMPTY_ARRAY, - - /** - A list of properties of the view to apply as attributes. If the property is - a string value, the value of that string will be applied as the attribute. - - ```javascript - // Applies the type attribute to the element - // with the value "button", like
    - Ember.View.extend({ - attributeBindings: ['type'], - type: 'button' - }); - ``` - - If the value of the property is a Boolean, the name of that property is - added as an attribute. - - ```javascript - // Renders something like
    - Ember.View.extend({ - attributeBindings: ['enabled'], - enabled: true - }); - ``` - - @property attributeBindings - */ - attributeBindings: EMPTY_ARRAY, - - // ....................................................... - // CORE DISPLAY METHODS - // - - /** - Setup a view, but do not finish waking it up. - - * configure `childViews` - * register the view with the global views hash, which is used for event - dispatch - - @method init - @private - */ - init: function() { - if (!this.isVirtual && !this.elementId) { - this.elementId = guidFor(this); - } - - this._super(); - - // setup child views. be sure to clone the child views array first - this._childViews = this._childViews.slice(); - - Ember.assert("Only arrays are allowed for 'classNameBindings'", typeOf(this.classNameBindings) === 'array'); - this.classNameBindings = emberA(this.classNameBindings.slice()); - - Ember.assert("Only arrays are allowed for 'classNames'", typeOf(this.classNames) === 'array'); - this.classNames = emberA(this.classNames.slice()); - }, - - appendChild: function(view, options) { - return this.currentState.appendChild(this, view, options); - }, - - /** - Removes the child view from the parent view. - - @method removeChild - @param {Ember.View} view - @return {Ember.View} receiver - */ - removeChild: function(view) { - // If we're destroying, the entire subtree will be - // freed, and the DOM will be handled separately, - // so no need to mess with childViews. - if (this.isDestroying) { return; } - - // update parent node - set(view, '_parentView', null); - - // remove view from childViews array. - var childViews = this._childViews; - - removeObject(childViews, view); - - this.propertyDidChange('childViews'); // HUH?! what happened to will change? - - return this; - }, - - /** - Removes all children from the `parentView`. - - @method removeAllChildren - @return {Ember.View} receiver - */ - removeAllChildren: function() { - return this.mutateChildViews(function(parentView, view) { - parentView.removeChild(view); - }); - }, - - destroyAllChildren: function() { - return this.mutateChildViews(function(parentView, view) { - view.destroy(); - }); - }, - - /** - Removes the view from its `parentView`, if one is found. Otherwise - does nothing. - - @method removeFromParent - @return {Ember.View} receiver - */ - removeFromParent: function() { - var parent = this._parentView; - - // Remove DOM element from parent - this.remove(); - - if (parent) { parent.removeChild(this); } - return this; - }, - - /** - You must call `destroy` on a view to destroy the view (and all of its - child views). This will remove the view from any parent node, then make - sure that the DOM element managed by the view can be released by the - memory manager. - - @method destroy - */ - destroy: function() { - var childViews = this._childViews; - // get parentView before calling super because it'll be destroyed - var nonVirtualParentView = get(this, 'parentView'); - var viewName = this.viewName; - var childLen, i; - - if (!this._super()) { return; } - - // remove from non-virtual parent view if viewName was specified - if (viewName && nonVirtualParentView) { - nonVirtualParentView.set(viewName, null); - } - - return this; - }, - - /** - Instantiates a view to be added to the childViews array during view - initialization. You generally will not call this method directly unless - you are overriding `createChildViews()`. Note that this method will - automatically configure the correct settings on the new view instance to - act as a child of the parent. - - @method createChildView - @param {Class|String} viewClass - @param {Hash} [attrs] Attributes to add - @return {Ember.View} new instance - */ - createChildView: function(view, attrs) { - if (!view) { - throw new TypeError("createChildViews first argument must exist"); - } - - if (view.isView && view._parentView === this && view.container === this.container) { - return view; - } - - attrs = attrs || {}; - attrs._parentView = this; - - if (CoreView.detect(view)) { - attrs.templateData = attrs.templateData || get(this, 'templateData'); - - attrs.container = this.container; - view = view.create(attrs); - - // don't set the property on a virtual view, as they are invisible to - // consumers of the view API - if (view.viewName) { - set(get(this, 'concreteView'), view.viewName, view); - } - } else if ('string' === typeof view) { - var fullName = 'view:' + view; - var ViewKlass = this.container.lookupFactory(fullName); - - Ember.assert("Could not find view: '" + fullName + "'", !!ViewKlass); - - attrs.templateData = get(this, 'templateData'); - view = ViewKlass.create(attrs); - } else { - Ember.assert('You must pass instance or subclass of View', view.isView); - attrs.container = this.container; - - if (!get(view, 'templateData')) { - attrs.templateData = get(this, 'templateData'); - } - - setProperties(view, attrs); - - } - - return view; - }, - - becameVisible: Ember.K, - becameHidden: Ember.K, - - /** - When the view's `isVisible` property changes, toggle the visibility - element of the actual DOM element. - - @method _isVisibleDidChange - @private - */ - _isVisibleDidChange: observer('isVisible', function() { - if (this._isVisible === get(this, 'isVisible')) { return ; } - run.scheduleOnce('render', this, this._toggleVisibility); - }), - - _toggleVisibility: function() { - var $el = this.$(); - var isVisible = get(this, 'isVisible'); - - if (this._isVisible === isVisible) { return ; } - - // It's important to keep these in sync, even if we don't yet have - // an element in the DOM to manipulate: - this._isVisible = isVisible; - - if (!$el) { return; } - - $el.toggle(isVisible); - - if (this._isAncestorHidden()) { return; } - - if (isVisible) { - this._notifyBecameVisible(); - } else { - this._notifyBecameHidden(); - } - }, - - _notifyBecameVisible: function() { - this.trigger('becameVisible'); - - this.forEachChildView(function(view) { - var isVisible = get(view, 'isVisible'); - - if (isVisible || isVisible === null) { - view._notifyBecameVisible(); - } - }); - }, - - _notifyBecameHidden: function() { - this.trigger('becameHidden'); - this.forEachChildView(function(view) { - var isVisible = get(view, 'isVisible'); - - if (isVisible || isVisible === null) { - view._notifyBecameHidden(); - } - }); - }, - - _isAncestorHidden: function() { - var parent = get(this, 'parentView'); - - while (parent) { - if (get(parent, 'isVisible') === false) { return true; } - - parent = get(parent, 'parentView'); - } - - return false; - }, - transitionTo: function(state, children) { - Ember.deprecate("Ember.View#transitionTo has been deprecated, it is for internal use only"); - this._transitionTo(state, children); - }, - _transitionTo: function(state, children) { - var priorState = this.currentState; - var currentState = this.currentState = this._states[state]; - this._state = state; - - if (priorState && priorState.exit) { priorState.exit(this); } - if (currentState.enter) { currentState.enter(this); } - }, - - // ....................................................... - // EVENT HANDLING - // - - /** - Handle events from `Ember.EventDispatcher` - - @method handleEvent - @param eventName {String} - @param evt {Event} - @private - */ - handleEvent: function(eventName, evt) { - return this.currentState.handleEvent(this, eventName, evt); - }, - - registerObserver: function(root, path, target, observer) { - if (!observer && 'function' === typeof target) { - observer = target; - target = null; - } - - if (!root || typeof root !== 'object') { - return; - } - - var view = this; - var stateCheckedObserver = function() { - view.currentState.invokeObserver(this, observer); - }; - var scheduledObserver = function() { - run.scheduleOnce('render', this, stateCheckedObserver); - }; - - addObserver(root, path, target, scheduledObserver); - - this.one('willClearRender', function() { - removeObserver(root, path, target, scheduledObserver); - }); - } - - }); - deprecateProperty(View.prototype, 'state', '_state'); - deprecateProperty(View.prototype, 'states', '_states'); - - /* - Describe how the specified actions should behave in the various - states that a view can exist in. Possible states: - - * preRender: when a view is first instantiated, and after its - element was destroyed, it is in the preRender state - * inBuffer: once a view has been rendered, but before it has - been inserted into the DOM, it is in the inBuffer state - * hasElement: the DOM representation of the view is created, - and is ready to be inserted - * inDOM: once a view has been inserted into the DOM it is in - the inDOM state. A view spends the vast majority of its - existence in this state. - * destroyed: once a view has been destroyed (using the destroy - method), it is in this state. No further actions can be invoked - on a destroyed view. - */ - - // in the destroyed state, everything is illegal - - // before rendering has begun, all legal manipulations are noops. - - // inside the buffer, legal manipulations are done on the buffer - - // once the view has been inserted into the DOM, legal manipulations - // are done on the DOM element. - - function notifyMutationListeners() { - run.once(View, 'notifyMutationListeners'); - } - - View.reopenClass({ - - /** - Parse a path and return an object which holds the parsed properties. - - For example a path like "content.isEnabled:enabled:disabled" will return the - following object: - - ```javascript - { - path: "content.isEnabled", - className: "enabled", - falsyClassName: "disabled", - classNames: ":enabled:disabled" - } - ``` - - @method _parsePropertyPath - @static - @private - */ - _parsePropertyPath: function(path) { - var split = path.split(':'); - var propertyPath = split[0]; - var classNames = ""; - var className, falsyClassName; - - // check if the property is defined as prop:class or prop:trueClass:falseClass - if (split.length > 1) { - className = split[1]; - if (split.length === 3) { falsyClassName = split[2]; } - - classNames = ':' + className; - if (falsyClassName) { classNames += ":" + falsyClassName; } - } - - return { - path: propertyPath, - classNames: classNames, - className: (className === '') ? undefined : className, - falsyClassName: falsyClassName - }; - }, - - /** - Get the class name for a given value, based on the path, optional - `className` and optional `falsyClassName`. - - - if a `className` or `falsyClassName` has been specified: - - if the value is truthy and `className` has been specified, - `className` is returned - - if the value is falsy and `falsyClassName` has been specified, - `falsyClassName` is returned - - otherwise `null` is returned - - if the value is `true`, the dasherized last part of the supplied path - is returned - - if the value is not `false`, `undefined` or `null`, the `value` - is returned - - if none of the above rules apply, `null` is returned - - @method _classStringForValue - @param path - @param val - @param className - @param falsyClassName - @static - @private - */ - _classStringForValue: function(path, val, className, falsyClassName) { - if(isArray(val)) { - val = get(val, 'length') !== 0; - } - - // When using the colon syntax, evaluate the truthiness or falsiness - // of the value to determine which className to return - if (className || falsyClassName) { - if (className && !!val) { - return className; - - } else if (falsyClassName && !val) { - return falsyClassName; - - } else { - return null; - } - - // If value is a Boolean and true, return the dasherized property - // name. - } else if (val === true) { - // Normalize property path to be suitable for use - // as a class name. For exaple, content.foo.barBaz - // becomes bar-baz. - var parts = path.split('.'); - return dasherize(parts[parts.length-1]); - - // If the value is not false, undefined, or null, return the current - // value of the property. - } else if (val !== false && val != null) { - return val; - - // Nothing to display. Return null so that the old class is removed - // but no new class is added. - } else { - return null; - } - } - }); - - var mutation = EmberObject.extend(Evented).create(); - // TODO MOVE TO RENDERER HOOKS - View.addMutationListener = function(callback) { - mutation.on('change', callback); - }; - - View.removeMutationListener = function(callback) { - mutation.off('change', callback); - }; - - View.notifyMutationListeners = function() { - mutation.trigger('change'); - }; - - /** - Global views hash - - @property views - @static - @type Hash - */ - View.views = {}; - - // If someone overrides the child views computed property when - // defining their class, we want to be able to process the user's - // supplied childViews and then restore the original computed property - // at view initialization time. This happens in Ember.ContainerView's init - // method. - View.childViewsProperty = childViewsProperty; - - View.applyAttributeBindings = function(elem, name, value) { - var type = typeOf(value); - - // if this changes, also change the logic in ember-handlebars/lib/helpers/binding.js - if (name !== 'value' && (type === 'string' || (type === 'number' && !isNaN(value)))) { - if (value !== elem.attr(name)) { - elem.attr(name, value); - } - } else if (name === 'value' || type === 'boolean') { - if (isNone(value) || value === false) { - // `null`, `undefined` or `false` should remove attribute - elem.removeAttr(name); - // In IE8 `prop` couldn't remove attribute when name is `required`. - if (name === 'required') { - elem.removeProp(name); - } else { - elem.prop(name, ''); - } - } else if (value !== elem.prop(name)) { - // value should always be properties - elem.prop(name, value); - } - } else if (!value) { - elem.removeAttr(name); - } - }; - - __exports__["default"] = View; - }); -enifed("ember", - ["ember-metal","ember-runtime","ember-handlebars","ember-views","ember-routing","ember-routing-handlebars","ember-application","ember-extension-support"], - function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__) { - "use strict"; - /* global navigator */ - // require the main entry points for each of these packages - // this is so that the global exports occur properly - - // do this to ensure that Ember.Test is defined properly on the global - // if it is present. - if (Ember.__loader.registry['ember-testing']) { - requireModule('ember-testing'); - } - - /** - Ember - - @module ember - */ - - Ember.deprecate('Usage of Ember is deprecated for Internet Explorer 6 and 7, support will be removed in the next major version.', !navigator.userAgent.match(/MSIE [67]/)); - }); -enifed("morph", - ["./morph/morph","./morph/dom-helper","exports"], - function(__dependency1__, __dependency2__, __exports__) { - "use strict"; - var Morph = __dependency1__["default"]; - var Morph; - __exports__.Morph = Morph; - var DOMHelper = __dependency2__["default"]; - var DOMHelper; - __exports__.DOMHelper = DOMHelper; - }); -enifed("morph/dom-helper", - ["../morph/morph","./dom-helper/build-html-dom","exports"], - function(__dependency1__, __dependency2__, __exports__) { - "use strict"; - var Morph = __dependency1__["default"]; - var buildHTMLDOM = __dependency2__.buildHTMLDOM; - var svgNamespace = __dependency2__.svgNamespace; - var svgHTMLIntegrationPoints = __dependency2__.svgHTMLIntegrationPoints; - - var deletesBlankTextNodes = (function(){ - var element = document.createElement('div'); - element.appendChild( document.createTextNode('') ); - var clonedElement = element.cloneNode(true); - return clonedElement.childNodes.length === 0; - })(); - - var ignoresCheckedAttribute = (function(){ - var element = document.createElement('input'); - element.setAttribute('checked', 'checked'); - var clonedElement = element.cloneNode(false); - return !clonedElement.checked; - })(); - - function isSVG(ns){ - return ns === svgNamespace; - } - - // This is not the namespace of the element, but of - // the elements inside that elements. - function interiorNamespace(element){ - if ( - element && - element.namespaceURI === svgNamespace && - !svgHTMLIntegrationPoints[element.tagName] - ) { - return svgNamespace; - } else { - return null; - } - } - - // The HTML spec allows for "omitted start tags". These tags are optional - // when their intended child is the first thing in the parent tag. For - // example, this is a tbody start tag: - // - //
    - // - // - // - // The tbody may be omitted, and the browser will accept and render: - // - //
    - // - // - // However, the omitted start tag will still be added to the DOM. Here - // we test the string and context to see if the browser is about to - // perform this cleanup. - // - // http://www.whatwg.org/specs/web-apps/current-work/multipage/syntax.html#optional-tags - // describes which tags are omittable. The spec for tbody and colgroup - // explains this behavior: - // - // http://www.whatwg.org/specs/web-apps/current-work/multipage/tables.html#the-tbody-element - // http://www.whatwg.org/specs/web-apps/current-work/multipage/tables.html#the-colgroup-element - // - - var omittedStartTagChildTest = /<([\w:]+)/; - function detectOmittedStartTag(string, contextualElement){ - // Omitted start tags are only inside table tags. - if (contextualElement.tagName === 'TABLE') { - var omittedStartTagChildMatch = omittedStartTagChildTest.exec(string); - if (omittedStartTagChildMatch) { - var omittedStartTagChild = omittedStartTagChildMatch[1]; - // It is already asserted that the contextual element is a table - // and not the proper start tag. Just see if a tag was omitted. - return omittedStartTagChild === 'tr' || - omittedStartTagChild === 'col'; - } - } - } - - function buildSVGDOM(html, dom){ - var div = dom.document.createElement('div'); - div.innerHTML = ''+html+''; - return div.firstChild.childNodes; - } - - /* - * A class wrapping DOM functions to address environment compatibility, - * namespaces, contextual elements for morph un-escaped content - * insertion. - * - * When entering a template, a DOMHelper should be passed: - * - * template(context, { hooks: hooks, dom: new DOMHelper() }); - * - * TODO: support foreignObject as a passed contextual element. It has - * a namespace (svg) that does not match its internal namespace - * (xhtml). - * - * @class DOMHelper - * @constructor - * @param {HTMLDocument} _document The document DOM methods are proxied to - */ - function DOMHelper(_document){ - this.document = _document || window.document; - this.namespace = null; - } - - var prototype = DOMHelper.prototype; - prototype.constructor = DOMHelper; - - prototype.insertBefore = function(element, childElement, referenceChild) { - return element.insertBefore(childElement, referenceChild); - }; - - prototype.appendChild = function(element, childElement) { - return element.appendChild(childElement); - }; - - prototype.appendText = function(element, text) { - return element.appendChild(this.document.createTextNode(text)); - }; - - prototype.setAttribute = function(element, name, value) { - element.setAttribute(name, value); - }; - - if (document.createElementNS) { - // Only opt into namespace detection if a contextualElement - // is passed. - prototype.createElement = function(tagName, contextualElement) { - var namespace = this.namespace; - if (contextualElement) { - if (tagName === 'svg') { - namespace = svgNamespace; - } else { - namespace = interiorNamespace(contextualElement); - } - } - if (namespace) { - return this.document.createElementNS(namespace, tagName); - } else { - return this.document.createElement(tagName); - } - }; - } else { - prototype.createElement = function(tagName) { - return this.document.createElement(tagName); - }; - } - - prototype.setNamespace = function(ns) { - this.namespace = ns; - }; - - prototype.detectNamespace = function(element) { - this.namespace = interiorNamespace(element); - }; - - prototype.createDocumentFragment = function(){ - return this.document.createDocumentFragment(); - }; - - prototype.createTextNode = function(text){ - return this.document.createTextNode(text); - }; - - prototype.repairClonedNode = function(element, blankChildTextNodes, isChecked){ - if (deletesBlankTextNodes && blankChildTextNodes.length > 0) { - for (var i=0, len=blankChildTextNodes.length;i]*selected/; - detectAutoSelectedOption = function detectAutoSelectedOption(select, option, html) { //jshint ignore:line - return select.selectedIndex === 0 && - !detectAutoSelectedOptionRegex.test(html); - }; - } else { - detectAutoSelectedOption = function detectAutoSelectedOption(select, option, html) { //jshint ignore:line - var selectedAttribute = option.getAttribute('selected'); - return select.selectedIndex === 0 && ( - selectedAttribute === null || - ( selectedAttribute !== '' && selectedAttribute.toLowerCase() !== 'selected' ) - ); - }; - } - - // IE 9 and earlier don't allow us to set innerHTML on col, colgroup, frameset, - // html, style, table, tbody, tfoot, thead, title, tr. Detect this and add - // them to an initial list of corrected tags. - // - // Here we are only dealing with the ones which can have child nodes. - // - var tagNamesRequiringInnerHTMLFix, tableNeedsInnerHTMLFix; - var tableInnerHTMLTestElement = document.createElement('table'); - try { - tableInnerHTMLTestElement.innerHTML = ''; - } catch (e) { - } finally { - tableNeedsInnerHTMLFix = (tableInnerHTMLTestElement.childNodes.length === 0); - } - if (tableNeedsInnerHTMLFix) { - tagNamesRequiringInnerHTMLFix = { - colgroup: ['table'], - table: [], - tbody: ['table'], - tfoot: ['table'], - thead: ['table'], - tr: ['table', 'tbody'] - }; - } - - // IE 8 doesn't allow setting innerHTML on a select tag. Detect this and - // add it to the list of corrected tags. - // - var selectInnerHTMLTestElement = document.createElement('select'); - selectInnerHTMLTestElement.innerHTML = ''; - if (selectInnerHTMLTestElement) { - tagNamesRequiringInnerHTMLFix = tagNamesRequiringInnerHTMLFix || {}; - tagNamesRequiringInnerHTMLFix.select = []; - } - - function scriptSafeInnerHTML(element, html) { - // without a leading text node, IE will drop a leading script tag. - html = '­'+html; - - element.innerHTML = html; - - var nodes = element.childNodes; - - // Look for ­ to remove it. - var shyElement = nodes[0]; - while (shyElement.nodeType === 1 && !shyElement.nodeName) { - shyElement = shyElement.firstChild; - } - // At this point it's the actual unicode character. - if (shyElement.nodeType === 3 && shyElement.nodeValue.charAt(0) === "\u00AD") { - var newValue = shyElement.nodeValue.slice(1); - if (newValue.length) { - shyElement.nodeValue = shyElement.nodeValue.slice(1); - } else { - shyElement.parentNode.removeChild(shyElement); - } - } - - return nodes; - } - - function buildDOMWithFix(html, contextualElement){ - var tagName = contextualElement.tagName; - - // Firefox versions < 11 do not have support for element.outerHTML. - var outerHTML = contextualElement.outerHTML || new XMLSerializer().serializeToString(contextualElement); - if (!outerHTML) { - throw "Can't set innerHTML on "+tagName+" in this browser"; - } - - var wrappingTags = tagNamesRequiringInnerHTMLFix[tagName.toLowerCase()]; - var startTag = outerHTML.match(new RegExp("<"+tagName+"([^>]*)>", 'i'))[0]; - var endTag = ''; - - var wrappedHTML = [startTag, html, endTag]; - - var i = wrappingTags.length; - var wrappedDepth = 1 + i; - while(i--) { - wrappedHTML.unshift('<'+wrappingTags[i]+'>'); - wrappedHTML.push(''); - } - - var wrapper = document.createElement('div'); - scriptSafeInnerHTML(wrapper, wrappedHTML.join('')); - var element = wrapper; - while (wrappedDepth--) { - element = element.firstChild; - while (element && element.nodeType !== 1) { - element = element.nextSibling; - } - } - while (element && element.tagName !== tagName) { - element = element.nextSibling; - } - return element ? element.childNodes : []; - } - - var buildDOM; - if (needsShy) { - buildDOM = function buildDOM(html, contextualElement, dom){ - contextualElement = dom.cloneNode(contextualElement, false); - scriptSafeInnerHTML(contextualElement, html); - return contextualElement.childNodes; - }; - } else { - buildDOM = function buildDOM(html, contextualElement, dom){ - contextualElement = dom.cloneNode(contextualElement, false); - contextualElement.innerHTML = html; - return contextualElement.childNodes; - }; - } - - var buildIESafeDOM; - if (tagNamesRequiringInnerHTMLFix || movesWhitespace) { - buildIESafeDOM = function buildIESafeDOM(html, contextualElement, dom) { - // Make a list of the leading text on script nodes. Include - // script tags without any whitespace for easier processing later. - var spacesBefore = []; - var spacesAfter = []; - html = html.replace(/(\s*)()(\s*)/g, function(match, tag, spaces) { - spacesAfter.push(spaces); - return tag; - }); - - // Fetch nodes - var nodes; - if (tagNamesRequiringInnerHTMLFix[contextualElement.tagName.toLowerCase()]) { - // buildDOMWithFix uses string wrappers for problematic innerHTML. - nodes = buildDOMWithFix(html, contextualElement); - } else { - nodes = buildDOM(html, contextualElement, dom); - } - - // Build a list of script tags, the nodes themselves will be - // mutated as we add test nodes. - var i, j, node, nodeScriptNodes; - var scriptNodes = []; - for (i=0;node=nodes[i];i++) { - if (node.nodeType !== 1) { - continue; - } - if (node.tagName === 'SCRIPT') { - scriptNodes.push(node); - } else { - nodeScriptNodes = node.getElementsByTagName('script'); - for (j=0;j 0) { - textNode = dom.document.createTextNode(spaceBefore); - scriptNode.parentNode.insertBefore(textNode, scriptNode); - } - - spaceAfter = spacesAfter[i]; - if (spaceAfter && spaceAfter.length > 0) { - textNode = dom.document.createTextNode(spaceAfter); - scriptNode.parentNode.insertBefore(textNode, scriptNode.nextSibling); - } - } - - return nodes; - }; - } else { - buildIESafeDOM = buildDOM; - } - - // When parsing innerHTML, the browser may set up DOM with some things - // not desired. For example, with a select element context and option - // innerHTML the first option will be marked selected. - // - // This method cleans up some of that, resetting those values back to - // their defaults. - // - function buildSafeDOM(html, contextualElement, dom) { - var childNodes = buildIESafeDOM(html, contextualElement, dom); - - if (contextualElement.tagName === 'SELECT') { - // Walk child nodes - for (var i = 0; childNodes[i]; i++) { - // Find and process the first option child node - if (childNodes[i].tagName === 'OPTION') { - if (detectAutoSelectedOption(childNodes[i].parentNode, childNodes[i], html)) { - // If the first node is selected but does not have an attribute, - // presume it is not really selected. - childNodes[i].parentNode.selectedIndex = -1; - } - break; - } - } - } - - return childNodes; - } - - var buildHTMLDOM; - if (needsIntegrationPointFix) { - buildHTMLDOM = function buildHTMLDOM(html, contextualElement, dom){ - if (svgHTMLIntegrationPoints[contextualElement.tagName]) { - return buildSafeDOM(html, document.createElement('div'), dom); - } else { - return buildSafeDOM(html, contextualElement, dom); - } - }; - } else { - buildHTMLDOM = buildSafeDOM; - } - - __exports__.buildHTMLDOM = buildHTMLDOM; - }); -enifed("morph/morph", - ["exports"], - function(__exports__) { - "use strict"; - var splice = Array.prototype.splice; - - function ensureStartEnd(start, end) { - if (start === null || end === null) { - throw new Error('a fragment parent must have boundary nodes in order to detect insertion'); - } - } - - function ensureContext(contextualElement) { - if (!contextualElement || contextualElement.nodeType !== 1) { - throw new Error('An element node must be provided for a contextualElement, you provided ' + - (contextualElement ? 'nodeType ' + contextualElement.nodeType : 'nothing')); - } - } - - // TODO: this is an internal API, this should be an assert - function Morph(parent, start, end, domHelper, contextualElement) { - if (parent.nodeType === 11) { - ensureStartEnd(start, end); - this.element = null; - } else { - this.element = parent; - } - this._parent = parent; - this.start = start; - this.end = end; - this.domHelper = domHelper; - ensureContext(contextualElement); - this.contextualElement = contextualElement; - this.reset(); - } - - Morph.prototype.reset = function() { - this.text = null; - this.owner = null; - this.morphs = null; - this.before = null; - this.after = null; - this.escaped = true; - }; - - Morph.prototype.parent = function () { - if (!this.element) { - var parent = this.start.parentNode; - if (this._parent !== parent) { - this.element = this._parent = parent; - } - } - return this._parent; - }; - - Morph.prototype.destroy = function () { - if (this.owner) { - this.owner.removeMorph(this); - } else { - clear(this.element || this.parent(), this.start, this.end); - } - }; - - Morph.prototype.removeMorph = function (morph) { - var morphs = this.morphs; - for (var i=0, l=morphs.length; i 0 ? morphs[index-1] : null; - var after = index < morphs.length ? morphs[index] : null; - var start = before === null ? this.start : (before.end === null ? parent.lastChild : before.end.previousSibling); - var end = after === null ? this.end : (after.start === null ? parent.firstChild : after.start.nextSibling); - var morph = new Morph(parent, start, end, this.domHelper, this.contextualElement); - - morph.owner = this; - morph._update(parent, node); - - if (before !== null) { - morph.before = before; - before.end = start.nextSibling; - before.after = morph; - } - - if (after !== null) { - morph.after = after; - after.before = morph; - after.start = end.previousSibling; - } - - this.morphs.splice(index, 0, morph); - return morph; - }; - - Morph.prototype.replace = function (index, removedLength, addedNodes) { - if (this.morphs === null) this.morphs = []; - var parent = this.element || this.parent(); - var morphs = this.morphs; - var before = index > 0 ? morphs[index-1] : null; - var after = index+removedLength < morphs.length ? morphs[index+removedLength] : null; - var start = before === null ? this.start : (before.end === null ? parent.lastChild : before.end.previousSibling); - var end = after === null ? this.end : (after.start === null ? parent.firstChild : after.start.nextSibling); - var addedLength = addedNodes === undefined ? 0 : addedNodes.length; - var args, i, current; - - if (removedLength > 0) { - clear(parent, start, end); - } - - if (addedLength === 0) { - if (before !== null) { - before.after = after; - before.end = end; - } - if (after !== null) { - after.before = before; - after.start = start; - } - morphs.splice(index, removedLength); - return; - } - - args = new Array(addedLength+2); - if (addedLength > 0) { - for (i=0; i " + n.nextStates.map(function(s) { return s.debug() }).join(" or ") + " )"; - }).join(", ") - } - END IF **/ - - // This is a somewhat naive strategy, but should work in a lot of cases - // A better strategy would properly resolve /posts/:id/new and /posts/edit/:id. - // - // This strategy generally prefers more static and less dynamic matching. - // Specifically, it - // - // * prefers fewer stars to more, then - // * prefers using stars for less of the match to more, then - // * prefers fewer dynamic segments to more, then - // * prefers more static segments to more - function sortSolutions(states) { - return states.sort(function(a, b) { - if (a.types.stars !== b.types.stars) { return a.types.stars - b.types.stars; } - - if (a.types.stars) { - if (a.types.statics !== b.types.statics) { return b.types.statics - a.types.statics; } - if (a.types.dynamics !== b.types.dynamics) { return b.types.dynamics - a.types.dynamics; } - } - - if (a.types.dynamics !== b.types.dynamics) { return a.types.dynamics - b.types.dynamics; } - if (a.types.statics !== b.types.statics) { return b.types.statics - a.types.statics; } - - return 0; - }); - } - - function recognizeChar(states, ch) { - var nextStates = []; - - for (var i=0, l=states.length; i 2 && key.slice(keyLength -2) === '[]') { - isArray = true; - key = key.slice(0, keyLength - 2); - if(!queryParams[key]) { - queryParams[key] = []; - } - } - value = pair[1] ? decodeURIComponent(pair[1]) : ''; - } - if (isArray) { - queryParams[key].push(value); - } else { - queryParams[key] = value; - } - } - return queryParams; - }, - - recognize: function(path) { - var states = [ this.rootState ], - pathLen, i, l, queryStart, queryParams = {}, - isSlashDropped = false; - - queryStart = path.indexOf('?'); - if (queryStart !== -1) { - var queryString = path.substr(queryStart + 1, path.length); - path = path.substr(0, queryStart); - queryParams = this.parseQueryString(queryString); - } - - path = decodeURI(path); - - // DEBUG GROUP path - - if (path.charAt(0) !== "/") { path = "/" + path; } - - pathLen = path.length; - if (pathLen > 1 && path.charAt(pathLen - 1) === "/") { - path = path.substr(0, pathLen - 1); - isSlashDropped = true; - } - - for (i=0, l=path.length; i= 0 && proceed; --i) { - var route = routes[i]; - recognizer.add(routes, { as: route.handler }); - proceed = route.path === '/' || route.path === '' || route.handler.slice(-6) === '.index'; - } - }); - }, - - hasRoute: function(route) { - return this.recognizer.hasRoute(route); - }, - - queryParamsTransition: function(changelist, wasTransitioning, oldState, newState) { - var router = this; - - fireQueryParamDidChange(this, newState, changelist); - - if (!wasTransitioning && this.activeTransition) { - // One of the handlers in queryParamsDidChange - // caused a transition. Just return that transition. - return this.activeTransition; - } else { - // Running queryParamsDidChange didn't change anything. - // Just update query params and be on our way. - - // We have to return a noop transition that will - // perform a URL update at the end. This gives - // the user the ability to set the url update - // method (default is replaceState). - var newTransition = new Transition(this); - newTransition.queryParamsOnly = true; - - oldState.queryParams = finalizeQueryParamChange(this, newState.handlerInfos, newState.queryParams, newTransition); - - newTransition.promise = newTransition.promise.then(function(result) { - updateURL(newTransition, oldState, true); - if (router.didTransition) { - router.didTransition(router.currentHandlerInfos); - } - return result; - }, null, promiseLabel("Transition complete")); - return newTransition; - } - }, - - // NOTE: this doesn't really belong here, but here - // it shall remain until our ES6 transpiler can - // handle cyclical deps. - transitionByIntent: function(intent, isIntermediate) { - try { - return getTransitionByIntent.apply(this, arguments); - } catch(e) { - return new Transition(this, intent, null, e); - } - }, - - /** - Clears the current and target route handlers and triggers exit - on each of them starting at the leaf and traversing up through - its ancestors. - */ - reset: function() { - if (this.state) { - forEach(this.state.handlerInfos.slice().reverse(), function(handlerInfo) { - var handler = handlerInfo.handler; - callHook(handler, 'exit'); - }); - } - - this.state = new TransitionState(); - this.currentHandlerInfos = null; - }, - - activeTransition: null, - - /** - var handler = handlerInfo.handler; - The entry point for handling a change to the URL (usually - via the back and forward button). - - Returns an Array of handlers and the parameters associated - with those parameters. - - @param {String} url a URL to process - - @return {Array} an Array of `[handler, parameter]` tuples - */ - handleURL: function(url) { - // Perform a URL-based transition, but don't change - // the URL afterward, since it already happened. - var args = slice.call(arguments); - if (url.charAt(0) !== '/') { args[0] = '/' + url; } - - return doTransition(this, args).method(null); - }, - - /** - Hook point for updating the URL. - - @param {String} url a URL to update to - */ - updateURL: function() { - throw new Error("updateURL is not implemented"); - }, - - /** - Hook point for replacing the current URL, i.e. with replaceState - - By default this behaves the same as `updateURL` - - @param {String} url a URL to update to - */ - replaceURL: function(url) { - this.updateURL(url); - }, - - /** - Transition into the specified named route. - - If necessary, trigger the exit callback on any handlers - that are no longer represented by the target route. - - @param {String} name the name of the route - */ - transitionTo: function(name) { - return doTransition(this, arguments); - }, - - intermediateTransitionTo: function(name) { - return doTransition(this, arguments, true); - }, - - refresh: function(pivotHandler) { - var state = this.activeTransition ? this.activeTransition.state : this.state; - var handlerInfos = state.handlerInfos; - var params = {}; - for (var i = 0, len = handlerInfos.length; i < len; ++i) { - var handlerInfo = handlerInfos[i]; - params[handlerInfo.name] = handlerInfo.params || {}; - } - - log(this, "Starting a refresh transition"); - var intent = new NamedTransitionIntent({ - name: handlerInfos[handlerInfos.length - 1].name, - pivotHandler: pivotHandler || handlerInfos[0].handler, - contexts: [], // TODO collect contexts...? - queryParams: this._changedQueryParams || state.queryParams || {} - }); - - return this.transitionByIntent(intent, false); - }, - - /** - Identical to `transitionTo` except that the current URL will be replaced - if possible. - - This method is intended primarily for use with `replaceState`. - - @param {String} name the name of the route - */ - replaceWith: function(name) { - return doTransition(this, arguments).method('replace'); - }, - - /** - Take a named route and context objects and generate a - URL. - - @param {String} name the name of the route to generate - a URL for - @param {...Object} objects a list of objects to serialize - - @return {String} a URL - */ - generate: function(handlerName) { - - var partitionedArgs = extractQueryParams(slice.call(arguments, 1)), - suppliedParams = partitionedArgs[0], - queryParams = partitionedArgs[1]; - - // Construct a TransitionIntent with the provided params - // and apply it to the present state of the router. - var intent = new NamedTransitionIntent({ name: handlerName, contexts: suppliedParams }); - var state = intent.applyToState(this.state, this.recognizer, this.getHandler); - var params = {}; - - for (var i = 0, len = state.handlerInfos.length; i < len; ++i) { - var handlerInfo = state.handlerInfos[i]; - var handlerParams = handlerInfo.serialize(); - merge(params, handlerParams); - } - params.queryParams = queryParams; - - return this.recognizer.generate(handlerName, params); - }, - - applyIntent: function(handlerName, contexts) { - var intent = new NamedTransitionIntent({ - name: handlerName, - contexts: contexts - }); - - var state = this.activeTransition && this.activeTransition.state || this.state; - return intent.applyToState(state, this.recognizer, this.getHandler); - }, - - isActiveIntent: function(handlerName, contexts, queryParams) { - var targetHandlerInfos = this.state.handlerInfos, - found = false, names, object, handlerInfo, handlerObj, i, len; - - if (!targetHandlerInfos.length) { return false; } - - var targetHandler = targetHandlerInfos[targetHandlerInfos.length - 1].name; - var recogHandlers = this.recognizer.handlersFor(targetHandler); - - var index = 0; - for (len = recogHandlers.length; index < len; ++index) { - handlerInfo = targetHandlerInfos[index]; - if (handlerInfo.name === handlerName) { break; } - } - - if (index === recogHandlers.length) { - // The provided route name isn't even in the route hierarchy. - return false; - } - - var state = new TransitionState(); - state.handlerInfos = targetHandlerInfos.slice(0, index + 1); - recogHandlers = recogHandlers.slice(0, index + 1); - - var intent = new NamedTransitionIntent({ - name: targetHandler, - contexts: contexts - }); - - var newState = intent.applyToHandlers(state, recogHandlers, this.getHandler, targetHandler, true, true); - - var handlersEqual = handlerInfosEqual(newState.handlerInfos, state.handlerInfos); - if (!queryParams || !handlersEqual) { - return handlersEqual; - } - - // Get a hash of QPs that will still be active on new route - var activeQPsOnNewHandler = {}; - merge(activeQPsOnNewHandler, queryParams); - - var activeQueryParams = this.state.queryParams; - for (var key in activeQueryParams) { - if (activeQueryParams.hasOwnProperty(key) && - activeQPsOnNewHandler.hasOwnProperty(key)) { - activeQPsOnNewHandler[key] = activeQueryParams[key]; - } - } - - return handlersEqual && !getChangelist(activeQPsOnNewHandler, queryParams); - }, - - isActive: function(handlerName) { - var partitionedArgs = extractQueryParams(slice.call(arguments, 1)); - return this.isActiveIntent(handlerName, partitionedArgs[0], partitionedArgs[1]); - }, - - trigger: function(name) { - var args = slice.call(arguments); - trigger(this, this.currentHandlerInfos, false, args); - }, - - /** - Hook point for logging transition status updates. - - @param {String} message The message to log. - */ - log: null, - - _willChangeContextEvent: 'willChangeContext', - _triggerWillChangeContext: function(handlerInfos, newTransition) { - trigger(this, handlerInfos, true, [this._willChangeContextEvent, newTransition]); - }, - - _triggerWillLeave: function(handlerInfos, newTransition, leavingChecker) { - trigger(this, handlerInfos, true, ['willLeave', newTransition, leavingChecker]); - } - }; - - /** - @private - - Fires queryParamsDidChange event - */ - function fireQueryParamDidChange(router, newState, queryParamChangelist) { - // If queryParams changed trigger event - if (queryParamChangelist) { - - // This is a little hacky but we need some way of storing - // changed query params given that no activeTransition - // is guaranteed to have occurred. - router._changedQueryParams = queryParamChangelist.all; - trigger(router, newState.handlerInfos, true, ['queryParamsDidChange', queryParamChangelist.changed, queryParamChangelist.all, queryParamChangelist.removed]); - router._changedQueryParams = null; - } - } - - /** - @private - - Takes an Array of `HandlerInfo`s, figures out which ones are - exiting, entering, or changing contexts, and calls the - proper handler hooks. - - For example, consider the following tree of handlers. Each handler is - followed by the URL segment it handles. - - ``` - |~index ("/") - | |~posts ("/posts") - | | |-showPost ("/:id") - | | |-newPost ("/new") - | | |-editPost ("/edit") - | |~about ("/about/:id") - ``` - - Consider the following transitions: - - 1. A URL transition to `/posts/1`. - 1. Triggers the `*model` callbacks on the - `index`, `posts`, and `showPost` handlers - 2. Triggers the `enter` callback on the same - 3. Triggers the `setup` callback on the same - 2. A direct transition to `newPost` - 1. Triggers the `exit` callback on `showPost` - 2. Triggers the `enter` callback on `newPost` - 3. Triggers the `setup` callback on `newPost` - 3. A direct transition to `about` with a specified - context object - 1. Triggers the `exit` callback on `newPost` - and `posts` - 2. Triggers the `serialize` callback on `about` - 3. Triggers the `enter` callback on `about` - 4. Triggers the `setup` callback on `about` - - @param {Router} transition - @param {TransitionState} newState - */ - function setupContexts(router, newState, transition) { - var partition = partitionHandlers(router.state, newState); - - forEach(partition.exited, function(handlerInfo) { - var handler = handlerInfo.handler; - delete handler.context; - - callHook(handler, 'reset', true, transition); - callHook(handler, 'exit', transition); - }); - - var oldState = router.oldState = router.state; - router.state = newState; - var currentHandlerInfos = router.currentHandlerInfos = partition.unchanged.slice(); - - try { - forEach(partition.reset, function(handlerInfo) { - var handler = handlerInfo.handler; - callHook(handler, 'reset', false, transition); - }); - - forEach(partition.updatedContext, function(handlerInfo) { - return handlerEnteredOrUpdated(currentHandlerInfos, handlerInfo, false, transition); - }); - - forEach(partition.entered, function(handlerInfo) { - return handlerEnteredOrUpdated(currentHandlerInfos, handlerInfo, true, transition); - }); - } catch(e) { - router.state = oldState; - router.currentHandlerInfos = oldState.handlerInfos; - throw e; - } - - router.state.queryParams = finalizeQueryParamChange(router, currentHandlerInfos, newState.queryParams, transition); - } - - - /** - @private - - Helper method used by setupContexts. Handles errors or redirects - that may happen in enter/setup. - */ - function handlerEnteredOrUpdated(currentHandlerInfos, handlerInfo, enter, transition) { - - var handler = handlerInfo.handler, - context = handlerInfo.context; - - if (enter) { - callHook(handler, 'enter', transition); - } - if (transition && transition.isAborted) { - throw new TransitionAborted(); - } - - handler.context = context; - callHook(handler, 'contextDidChange'); - - callHook(handler, 'setup', context, transition); - if (transition && transition.isAborted) { - throw new TransitionAborted(); - } - - currentHandlerInfos.push(handlerInfo); - - return true; - } - - - /** - @private - - This function is called when transitioning from one URL to - another to determine which handlers are no longer active, - which handlers are newly active, and which handlers remain - active but have their context changed. - - Take a list of old handlers and new handlers and partition - them into four buckets: - - * unchanged: the handler was active in both the old and - new URL, and its context remains the same - * updated context: the handler was active in both the - old and new URL, but its context changed. The handler's - `setup` method, if any, will be called with the new - context. - * exited: the handler was active in the old URL, but is - no longer active. - * entered: the handler was not active in the old URL, but - is now active. - - The PartitionedHandlers structure has four fields: - - * `updatedContext`: a list of `HandlerInfo` objects that - represent handlers that remain active but have a changed - context - * `entered`: a list of `HandlerInfo` objects that represent - handlers that are newly active - * `exited`: a list of `HandlerInfo` objects that are no - longer active. - * `unchanged`: a list of `HanderInfo` objects that remain active. - - @param {Array[HandlerInfo]} oldHandlers a list of the handler - information for the previous URL (or `[]` if this is the - first handled transition) - @param {Array[HandlerInfo]} newHandlers a list of the handler - information for the new URL - - @return {Partition} - */ - function partitionHandlers(oldState, newState) { - var oldHandlers = oldState.handlerInfos; - var newHandlers = newState.handlerInfos; - - var handlers = { - updatedContext: [], - exited: [], - entered: [], - unchanged: [] - }; - - var handlerChanged, contextChanged = false, i, l; - - for (i=0, l=newHandlers.length; i= 0; --i) { - var handlerInfo = handlerInfos[i]; - merge(params, handlerInfo.params); - if (handlerInfo.handler.inaccessibleByURL) { - urlMethod = null; - } - } - - if (urlMethod) { - params.queryParams = transition._visibleQueryParams || state.queryParams; - var url = router.recognizer.generate(handlerName, params); - - if (urlMethod === 'replace') { - router.replaceURL(url); - } else { - router.updateURL(url); - } - } - } - - /** - @private - - Updates the URL (if necessary) and calls `setupContexts` - to update the router's array of `currentHandlerInfos`. - */ - function finalizeTransition(transition, newState) { - - try { - log(transition.router, transition.sequence, "Resolved all models on destination route; finalizing transition."); - - var router = transition.router, - handlerInfos = newState.handlerInfos, - seq = transition.sequence; - - // Run all the necessary enter/setup/exit hooks - setupContexts(router, newState, transition); - - // Check if a redirect occurred in enter/setup - if (transition.isAborted) { - // TODO: cleaner way? distinguish b/w targetHandlerInfos? - router.state.handlerInfos = router.currentHandlerInfos; - return Promise.reject(logAbort(transition)); - } - - updateURL(transition, newState, transition.intent.url); - - transition.isActive = false; - router.activeTransition = null; - - trigger(router, router.currentHandlerInfos, true, ['didTransition']); - - if (router.didTransition) { - router.didTransition(router.currentHandlerInfos); - } - - log(router, transition.sequence, "TRANSITION COMPLETE."); - - // Resolve with the final handler. - return handlerInfos[handlerInfos.length - 1].handler; - } catch(e) { - if (!((e instanceof TransitionAborted))) { - //var erroneousHandler = handlerInfos.pop(); - var infos = transition.state.handlerInfos; - transition.trigger(true, 'error', e, transition, infos[infos.length-1].handler); - transition.abort(); - } - - throw e; - } - } - - /** - @private - - Begins and returns a Transition based on the provided - arguments. Accepts arguments in the form of both URL - transitions and named transitions. - - @param {Router} router - @param {Array[Object]} args arguments passed to transitionTo, - replaceWith, or handleURL - */ - function doTransition(router, args, isIntermediate) { - // Normalize blank transitions to root URL transitions. - var name = args[0] || '/'; - - var lastArg = args[args.length-1]; - var queryParams = {}; - if (lastArg && lastArg.hasOwnProperty('queryParams')) { - queryParams = pop.call(args).queryParams; - } - - var intent; - if (args.length === 0) { - - log(router, "Updating query params"); - - // A query param update is really just a transition - // into the route you're already on. - var handlerInfos = router.state.handlerInfos; - intent = new NamedTransitionIntent({ - name: handlerInfos[handlerInfos.length - 1].name, - contexts: [], - queryParams: queryParams - }); - - } else if (name.charAt(0) === '/') { - - log(router, "Attempting URL transition to " + name); - intent = new URLTransitionIntent({ url: name }); - - } else { - - log(router, "Attempting transition to " + name); - intent = new NamedTransitionIntent({ - name: args[0], - contexts: slice.call(args, 1), - queryParams: queryParams - }); - } - - return router.transitionByIntent(intent, isIntermediate); - } - - function handlerInfosEqual(handlerInfos, otherHandlerInfos) { - if (handlerInfos.length !== otherHandlerInfos.length) { - return false; - } - - for (var i = 0, len = handlerInfos.length; i < len; ++i) { - if (handlerInfos[i] !== otherHandlerInfos[i]) { - return false; - } - } - return true; - } - - function finalizeQueryParamChange(router, resolvedHandlers, newQueryParams, transition) { - // We fire a finalizeQueryParamChange event which - // gives the new route hierarchy a chance to tell - // us which query params it's consuming and what - // their final values are. If a query param is - // no longer consumed in the final route hierarchy, - // its serialized segment will be removed - // from the URL. - - for (var k in newQueryParams) { - if (newQueryParams.hasOwnProperty(k) && - newQueryParams[k] === null) { - delete newQueryParams[k]; - } - } - - var finalQueryParamsArray = []; - trigger(router, resolvedHandlers, true, ['finalizeQueryParamChange', newQueryParams, finalQueryParamsArray, transition]); - - if (transition) { - transition._visibleQueryParams = {}; - } - - var finalQueryParams = {}; - for (var i = 0, len = finalQueryParamsArray.length; i < len; ++i) { - var qp = finalQueryParamsArray[i]; - finalQueryParams[qp.key] = qp.value; - if (transition && qp.visible !== false) { - transition._visibleQueryParams[qp.key] = qp.value; - } - } - return finalQueryParams; - } - - function notifyExistingHandlers(router, newState, newTransition) { - var oldHandlers = router.state.handlerInfos, - changing = [], - leavingIndex = null, - leaving, leavingChecker, i, oldHandlerLen, oldHandler, newHandler; - - oldHandlerLen = oldHandlers.length; - for (i = 0; i < oldHandlerLen; i++) { - oldHandler = oldHandlers[i]; - newHandler = newState.handlerInfos[i]; - - if (!newHandler || oldHandler.name !== newHandler.name) { - leavingIndex = i; - break; - } - - if (!newHandler.isResolved) { - changing.push(oldHandler); - } - } - - if (leavingIndex !== null) { - leaving = oldHandlers.slice(leavingIndex, oldHandlerLen); - leavingChecker = function(name) { - for (var h = 0, len = leaving.length; h < len; h++) { - if (leaving[h].name === name) { - return true; - } - } - return false; - }; - - router._triggerWillLeave(leaving, newTransition, leavingChecker); - } - - if (changing.length > 0) { - router._triggerWillChangeContext(changing, newTransition); - } - - trigger(router, oldHandlers, true, ['willTransition', newTransition]); - } - - __exports__["default"] = Router; - }); -enifed("router/transition-intent", - ["./utils","exports"], - function(__dependency1__, __exports__) { - "use strict"; - var merge = __dependency1__.merge; - - function TransitionIntent(props) { - this.initialize(props); - - // TODO: wat - this.data = this.data || {}; - } - - TransitionIntent.prototype = { - initialize: null, - applyToState: null - }; - - __exports__["default"] = TransitionIntent; - }); -enifed("router/transition-intent/named-transition-intent", - ["../transition-intent","../transition-state","../handler-info/factory","../utils","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __exports__) { - "use strict"; - var TransitionIntent = __dependency1__["default"]; - var TransitionState = __dependency2__["default"]; - var handlerInfoFactory = __dependency3__["default"]; - var isParam = __dependency4__.isParam; - var extractQueryParams = __dependency4__.extractQueryParams; - var merge = __dependency4__.merge; - var subclass = __dependency4__.subclass; - - __exports__["default"] = subclass(TransitionIntent, { - name: null, - pivotHandler: null, - contexts: null, - queryParams: null, - - initialize: function(props) { - this.name = props.name; - this.pivotHandler = props.pivotHandler; - this.contexts = props.contexts || []; - this.queryParams = props.queryParams; - }, - - applyToState: function(oldState, recognizer, getHandler, isIntermediate) { - - var partitionedArgs = extractQueryParams([this.name].concat(this.contexts)), - pureArgs = partitionedArgs[0], - queryParams = partitionedArgs[1], - handlers = recognizer.handlersFor(pureArgs[0]); - - var targetRouteName = handlers[handlers.length-1].handler; - - return this.applyToHandlers(oldState, handlers, getHandler, targetRouteName, isIntermediate); - }, - - applyToHandlers: function(oldState, handlers, getHandler, targetRouteName, isIntermediate, checkingIfActive) { - - var i, len; - var newState = new TransitionState(); - var objects = this.contexts.slice(0); - - var invalidateIndex = handlers.length; - - // Pivot handlers are provided for refresh transitions - if (this.pivotHandler) { - for (i = 0, len = handlers.length; i < len; ++i) { - if (getHandler(handlers[i].handler) === this.pivotHandler) { - invalidateIndex = i; - break; - } - } - } - - var pivotHandlerFound = !this.pivotHandler; - - for (i = handlers.length - 1; i >= 0; --i) { - var result = handlers[i]; - var name = result.handler; - var handler = getHandler(name); - - var oldHandlerInfo = oldState.handlerInfos[i]; - var newHandlerInfo = null; - - if (result.names.length > 0) { - if (i >= invalidateIndex) { - newHandlerInfo = this.createParamHandlerInfo(name, handler, result.names, objects, oldHandlerInfo); - } else { - newHandlerInfo = this.getHandlerInfoForDynamicSegment(name, handler, result.names, objects, oldHandlerInfo, targetRouteName, i); - } - } else { - // This route has no dynamic segment. - // Therefore treat as a param-based handlerInfo - // with empty params. This will cause the `model` - // hook to be called with empty params, which is desirable. - newHandlerInfo = this.createParamHandlerInfo(name, handler, result.names, objects, oldHandlerInfo); - } - - if (checkingIfActive) { - // If we're performing an isActive check, we want to - // serialize URL params with the provided context, but - // ignore mismatches between old and new context. - newHandlerInfo = newHandlerInfo.becomeResolved(null, newHandlerInfo.context); - var oldContext = oldHandlerInfo && oldHandlerInfo.context; - if (result.names.length > 0 && newHandlerInfo.context === oldContext) { - // If contexts match in isActive test, assume params also match. - // This allows for flexibility in not requiring that every last - // handler provide a `serialize` method - newHandlerInfo.params = oldHandlerInfo && oldHandlerInfo.params; - } - newHandlerInfo.context = oldContext; - } - - var handlerToUse = oldHandlerInfo; - if (i >= invalidateIndex || newHandlerInfo.shouldSupercede(oldHandlerInfo)) { - invalidateIndex = Math.min(i, invalidateIndex); - handlerToUse = newHandlerInfo; - } - - if (isIntermediate && !checkingIfActive) { - handlerToUse = handlerToUse.becomeResolved(null, handlerToUse.context); - } - - newState.handlerInfos.unshift(handlerToUse); - } - - if (objects.length > 0) { - throw new Error("More context objects were passed than there are dynamic segments for the route: " + targetRouteName); - } - - if (!isIntermediate) { - this.invalidateChildren(newState.handlerInfos, invalidateIndex); - } - - merge(newState.queryParams, this.queryParams || {}); - - return newState; - }, - - invalidateChildren: function(handlerInfos, invalidateIndex) { - for (var i = invalidateIndex, l = handlerInfos.length; i < l; ++i) { - var handlerInfo = handlerInfos[i]; - handlerInfos[i] = handlerInfos[i].getUnresolved(); - } - }, - - getHandlerInfoForDynamicSegment: function(name, handler, names, objects, oldHandlerInfo, targetRouteName, i) { - - var numNames = names.length; - var objectToUse; - if (objects.length > 0) { - - // Use the objects provided for this transition. - objectToUse = objects[objects.length - 1]; - if (isParam(objectToUse)) { - return this.createParamHandlerInfo(name, handler, names, objects, oldHandlerInfo); - } else { - objects.pop(); - } - } else if (oldHandlerInfo && oldHandlerInfo.name === name) { - // Reuse the matching oldHandlerInfo - return oldHandlerInfo; - } else { - if (this.preTransitionState) { - var preTransitionHandlerInfo = this.preTransitionState.handlerInfos[i]; - objectToUse = preTransitionHandlerInfo && preTransitionHandlerInfo.context; - } else { - // Ideally we should throw this error to provide maximal - // information to the user that not enough context objects - // were provided, but this proves too cumbersome in Ember - // in cases where inner template helpers are evaluated - // before parent helpers un-render, in which cases this - // error somewhat prematurely fires. - //throw new Error("Not enough context objects were provided to complete a transition to " + targetRouteName + ". Specifically, the " + name + " route needs an object that can be serialized into its dynamic URL segments [" + names.join(', ') + "]"); - return oldHandlerInfo; - } - } - - return handlerInfoFactory('object', { - name: name, - handler: handler, - context: objectToUse, - names: names - }); - }, - - createParamHandlerInfo: function(name, handler, names, objects, oldHandlerInfo) { - var params = {}; - - // Soak up all the provided string/numbers - var numNames = names.length; - while (numNames--) { - - // Only use old params if the names match with the new handler - var oldParams = (oldHandlerInfo && name === oldHandlerInfo.name && oldHandlerInfo.params) || {}; - - var peek = objects[objects.length - 1]; - var paramName = names[numNames]; - if (isParam(peek)) { - params[paramName] = "" + objects.pop(); - } else { - // If we're here, this means only some of the params - // were string/number params, so try and use a param - // value from a previous handler. - if (oldParams.hasOwnProperty(paramName)) { - params[paramName] = oldParams[paramName]; - } else { - throw new Error("You didn't provide enough string/numeric parameters to satisfy all of the dynamic segments for route " + name); - } - } - } - - return handlerInfoFactory('param', { - name: name, - handler: handler, - params: params - }); - } - }); - }); -enifed("router/transition-intent/url-transition-intent", - ["../transition-intent","../transition-state","../handler-info/factory","../utils","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __exports__) { - "use strict"; - var TransitionIntent = __dependency1__["default"]; - var TransitionState = __dependency2__["default"]; - var handlerInfoFactory = __dependency3__["default"]; - var oCreate = __dependency4__.oCreate; - var merge = __dependency4__.merge; - var subclass = __dependency4__.subclass; - - __exports__["default"] = subclass(TransitionIntent, { - url: null, - - initialize: function(props) { - this.url = props.url; - }, - - applyToState: function(oldState, recognizer, getHandler) { - var newState = new TransitionState(); - - var results = recognizer.recognize(this.url), - queryParams = {}, - i, len; - - if (!results) { - throw new UnrecognizedURLError(this.url); - } - - var statesDiffer = false; - - for (i = 0, len = results.length; i < len; ++i) { - var result = results[i]; - var name = result.handler; - var handler = getHandler(name); - - if (handler.inaccessibleByURL) { - throw new UnrecognizedURLError(this.url); - } - - var newHandlerInfo = handlerInfoFactory('param', { - name: name, - handler: handler, - params: result.params - }); - - var oldHandlerInfo = oldState.handlerInfos[i]; - if (statesDiffer || newHandlerInfo.shouldSupercede(oldHandlerInfo)) { - statesDiffer = true; - newState.handlerInfos[i] = newHandlerInfo; - } else { - newState.handlerInfos[i] = oldHandlerInfo; - } - } - - merge(newState.queryParams, results.queryParams); - - return newState; - } - }); - - /** - Promise reject reasons passed to promise rejection - handlers for failed transitions. - */ - function UnrecognizedURLError(message) { - this.message = (message || "UnrecognizedURLError"); - this.name = "UnrecognizedURLError"; - } - }); -enifed("router/transition-state", - ["./handler-info","./utils","rsvp/promise","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __exports__) { - "use strict"; - var ResolvedHandlerInfo = __dependency1__.ResolvedHandlerInfo; - var forEach = __dependency2__.forEach; - var promiseLabel = __dependency2__.promiseLabel; - var callHook = __dependency2__.callHook; - var Promise = __dependency3__["default"]; - - function TransitionState(other) { - this.handlerInfos = []; - this.queryParams = {}; - this.params = {}; - } - - TransitionState.prototype = { - handlerInfos: null, - queryParams: null, - params: null, - - promiseLabel: function(label) { - var targetName = ''; - forEach(this.handlerInfos, function(handlerInfo) { - if (targetName !== '') { - targetName += '.'; - } - targetName += handlerInfo.name; - }); - return promiseLabel("'" + targetName + "': " + label); - }, - - resolve: function(shouldContinue, payload) { - var self = this; - // First, calculate params for this state. This is useful - // information to provide to the various route hooks. - var params = this.params; - forEach(this.handlerInfos, function(handlerInfo) { - params[handlerInfo.name] = handlerInfo.params || {}; - }); - - payload = payload || {}; - payload.resolveIndex = 0; - - var currentState = this; - var wasAborted = false; - - // The prelude RSVP.resolve() asyncs us into the promise land. - return Promise.resolve(null, this.promiseLabel("Start transition")) - .then(resolveOneHandlerInfo, null, this.promiseLabel('Resolve handler'))['catch'](handleError, this.promiseLabel('Handle error')); - - function innerShouldContinue() { - return Promise.resolve(shouldContinue(), currentState.promiseLabel("Check if should continue"))['catch'](function(reason) { - // We distinguish between errors that occurred - // during resolution (e.g. beforeModel/model/afterModel), - // and aborts due to a rejecting promise from shouldContinue(). - wasAborted = true; - return Promise.reject(reason); - }, currentState.promiseLabel("Handle abort")); - } - - function handleError(error) { - // This is the only possible - // reject value of TransitionState#resolve - var handlerInfos = currentState.handlerInfos; - var errorHandlerIndex = payload.resolveIndex >= handlerInfos.length ? - handlerInfos.length - 1 : payload.resolveIndex; - return Promise.reject({ - error: error, - handlerWithError: currentState.handlerInfos[errorHandlerIndex].handler, - wasAborted: wasAborted, - state: currentState - }); - } - - function proceed(resolvedHandlerInfo) { - var wasAlreadyResolved = currentState.handlerInfos[payload.resolveIndex].isResolved; - - // Swap the previously unresolved handlerInfo with - // the resolved handlerInfo - currentState.handlerInfos[payload.resolveIndex++] = resolvedHandlerInfo; - - if (!wasAlreadyResolved) { - // Call the redirect hook. The reason we call it here - // vs. afterModel is so that redirects into child - // routes don't re-run the model hooks for this - // already-resolved route. - var handler = resolvedHandlerInfo.handler; - callHook(handler, 'redirect', resolvedHandlerInfo.context, payload); - } - - // Proceed after ensuring that the redirect hook - // didn't abort this transition by transitioning elsewhere. - return innerShouldContinue().then(resolveOneHandlerInfo, null, currentState.promiseLabel('Resolve handler')); - } - - function resolveOneHandlerInfo() { - if (payload.resolveIndex === currentState.handlerInfos.length) { - // This is is the only possible - // fulfill value of TransitionState#resolve - return { - error: null, - state: currentState - }; - } - - var handlerInfo = currentState.handlerInfos[payload.resolveIndex]; - - return handlerInfo.resolve(innerShouldContinue, payload) - .then(proceed, null, currentState.promiseLabel('Proceed')); - } - } - }; - - __exports__["default"] = TransitionState; - }); -enifed("router/transition", - ["rsvp/promise","./handler-info","./utils","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __exports__) { - "use strict"; - var Promise = __dependency1__["default"]; - var ResolvedHandlerInfo = __dependency2__.ResolvedHandlerInfo; - var trigger = __dependency3__.trigger; - var slice = __dependency3__.slice; - var log = __dependency3__.log; - var promiseLabel = __dependency3__.promiseLabel; - - /** - @private - - A Transition is a thennable (a promise-like object) that represents - an attempt to transition to another route. It can be aborted, either - explicitly via `abort` or by attempting another transition while a - previous one is still underway. An aborted transition can also - be `retry()`d later. - */ - function Transition(router, intent, state, error) { - var transition = this; - this.state = state || router.state; - this.intent = intent; - this.router = router; - this.data = this.intent && this.intent.data || {}; - this.resolvedModels = {}; - this.queryParams = {}; - - if (error) { - this.promise = Promise.reject(error); - return; - } - - if (state) { - this.params = state.params; - this.queryParams = state.queryParams; - this.handlerInfos = state.handlerInfos; - - var len = state.handlerInfos.length; - if (len) { - this.targetName = state.handlerInfos[len-1].name; - } - - for (var i = 0; i < len; ++i) { - var handlerInfo = state.handlerInfos[i]; - - // TODO: this all seems hacky - if (!handlerInfo.isResolved) { break; } - this.pivotHandler = handlerInfo.handler; - } - - this.sequence = Transition.currentSequence++; - this.promise = state.resolve(checkForAbort, this)['catch'](function(result) { - if (result.wasAborted || transition.isAborted) { - return Promise.reject(logAbort(transition)); - } else { - transition.trigger('error', result.error, transition, result.handlerWithError); - transition.abort(); - return Promise.reject(result.error); - } - }, promiseLabel('Handle Abort')); - } else { - this.promise = Promise.resolve(this.state); - this.params = {}; - } - - function checkForAbort() { - if (transition.isAborted) { - return Promise.reject(undefined, promiseLabel("Transition aborted - reject")); - } - } - } - - Transition.currentSequence = 0; - - Transition.prototype = { - targetName: null, - urlMethod: 'update', - intent: null, - params: null, - pivotHandler: null, - resolveIndex: 0, - handlerInfos: null, - resolvedModels: null, - isActive: true, - state: null, - queryParamsOnly: false, - - isTransition: true, - - isExiting: function(handler) { - var handlerInfos = this.handlerInfos; - for (var i = 0, len = handlerInfos.length; i < len; ++i) { - var handlerInfo = handlerInfos[i]; - if (handlerInfo.name === handler || handlerInfo.handler === handler) { - return false; - } - } - return true; - }, - - /** - @public - - The Transition's internal promise. Calling `.then` on this property - is that same as calling `.then` on the Transition object itself, but - this property is exposed for when you want to pass around a - Transition's promise, but not the Transition object itself, since - Transition object can be externally `abort`ed, while the promise - cannot. - */ - promise: null, - - /** - @public - - Custom state can be stored on a Transition's `data` object. - This can be useful for decorating a Transition within an earlier - hook and shared with a later hook. Properties set on `data` will - be copied to new transitions generated by calling `retry` on this - transition. - */ - data: null, - - /** - @public - - A standard promise hook that resolves if the transition - succeeds and rejects if it fails/redirects/aborts. - - Forwards to the internal `promise` property which you can - use in situations where you want to pass around a thennable, - but not the Transition itself. - - @param {Function} onFulfilled - @param {Function} onRejected - @param {String} label optional string for labeling the promise. - Useful for tooling. - @return {Promise} - */ - then: function(onFulfilled, onRejected, label) { - return this.promise.then(onFulfilled, onRejected, label); - }, - - /** - @public - - Forwards to the internal `promise` property which you can - use in situations where you want to pass around a thennable, - but not the Transition itself. - - @method catch - @param {Function} onRejection - @param {String} label optional string for labeling the promise. - Useful for tooling. - @return {Promise} - */ - "catch": function(onRejection, label) { - return this.promise["catch"](onRejection, label); - }, - - /** - @public - - Forwards to the internal `promise` property which you can - use in situations where you want to pass around a thennable, - but not the Transition itself. - - @method finally - @param {Function} callback - @param {String} label optional string for labeling the promise. - Useful for tooling. - @return {Promise} - */ - "finally": function(callback, label) { - return this.promise["finally"](callback, label); - }, - - /** - @public - - Aborts the Transition. Note you can also implicitly abort a transition - by initiating another transition while a previous one is underway. - */ - abort: function() { - if (this.isAborted) { return this; } - log(this.router, this.sequence, this.targetName + ": transition was aborted"); - this.intent.preTransitionState = this.router.state; - this.isAborted = true; - this.isActive = false; - this.router.activeTransition = null; - return this; - }, - - /** - @public - - Retries a previously-aborted transition (making sure to abort the - transition if it's still active). Returns a new transition that - represents the new attempt to transition. - */ - retry: function() { - // TODO: add tests for merged state retry()s - this.abort(); - return this.router.transitionByIntent(this.intent, false); - }, - - /** - @public - - Sets the URL-changing method to be employed at the end of a - successful transition. By default, a new Transition will just - use `updateURL`, but passing 'replace' to this method will - cause the URL to update using 'replaceWith' instead. Omitting - a parameter will disable the URL change, allowing for transitions - that don't update the URL at completion (this is also used for - handleURL, since the URL has already changed before the - transition took place). - - @param {String} method the type of URL-changing method to use - at the end of a transition. Accepted values are 'replace', - falsy values, or any other non-falsy value (which is - interpreted as an updateURL transition). - - @return {Transition} this transition - */ - method: function(method) { - this.urlMethod = method; - return this; - }, - - /** - @public - - Fires an event on the current list of resolved/resolving - handlers within this transition. Useful for firing events - on route hierarchies that haven't fully been entered yet. - - Note: This method is also aliased as `send` - - @param {Boolean} [ignoreFailure=false] a boolean specifying whether unhandled events throw an error - @param {String} name the name of the event to fire - */ - trigger: function (ignoreFailure) { - var args = slice.call(arguments); - if (typeof ignoreFailure === 'boolean') { - args.shift(); - } else { - // Throw errors on unhandled trigger events by default - ignoreFailure = false; - } - trigger(this.router, this.state.handlerInfos.slice(0, this.resolveIndex + 1), ignoreFailure, args); - }, - - /** - @public - - Transitions are aborted and their promises rejected - when redirects occur; this method returns a promise - that will follow any redirects that occur and fulfill - with the value fulfilled by any redirecting transitions - that occur. - - @return {Promise} a promise that fulfills with the same - value that the final redirecting transition fulfills with - */ - followRedirects: function() { - var router = this.router; - return this.promise['catch'](function(reason) { - if (router.activeTransition) { - return router.activeTransition.followRedirects(); - } - return Promise.reject(reason); - }); - }, - - toString: function() { - return "Transition (sequence " + this.sequence + ")"; - }, - - /** - @private - */ - log: function(message) { - log(this.router, this.sequence, message); - } - }; - - // Alias 'trigger' as 'send' - Transition.prototype.send = Transition.prototype.trigger; - - /** - @private - - Logs and returns a TransitionAborted error. - */ - function logAbort(transition) { - log(transition.router, transition.sequence, "detected abort."); - return new TransitionAborted(); - } - - function TransitionAborted(message) { - this.message = (message || "TransitionAborted"); - this.name = "TransitionAborted"; - } - - __exports__.Transition = Transition; - __exports__.logAbort = logAbort; - __exports__.TransitionAborted = TransitionAborted; - }); -enifed("router/utils", - ["exports"], - function(__exports__) { - "use strict"; - var slice = Array.prototype.slice; - - var _isArray; - if (!Array.isArray) { - _isArray = function (x) { - return Object.prototype.toString.call(x) === "[object Array]"; - }; - } else { - _isArray = Array.isArray; - } - - var isArray = _isArray; - __exports__.isArray = isArray; - function merge(hash, other) { - for (var prop in other) { - if (other.hasOwnProperty(prop)) { hash[prop] = other[prop]; } - } - } - - var oCreate = Object.create || function(proto) { - function F() {} - F.prototype = proto; - return new F(); - }; - __exports__.oCreate = oCreate; - /** - @private - - Extracts query params from the end of an array - **/ - function extractQueryParams(array) { - var len = (array && array.length), head, queryParams; - - if(len && len > 0 && array[len - 1] && array[len - 1].hasOwnProperty('queryParams')) { - queryParams = array[len - 1].queryParams; - head = slice.call(array, 0, len - 1); - return [head, queryParams]; - } else { - return [array, null]; - } - } - - __exports__.extractQueryParams = extractQueryParams;/** - @private - - Coerces query param properties and array elements into strings. - **/ - function coerceQueryParamsToString(queryParams) { - for (var key in queryParams) { - if (typeof queryParams[key] === 'number') { - queryParams[key] = '' + queryParams[key]; - } else if (isArray(queryParams[key])) { - for (var i = 0, l = queryParams[key].length; i < l; i++) { - queryParams[key][i] = '' + queryParams[key][i]; - } - } - } - } - /** - @private - */ - function log(router, sequence, msg) { - if (!router.log) { return; } - - if (arguments.length === 3) { - router.log("Transition #" + sequence + ": " + msg); - } else { - msg = sequence; - router.log(msg); - } - } - - __exports__.log = log;function bind(context, fn) { - var boundArgs = arguments; - return function(value) { - var args = slice.call(boundArgs, 2); - args.push(value); - return fn.apply(context, args); - }; - } - - __exports__.bind = bind;function isParam(object) { - return (typeof object === "string" || object instanceof String || typeof object === "number" || object instanceof Number); - } - - - function forEach(array, callback) { - for (var i=0, l=array.length; i=0; i--) { - var handlerInfo = handlerInfos[i], - handler = handlerInfo.handler; - - if (handler.events && handler.events[name]) { - if (handler.events[name].apply(handler, args) === true) { - eventWasHandled = true; - } else { - return; - } - } - } - - if (!eventWasHandled && !ignoreFailure) { - throw new Error("Nothing handled the event '" + name + "'."); - } - } - - __exports__.trigger = trigger;function getChangelist(oldObject, newObject) { - var key; - var results = { - all: {}, - changed: {}, - removed: {} - }; - - merge(results.all, newObject); - - var didChange = false; - coerceQueryParamsToString(oldObject); - coerceQueryParamsToString(newObject); - - // Calculate removals - for (key in oldObject) { - if (oldObject.hasOwnProperty(key)) { - if (!newObject.hasOwnProperty(key)) { - didChange = true; - results.removed[key] = oldObject[key]; - } - } - } - - // Calculate changes - for (key in newObject) { - if (newObject.hasOwnProperty(key)) { - if (isArray(oldObject[key]) && isArray(newObject[key])) { - if (oldObject[key].length !== newObject[key].length) { - results.changed[key] = newObject[key]; - didChange = true; - } else { - for (var i = 0, l = oldObject[key].length; i < l; i++) { - if (oldObject[key][i] !== newObject[key][i]) { - results.changed[key] = newObject[key]; - didChange = true; - } - } - } - } - else { - if (oldObject[key] !== newObject[key]) { - results.changed[key] = newObject[key]; - didChange = true; - } - } - } - } - - return didChange && results; - } - - __exports__.getChangelist = getChangelist;function promiseLabel(label) { - return 'Router: ' + label; - } - - __exports__.promiseLabel = promiseLabel;function subclass(parentConstructor, proto) { - function C(props) { - parentConstructor.call(this, props || {}); - } - C.prototype = oCreate(parentConstructor.prototype); - merge(C.prototype, proto); - return C; - } - - __exports__.subclass = subclass;function resolveHook(obj, hookName) { - if (!obj) { return; } - var underscored = "_" + hookName; - return obj[underscored] && underscored || - obj[hookName] && hookName; - } - - function callHook(obj, hookName) { - var args = slice.call(arguments, 2); - return applyHook(obj, hookName, args); - } - - function applyHook(obj, _hookName, args) { - var hookName = resolveHook(obj, _hookName); - if (hookName) { - return obj[hookName].apply(obj, args); - } - } - - __exports__.merge = merge; - __exports__.slice = slice; - __exports__.isParam = isParam; - __exports__.coerceQueryParamsToString = coerceQueryParamsToString; - __exports__.callHook = callHook; - __exports__.resolveHook = resolveHook; - __exports__.applyHook = applyHook; - }); -enifed("rsvp", - ["./rsvp/promise","./rsvp/events","./rsvp/node","./rsvp/all","./rsvp/all-settled","./rsvp/race","./rsvp/hash","./rsvp/hash-settled","./rsvp/rethrow","./rsvp/defer","./rsvp/config","./rsvp/map","./rsvp/resolve","./rsvp/reject","./rsvp/filter","./rsvp/asap","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __dependency11__, __dependency12__, __dependency13__, __dependency14__, __dependency15__, __dependency16__, __exports__) { - "use strict"; - var Promise = __dependency1__["default"]; - var EventTarget = __dependency2__["default"]; - var denodeify = __dependency3__["default"]; - var all = __dependency4__["default"]; - var allSettled = __dependency5__["default"]; - var race = __dependency6__["default"]; - var hash = __dependency7__["default"]; - var hashSettled = __dependency8__["default"]; - var rethrow = __dependency9__["default"]; - var defer = __dependency10__["default"]; - var config = __dependency11__.config; - var configure = __dependency11__.configure; - var map = __dependency12__["default"]; - var resolve = __dependency13__["default"]; - var reject = __dependency14__["default"]; - var filter = __dependency15__["default"]; - var asap = __dependency16__["default"]; - - config.async = asap; // default async is asap; - var cast = resolve; - function async(callback, arg) { - config.async(callback, arg); - } - - function on() { - config.on.apply(config, arguments); - } - - function off() { - config.off.apply(config, arguments); - } - - // Set up instrumentation through `window.__PROMISE_INTRUMENTATION__` - if (typeof window !== 'undefined' && typeof window['__PROMISE_INSTRUMENTATION__'] === 'object') { - var callbacks = window['__PROMISE_INSTRUMENTATION__']; - configure('instrument', true); - for (var eventName in callbacks) { - if (callbacks.hasOwnProperty(eventName)) { - on(eventName, callbacks[eventName]); - } - } - } - - __exports__.cast = cast; - __exports__.Promise = Promise; - __exports__.EventTarget = EventTarget; - __exports__.all = all; - __exports__.allSettled = allSettled; - __exports__.race = race; - __exports__.hash = hash; - __exports__.hashSettled = hashSettled; - __exports__.rethrow = rethrow; - __exports__.defer = defer; - __exports__.denodeify = denodeify; - __exports__.configure = configure; - __exports__.on = on; - __exports__.off = off; - __exports__.resolve = resolve; - __exports__.reject = reject; - __exports__.async = async; - __exports__.map = map; - __exports__.filter = filter; - }); -enifed("rsvp.umd", - ["./rsvp"], - function(__dependency1__) { - "use strict"; - var Promise = __dependency1__.Promise; - var allSettled = __dependency1__.allSettled; - var hash = __dependency1__.hash; - var hashSettled = __dependency1__.hashSettled; - var denodeify = __dependency1__.denodeify; - var on = __dependency1__.on; - var off = __dependency1__.off; - var map = __dependency1__.map; - var filter = __dependency1__.filter; - var resolve = __dependency1__.resolve; - var reject = __dependency1__.reject; - var rethrow = __dependency1__.rethrow; - var all = __dependency1__.all; - var defer = __dependency1__.defer; - var EventTarget = __dependency1__.EventTarget; - var configure = __dependency1__.configure; - var race = __dependency1__.race; - var async = __dependency1__.async; - - var RSVP = { - 'race': race, - 'Promise': Promise, - 'allSettled': allSettled, - 'hash': hash, - 'hashSettled': hashSettled, - 'denodeify': denodeify, - 'on': on, - 'off': off, - 'map': map, - 'filter': filter, - 'resolve': resolve, - 'reject': reject, - 'all': all, - 'rethrow': rethrow, - 'defer': defer, - 'EventTarget': EventTarget, - 'configure': configure, - 'async': async - }; - - /* global define:true module:true window: true */ - if (typeof enifed === 'function' && enifed['amd']) { - enifed(function() { return RSVP; }); - } else if (typeof module !== 'undefined' && module['exports']) { - module['exports'] = RSVP; - } else if (typeof this !== 'undefined') { - this['RSVP'] = RSVP; - } - }); -enifed("rsvp/-internal", - ["./utils","./instrument","./config","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __exports__) { - "use strict"; - var objectOrFunction = __dependency1__.objectOrFunction; - var isFunction = __dependency1__.isFunction; - - var instrument = __dependency2__["default"]; - - var config = __dependency3__.config; - - function withOwnPromise() { - return new TypeError('A promises callback cannot return that same promise.'); - } - - function noop() {} - - var PENDING = void 0; - var FULFILLED = 1; - var REJECTED = 2; - - var GET_THEN_ERROR = new ErrorObject(); - - function getThen(promise) { - try { - return promise.then; - } catch(error) { - GET_THEN_ERROR.error = error; - return GET_THEN_ERROR; - } - } - - function tryThen(then, value, fulfillmentHandler, rejectionHandler) { - try { - then.call(value, fulfillmentHandler, rejectionHandler); - } catch(e) { - return e; - } - } - - function handleForeignThenable(promise, thenable, then) { - config.async(function(promise) { - var sealed = false; - var error = tryThen(then, thenable, function(value) { - if (sealed) { return; } - sealed = true; - if (thenable !== value) { - resolve(promise, value); - } else { - fulfill(promise, value); - } - }, function(reason) { - if (sealed) { return; } - sealed = true; - - reject(promise, reason); - }, 'Settle: ' + (promise._label || ' unknown promise')); - - if (!sealed && error) { - sealed = true; - reject(promise, error); - } - }, promise); - } - - function handleOwnThenable(promise, thenable) { - if (thenable._state === FULFILLED) { - fulfill(promise, thenable._result); - } else if (promise._state === REJECTED) { - reject(promise, thenable._result); - } else { - subscribe(thenable, undefined, function(value) { - if (thenable !== value) { - resolve(promise, value); - } else { - fulfill(promise, value); - } - }, function(reason) { - reject(promise, reason); - }); - } - } - - function handleMaybeThenable(promise, maybeThenable) { - if (maybeThenable.constructor === promise.constructor) { - handleOwnThenable(promise, maybeThenable); - } else { - var then = getThen(maybeThenable); - - if (then === GET_THEN_ERROR) { - reject(promise, GET_THEN_ERROR.error); - } else if (then === undefined) { - fulfill(promise, maybeThenable); - } else if (isFunction(then)) { - handleForeignThenable(promise, maybeThenable, then); - } else { - fulfill(promise, maybeThenable); - } - } - } - - function resolve(promise, value) { - if (promise === value) { - fulfill(promise, value); - } else if (objectOrFunction(value)) { - handleMaybeThenable(promise, value); - } else { - fulfill(promise, value); - } - } - - function publishRejection(promise) { - if (promise._onerror) { - promise._onerror(promise._result); - } - - publish(promise); - } - - function fulfill(promise, value) { - if (promise._state !== PENDING) { return; } - - promise._result = value; - promise._state = FULFILLED; - - if (promise._subscribers.length === 0) { - if (config.instrument) { - instrument('fulfilled', promise); - } - } else { - config.async(publish, promise); - } - } - - function reject(promise, reason) { - if (promise._state !== PENDING) { return; } - promise._state = REJECTED; - promise._result = reason; - - config.async(publishRejection, promise); - } - - function subscribe(parent, child, onFulfillment, onRejection) { - var subscribers = parent._subscribers; - var length = subscribers.length; - - parent._onerror = null; - - subscribers[length] = child; - subscribers[length + FULFILLED] = onFulfillment; - subscribers[length + REJECTED] = onRejection; - - if (length === 0 && parent._state) { - config.async(publish, parent); - } - } - - function publish(promise) { - var subscribers = promise._subscribers; - var settled = promise._state; - - if (config.instrument) { - instrument(settled === FULFILLED ? 'fulfilled' : 'rejected', promise); - } - - if (subscribers.length === 0) { return; } - - var child, callback, detail = promise._result; - - for (var i = 0; i < subscribers.length; i += 3) { - child = subscribers[i]; - callback = subscribers[i + settled]; - - if (child) { - invokeCallback(settled, child, callback, detail); - } else { - callback(detail); - } - } - - promise._subscribers.length = 0; - } - - function ErrorObject() { - this.error = null; - } - - var TRY_CATCH_ERROR = new ErrorObject(); - - function tryCatch(callback, detail) { - try { - return callback(detail); - } catch(e) { - TRY_CATCH_ERROR.error = e; - return TRY_CATCH_ERROR; - } - } - - function invokeCallback(settled, promise, callback, detail) { - var hasCallback = isFunction(callback), - value, error, succeeded, failed; - - if (hasCallback) { - value = tryCatch(callback, detail); - - if (value === TRY_CATCH_ERROR) { - failed = true; - error = value.error; - value = null; - } else { - succeeded = true; - } - - if (promise === value) { - reject(promise, withOwnPromise()); - return; - } - - } else { - value = detail; - succeeded = true; - } - - if (promise._state !== PENDING) { - // noop - } else if (hasCallback && succeeded) { - resolve(promise, value); - } else if (failed) { - reject(promise, error); - } else if (settled === FULFILLED) { - fulfill(promise, value); - } else if (settled === REJECTED) { - reject(promise, value); - } - } - - function initializePromise(promise, resolver) { - try { - resolver(function resolvePromise(value){ - resolve(promise, value); - }, function rejectPromise(reason) { - reject(promise, reason); - }); - } catch(e) { - reject(promise, e); - } - } - - __exports__.noop = noop; - __exports__.resolve = resolve; - __exports__.reject = reject; - __exports__.fulfill = fulfill; - __exports__.subscribe = subscribe; - __exports__.publish = publish; - __exports__.publishRejection = publishRejection; - __exports__.initializePromise = initializePromise; - __exports__.invokeCallback = invokeCallback; - __exports__.FULFILLED = FULFILLED; - __exports__.REJECTED = REJECTED; - __exports__.PENDING = PENDING; - }); -enifed("rsvp/all-settled", - ["./enumerator","./promise","./utils","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __exports__) { - "use strict"; - var Enumerator = __dependency1__["default"]; - var makeSettledResult = __dependency1__.makeSettledResult; - var Promise = __dependency2__["default"]; - var o_create = __dependency3__.o_create; - - function AllSettled(Constructor, entries, label) { - this._superConstructor(Constructor, entries, false /* don't abort on reject */, label); - } - - AllSettled.prototype = o_create(Enumerator.prototype); - AllSettled.prototype._superConstructor = Enumerator; - AllSettled.prototype._makeResult = makeSettledResult; - AllSettled.prototype._validationError = function() { - return new Error('allSettled must be called with an array'); - }; - - /** - `RSVP.allSettled` is similar to `RSVP.all`, but instead of implementing - a fail-fast method, it waits until all the promises have returned and - shows you all the results. This is useful if you want to handle multiple - promises' failure states together as a set. - - Returns a promise that is fulfilled when all the given promises have been - settled. The return promise is fulfilled with an array of the states of - the promises passed into the `promises` array argument. - - Each state object will either indicate fulfillment or rejection, and - provide the corresponding value or reason. The states will take one of - the following formats: - - ```javascript - { state: 'fulfilled', value: value } - or - { state: 'rejected', reason: reason } - ``` - - Example: - - ```javascript - var promise1 = RSVP.Promise.resolve(1); - var promise2 = RSVP.Promise.reject(new Error('2')); - var promise3 = RSVP.Promise.reject(new Error('3')); - var promises = [ promise1, promise2, promise3 ]; - - RSVP.allSettled(promises).then(function(array){ - // array == [ - // { state: 'fulfilled', value: 1 }, - // { state: 'rejected', reason: Error }, - // { state: 'rejected', reason: Error } - // ] - // Note that for the second item, reason.message will be '2', and for the - // third item, reason.message will be '3'. - }, function(error) { - // Not run. (This block would only be called if allSettled had failed, - // for instance if passed an incorrect argument type.) - }); - ``` - - @method allSettled - @static - @for RSVP - @param {Array} promises - @param {String} label - optional string that describes the promise. - Useful for tooling. - @return {Promise} promise that is fulfilled with an array of the settled - states of the constituent promises. - */ - - __exports__["default"] = function allSettled(entries, label) { - return new AllSettled(Promise, entries, label).promise; - } - }); -enifed("rsvp/all", - ["./promise","exports"], - function(__dependency1__, __exports__) { - "use strict"; - var Promise = __dependency1__["default"]; - - /** - This is a convenient alias for `RSVP.Promise.all`. - - @method all - @static - @for RSVP - @param {Array} array Array of promises. - @param {String} label An optional label. This is useful - for tooling. - */ - __exports__["default"] = function all(array, label) { - return Promise.all(array, label); - } - }); -enifed("rsvp/asap", - ["exports"], - function(__exports__) { - "use strict"; - var len = 0; - - __exports__["default"] = function asap(callback, arg) { - queue[len] = callback; - queue[len + 1] = arg; - len += 2; - if (len === 2) { - // If len is 1, that means that we need to schedule an async flush. - // If additional callbacks are queued before the queue is flushed, they - // will be processed by this flush that we are scheduling. - scheduleFlush(); - } - } - - var browserWindow = (typeof window !== 'undefined') ? window : undefined - var browserGlobal = browserWindow || {}; - var BrowserMutationObserver = browserGlobal.MutationObserver || browserGlobal.WebKitMutationObserver; - - // test for web worker but not in IE10 - var isWorker = typeof Uint8ClampedArray !== 'undefined' && - typeof importScripts !== 'undefined' && - typeof MessageChannel !== 'undefined'; - - // node - function useNextTick() { - return function() { - process.nextTick(flush); - }; - } - - // vertx - function useVertxTimer() { - return function() { - vertxNext(flush); - }; - } - - function useMutationObserver() { - var iterations = 0; - var observer = new BrowserMutationObserver(flush); - var node = document.createTextNode(''); - observer.observe(node, { characterData: true }); - - return function() { - node.data = (iterations = ++iterations % 2); - }; - } - - // web worker - function useMessageChannel() { - var channel = new MessageChannel(); - channel.port1.onmessage = flush; - return function () { - channel.port2.postMessage(0); - }; - } - - function useSetTimeout() { - return function() { - setTimeout(flush, 1); - }; - } - - var queue = new Array(1000); - function flush() { - for (var i = 0; i < len; i+=2) { - var callback = queue[i]; - var arg = queue[i+1]; - - callback(arg); - - queue[i] = undefined; - queue[i+1] = undefined; - } - - len = 0; - } - - function attemptVertex() { - try { - var vertx = eriuqer('vertx'); - var vertxNext = vertx.runOnLoop || vertx.runOnContext; - return useVertxTimer(); - } catch(e) { - return useSetTimeout(); - } - } - - var scheduleFlush; - // Decide what async method to use to triggering processing of queued callbacks: - if (typeof process !== 'undefined' && {}.toString.call(process) === '[object process]') { - scheduleFlush = useNextTick(); - } else if (BrowserMutationObserver) { - scheduleFlush = useMutationObserver(); - } else if (isWorker) { - scheduleFlush = useMessageChannel(); - } else if (browserWindow === undefined && typeof eriuqer === 'function') { - scheduleFlush = attemptVertex(); - } else { - scheduleFlush = useSetTimeout(); - } - }); -enifed("rsvp/config", - ["./events","exports"], - function(__dependency1__, __exports__) { - "use strict"; - var EventTarget = __dependency1__["default"]; - - var config = { - instrument: false - }; - - EventTarget.mixin(config); - - function configure(name, value) { - if (name === 'onerror') { - // handle for legacy users that expect the actual - // error to be passed to their function added via - // `RSVP.configure('onerror', someFunctionHere);` - config.on('error', value); - return; - } - - if (arguments.length === 2) { - config[name] = value; - } else { - return config[name]; - } - } - - __exports__.config = config; - __exports__.configure = configure; - }); -enifed("rsvp/defer", - ["./promise","exports"], - function(__dependency1__, __exports__) { - "use strict"; - var Promise = __dependency1__["default"]; - - /** - `RSVP.defer` returns an object similar to jQuery's `$.Deferred`. - `RSVP.defer` should be used when porting over code reliant on `$.Deferred`'s - interface. New code should use the `RSVP.Promise` constructor instead. - - The object returned from `RSVP.defer` is a plain object with three properties: - - * promise - an `RSVP.Promise`. - * reject - a function that causes the `promise` property on this object to - become rejected - * resolve - a function that causes the `promise` property on this object to - become fulfilled. - - Example: - - ```javascript - var deferred = RSVP.defer(); - - deferred.resolve("Success!"); - - defered.promise.then(function(value){ - // value here is "Success!" - }); - ``` - - @method defer - @static - @for RSVP - @param {String} label optional string for labeling the promise. - Useful for tooling. - @return {Object} - */ - - __exports__["default"] = function defer(label) { - var deferred = { }; - - deferred['promise'] = new Promise(function(resolve, reject) { - deferred['resolve'] = resolve; - deferred['reject'] = reject; - }, label); - - return deferred; - } - }); -enifed("rsvp/enumerator", - ["./utils","./-internal","exports"], - function(__dependency1__, __dependency2__, __exports__) { - "use strict"; - var isArray = __dependency1__.isArray; - var isMaybeThenable = __dependency1__.isMaybeThenable; - - var noop = __dependency2__.noop; - var reject = __dependency2__.reject; - var fulfill = __dependency2__.fulfill; - var subscribe = __dependency2__.subscribe; - var FULFILLED = __dependency2__.FULFILLED; - var REJECTED = __dependency2__.REJECTED; - var PENDING = __dependency2__.PENDING; - - function makeSettledResult(state, position, value) { - if (state === FULFILLED) { - return { - state: 'fulfilled', - value: value - }; - } else { - return { - state: 'rejected', - reason: value - }; - } - } - - __exports__.makeSettledResult = makeSettledResult;function Enumerator(Constructor, input, abortOnReject, label) { - this._instanceConstructor = Constructor; - this.promise = new Constructor(noop, label); - this._abortOnReject = abortOnReject; - - if (this._validateInput(input)) { - this._input = input; - this.length = input.length; - this._remaining = input.length; - - this._init(); - - if (this.length === 0) { - fulfill(this.promise, this._result); - } else { - this.length = this.length || 0; - this._enumerate(); - if (this._remaining === 0) { - fulfill(this.promise, this._result); - } - } - } else { - reject(this.promise, this._validationError()); - } - } - - Enumerator.prototype._validateInput = function(input) { - return isArray(input); - }; - - Enumerator.prototype._validationError = function() { - return new Error('Array Methods must be provided an Array'); - }; - - Enumerator.prototype._init = function() { - this._result = new Array(this.length); - }; - - __exports__["default"] = Enumerator; - - Enumerator.prototype._enumerate = function() { - var length = this.length; - var promise = this.promise; - var input = this._input; - - for (var i = 0; promise._state === PENDING && i < length; i++) { - this._eachEntry(input[i], i); - } - }; - - Enumerator.prototype._eachEntry = function(entry, i) { - var c = this._instanceConstructor; - if (isMaybeThenable(entry)) { - if (entry.constructor === c && entry._state !== PENDING) { - entry._onerror = null; - this._settledAt(entry._state, i, entry._result); - } else { - this._willSettleAt(c.resolve(entry), i); - } - } else { - this._remaining--; - this._result[i] = this._makeResult(FULFILLED, i, entry); - } - }; - - Enumerator.prototype._settledAt = function(state, i, value) { - var promise = this.promise; - - if (promise._state === PENDING) { - this._remaining--; - - if (this._abortOnReject && state === REJECTED) { - reject(promise, value); - } else { - this._result[i] = this._makeResult(state, i, value); - } - } - - if (this._remaining === 0) { - fulfill(promise, this._result); - } - }; - - Enumerator.prototype._makeResult = function(state, i, value) { - return value; - }; - - Enumerator.prototype._willSettleAt = function(promise, i) { - var enumerator = this; - - subscribe(promise, undefined, function(value) { - enumerator._settledAt(FULFILLED, i, value); - }, function(reason) { - enumerator._settledAt(REJECTED, i, reason); - }); - }; - }); -enifed("rsvp/events", - ["exports"], - function(__exports__) { - "use strict"; - function indexOf(callbacks, callback) { - for (var i=0, l=callbacks.length; i 1; - }; - - RSVP.filter(promises, filterFn).then(function(result){ - // result is [ 2, 3 ] - }); - ``` - - If any of the `promises` given to `RSVP.filter` are rejected, the first promise - that is rejected will be given as an argument to the returned promise's - rejection handler. For example: - - ```javascript - var promise1 = RSVP.resolve(1); - var promise2 = RSVP.reject(new Error('2')); - var promise3 = RSVP.reject(new Error('3')); - var promises = [ promise1, promise2, promise3 ]; - - var filterFn = function(item){ - return item > 1; - }; - - RSVP.filter(promises, filterFn).then(function(array){ - // Code here never runs because there are rejected promises! - }, function(reason) { - // reason.message === '2' - }); - ``` - - `RSVP.filter` will also wait for any promises returned from `filterFn`. - For instance, you may want to fetch a list of users then return a subset - of those users based on some asynchronous operation: - - ```javascript - - var alice = { name: 'alice' }; - var bob = { name: 'bob' }; - var users = [ alice, bob ]; - - var promises = users.map(function(user){ - return RSVP.resolve(user); - }); - - var filterFn = function(user){ - // Here, Alice has permissions to create a blog post, but Bob does not. - return getPrivilegesForUser(user).then(function(privs){ - return privs.can_create_blog_post === true; - }); - }; - RSVP.filter(promises, filterFn).then(function(users){ - // true, because the server told us only Alice can create a blog post. - users.length === 1; - // false, because Alice is the only user present in `users` - users[0] === bob; - }); - ``` - - @method filter - @static - @for RSVP - @param {Array} promises - @param {Function} filterFn - function to be called on each resolved value to - filter the final results. - @param {String} label optional string describing the promise. Useful for - tooling. - @return {Promise} - */ - __exports__["default"] = function filter(promises, filterFn, label) { - return Promise.all(promises, label).then(function(values) { - if (!isFunction(filterFn)) { - throw new TypeError("You must pass a function as filter's second argument."); - } - - var length = values.length; - var filtered = new Array(length); - - for (var i = 0; i < length; i++) { - filtered[i] = filterFn(values[i]); - } - - return Promise.all(filtered, label).then(function(filtered) { - var results = new Array(length); - var newLength = 0; - - for (var i = 0; i < length; i++) { - if (filtered[i]) { - results[newLength] = values[i]; - newLength++; - } - } - - results.length = newLength; - - return results; - }); - }); - } - }); -enifed("rsvp/hash-settled", - ["./promise","./enumerator","./promise-hash","./utils","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __exports__) { - "use strict"; - var Promise = __dependency1__["default"]; - var makeSettledResult = __dependency2__.makeSettledResult; - var PromiseHash = __dependency3__["default"]; - var Enumerator = __dependency2__["default"]; - var o_create = __dependency4__.o_create; - - function HashSettled(Constructor, object, label) { - this._superConstructor(Constructor, object, false, label); - } - - HashSettled.prototype = o_create(PromiseHash.prototype); - HashSettled.prototype._superConstructor = Enumerator; - HashSettled.prototype._makeResult = makeSettledResult; - - HashSettled.prototype._validationError = function() { - return new Error('hashSettled must be called with an object'); - }; - - /** - `RSVP.hashSettled` is similar to `RSVP.allSettled`, but takes an object - instead of an array for its `promises` argument. - - Unlike `RSVP.all` or `RSVP.hash`, which implement a fail-fast method, - but like `RSVP.allSettled`, `hashSettled` waits until all the - constituent promises have returned and then shows you all the results - with their states and values/reasons. This is useful if you want to - handle multiple promises' failure states together as a set. - - Returns a promise that is fulfilled when all the given promises have been - settled, or rejected if the passed parameters are invalid. - - The returned promise is fulfilled with a hash that has the same key names as - the `promises` object argument. If any of the values in the object are not - promises, they will be copied over to the fulfilled object and marked with state - 'fulfilled'. - - Example: - - ```javascript - var promises = { - myPromise: RSVP.Promise.resolve(1), - yourPromise: RSVP.Promise.resolve(2), - theirPromise: RSVP.Promise.resolve(3), - notAPromise: 4 - }; - - RSVP.hashSettled(promises).then(function(hash){ - // hash here is an object that looks like: - // { - // myPromise: { state: 'fulfilled', value: 1 }, - // yourPromise: { state: 'fulfilled', value: 2 }, - // theirPromise: { state: 'fulfilled', value: 3 }, - // notAPromise: { state: 'fulfilled', value: 4 } - // } - }); - ``` - - If any of the `promises` given to `RSVP.hash` are rejected, the state will - be set to 'rejected' and the reason for rejection provided. - - Example: - - ```javascript - var promises = { - myPromise: RSVP.Promise.resolve(1), - rejectedPromise: RSVP.Promise.reject(new Error('rejection')), - anotherRejectedPromise: RSVP.Promise.reject(new Error('more rejection')), - }; - - RSVP.hashSettled(promises).then(function(hash){ - // hash here is an object that looks like: - // { - // myPromise: { state: 'fulfilled', value: 1 }, - // rejectedPromise: { state: 'rejected', reason: Error }, - // anotherRejectedPromise: { state: 'rejected', reason: Error }, - // } - // Note that for rejectedPromise, reason.message == 'rejection', - // and for anotherRejectedPromise, reason.message == 'more rejection'. - }); - ``` - - An important note: `RSVP.hashSettled` is intended for plain JavaScript objects that - are just a set of keys and values. `RSVP.hashSettled` will NOT preserve prototype - chains. - - Example: - - ```javascript - function MyConstructor(){ - this.example = RSVP.Promise.resolve('Example'); - } - - MyConstructor.prototype = { - protoProperty: RSVP.Promise.resolve('Proto Property') - }; - - var myObject = new MyConstructor(); - - RSVP.hashSettled(myObject).then(function(hash){ - // protoProperty will not be present, instead you will just have an - // object that looks like: - // { - // example: { state: 'fulfilled', value: 'Example' } - // } - // - // hash.hasOwnProperty('protoProperty'); // false - // 'undefined' === typeof hash.protoProperty - }); - ``` - - @method hashSettled - @for RSVP - @param {Object} promises - @param {String} label optional string that describes the promise. - Useful for tooling. - @return {Promise} promise that is fulfilled when when all properties of `promises` - have been settled. - @static - */ - __exports__["default"] = function hashSettled(object, label) { - return new HashSettled(Promise, object, label).promise; - } - }); -enifed("rsvp/hash", - ["./promise","./promise-hash","exports"], - function(__dependency1__, __dependency2__, __exports__) { - "use strict"; - var Promise = __dependency1__["default"]; - var PromiseHash = __dependency2__["default"]; - - /** - `RSVP.hash` is similar to `RSVP.all`, but takes an object instead of an array - for its `promises` argument. - - Returns a promise that is fulfilled when all the given promises have been - fulfilled, or rejected if any of them become rejected. The returned promise - is fulfilled with a hash that has the same key names as the `promises` object - argument. If any of the values in the object are not promises, they will - simply be copied over to the fulfilled object. - - Example: - - ```javascript - var promises = { - myPromise: RSVP.resolve(1), - yourPromise: RSVP.resolve(2), - theirPromise: RSVP.resolve(3), - notAPromise: 4 - }; - - RSVP.hash(promises).then(function(hash){ - // hash here is an object that looks like: - // { - // myPromise: 1, - // yourPromise: 2, - // theirPromise: 3, - // notAPromise: 4 - // } - }); - ```` - - If any of the `promises` given to `RSVP.hash` are rejected, the first promise - that is rejected will be given as the reason to the rejection handler. - - Example: - - ```javascript - var promises = { - myPromise: RSVP.resolve(1), - rejectedPromise: RSVP.reject(new Error('rejectedPromise')), - anotherRejectedPromise: RSVP.reject(new Error('anotherRejectedPromise')), - }; - - RSVP.hash(promises).then(function(hash){ - // Code here never runs because there are rejected promises! - }, function(reason) { - // reason.message === 'rejectedPromise' - }); - ``` - - An important note: `RSVP.hash` is intended for plain JavaScript objects that - are just a set of keys and values. `RSVP.hash` will NOT preserve prototype - chains. - - Example: - - ```javascript - function MyConstructor(){ - this.example = RSVP.resolve('Example'); - } - - MyConstructor.prototype = { - protoProperty: RSVP.resolve('Proto Property') - }; - - var myObject = new MyConstructor(); - - RSVP.hash(myObject).then(function(hash){ - // protoProperty will not be present, instead you will just have an - // object that looks like: - // { - // example: 'Example' - // } - // - // hash.hasOwnProperty('protoProperty'); // false - // 'undefined' === typeof hash.protoProperty - }); - ``` - - @method hash - @static - @for RSVP - @param {Object} promises - @param {String} label optional string that describes the promise. - Useful for tooling. - @return {Promise} promise that is fulfilled when all properties of `promises` - have been fulfilled, or rejected if any of them become rejected. - */ - __exports__["default"] = function hash(object, label) { - return new PromiseHash(Promise, object, label).promise; - } - }); -enifed("rsvp/instrument", - ["./config","./utils","exports"], - function(__dependency1__, __dependency2__, __exports__) { - "use strict"; - var config = __dependency1__.config; - var now = __dependency2__.now; - - var queue = []; - - function scheduleFlush() { - setTimeout(function() { - var entry; - for (var i = 0; i < queue.length; i++) { - entry = queue[i]; - - var payload = entry.payload; - - payload.guid = payload.key + payload.id; - payload.childGuid = payload.key + payload.childId; - if (payload.error) { - payload.stack = payload.error.stack; - } - - config.trigger(entry.name, entry.payload); - } - queue.length = 0; - }, 50); - } - - __exports__["default"] = function instrument(eventName, promise, child) { - if (1 === queue.push({ - name: eventName, - payload: { - key: promise._guidKey, - id: promise._id, - eventName: eventName, - detail: promise._result, - childId: child && child._id, - label: promise._label, - timeStamp: now(), - error: config["instrument-with-stack"] ? new Error(promise._label) : null - }})) { - scheduleFlush(); - } - } - }); -enifed("rsvp/map", - ["./promise","./utils","exports"], - function(__dependency1__, __dependency2__, __exports__) { - "use strict"; - var Promise = __dependency1__["default"]; - var isFunction = __dependency2__.isFunction; - - /** - `RSVP.map` is similar to JavaScript's native `map` method, except that it - waits for all promises to become fulfilled before running the `mapFn` on - each item in given to `promises`. `RSVP.map` returns a promise that will - become fulfilled with the result of running `mapFn` on the values the promises - become fulfilled with. - - For example: - - ```javascript - - var promise1 = RSVP.resolve(1); - var promise2 = RSVP.resolve(2); - var promise3 = RSVP.resolve(3); - var promises = [ promise1, promise2, promise3 ]; - - var mapFn = function(item){ - return item + 1; - }; - - RSVP.map(promises, mapFn).then(function(result){ - // result is [ 2, 3, 4 ] - }); - ``` - - If any of the `promises` given to `RSVP.map` are rejected, the first promise - that is rejected will be given as an argument to the returned promise's - rejection handler. For example: - - ```javascript - var promise1 = RSVP.resolve(1); - var promise2 = RSVP.reject(new Error('2')); - var promise3 = RSVP.reject(new Error('3')); - var promises = [ promise1, promise2, promise3 ]; - - var mapFn = function(item){ - return item + 1; - }; - - RSVP.map(promises, mapFn).then(function(array){ - // Code here never runs because there are rejected promises! - }, function(reason) { - // reason.message === '2' - }); - ``` - - `RSVP.map` will also wait if a promise is returned from `mapFn`. For example, - say you want to get all comments from a set of blog posts, but you need - the blog posts first because they contain a url to those comments. - - ```javscript - - var mapFn = function(blogPost){ - // getComments does some ajax and returns an RSVP.Promise that is fulfilled - // with some comments data - return getComments(blogPost.comments_url); - }; - - // getBlogPosts does some ajax and returns an RSVP.Promise that is fulfilled - // with some blog post data - RSVP.map(getBlogPosts(), mapFn).then(function(comments){ - // comments is the result of asking the server for the comments - // of all blog posts returned from getBlogPosts() - }); - ``` - - @method map - @static - @for RSVP - @param {Array} promises - @param {Function} mapFn function to be called on each fulfilled promise. - @param {String} label optional string for labeling the promise. - Useful for tooling. - @return {Promise} promise that is fulfilled with the result of calling - `mapFn` on each fulfilled promise or value when they become fulfilled. - The promise will be rejected if any of the given `promises` become rejected. - @static - */ - __exports__["default"] = function map(promises, mapFn, label) { - return Promise.all(promises, label).then(function(values) { - if (!isFunction(mapFn)) { - throw new TypeError("You must pass a function as map's second argument."); - } - - var length = values.length; - var results = new Array(length); - - for (var i = 0; i < length; i++) { - results[i] = mapFn(values[i]); - } - - return Promise.all(results, label); - }); - } - }); -enifed("rsvp/node", - ["./promise","./-internal","./utils","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __exports__) { - "use strict"; - var Promise = __dependency1__["default"]; - var noop = __dependency2__.noop; - var resolve = __dependency2__.resolve; - var reject = __dependency2__.reject; - var isArray = __dependency3__.isArray; - - function Result() { - this.value = undefined; - } - - var ERROR = new Result(); - var GET_THEN_ERROR = new Result(); - - function getThen(obj) { - try { - return obj.then; - } catch(error) { - ERROR.value= error; - return ERROR; - } - } - - - function tryApply(f, s, a) { - try { - f.apply(s, a); - } catch(error) { - ERROR.value = error; - return ERROR; - } - } - - function makeObject(_, argumentNames) { - var obj = {}; - var name; - var i; - var length = _.length; - var args = new Array(length); - - for (var x = 0; x < length; x++) { - args[x] = _[x]; - } - - for (i = 0; i < argumentNames.length; i++) { - name = argumentNames[i]; - obj[name] = args[i + 1]; - } - - return obj; - } - - function arrayResult(_) { - var length = _.length; - var args = new Array(length - 1); - - for (var i = 1; i < length; i++) { - args[i - 1] = _[i]; - } - - return args; - } - - function wrapThenable(then, promise) { - return { - then: function(onFulFillment, onRejection) { - return then.call(promise, onFulFillment, onRejection); - } - }; - } - - /** - `RSVP.denodeify` takes a 'node-style' function and returns a function that - will return an `RSVP.Promise`. You can use `denodeify` in Node.js or the - browser when you'd prefer to use promises over using callbacks. For example, - `denodeify` transforms the following: - - ```javascript - var fs = require('fs'); - - fs.readFile('myfile.txt', function(err, data){ - if (err) return handleError(err); - handleData(data); - }); - ``` - - into: - - ```javascript - var fs = require('fs'); - var readFile = RSVP.denodeify(fs.readFile); - - readFile('myfile.txt').then(handleData, handleError); - ``` - - If the node function has multiple success parameters, then `denodeify` - just returns the first one: - - ```javascript - var request = RSVP.denodeify(require('request')); - - request('http://example.com').then(function(res) { - // ... - }); - ``` - - However, if you need all success parameters, setting `denodeify`'s - second parameter to `true` causes it to return all success parameters - as an array: - - ```javascript - var request = RSVP.denodeify(require('request'), true); - - request('http://example.com').then(function(result) { - // result[0] -> res - // result[1] -> body - }); - ``` - - Or if you pass it an array with names it returns the parameters as a hash: - - ```javascript - var request = RSVP.denodeify(require('request'), ['res', 'body']); - - request('http://example.com').then(function(result) { - // result.res - // result.body - }); - ``` - - Sometimes you need to retain the `this`: - - ```javascript - var app = require('express')(); - var render = RSVP.denodeify(app.render.bind(app)); - ``` - - The denodified function inherits from the original function. It works in all - environments, except IE 10 and below. Consequently all properties of the original - function are available to you. However, any properties you change on the - denodeified function won't be changed on the original function. Example: - - ```javascript - var request = RSVP.denodeify(require('request')), - cookieJar = request.jar(); // <- Inheritance is used here - - request('http://example.com', {jar: cookieJar}).then(function(res) { - // cookieJar.cookies holds now the cookies returned by example.com - }); - ``` - - Using `denodeify` makes it easier to compose asynchronous operations instead - of using callbacks. For example, instead of: - - ```javascript - var fs = require('fs'); - - fs.readFile('myfile.txt', function(err, data){ - if (err) { ... } // Handle error - fs.writeFile('myfile2.txt', data, function(err){ - if (err) { ... } // Handle error - console.log('done') - }); - }); - ``` - - you can chain the operations together using `then` from the returned promise: - - ```javascript - var fs = require('fs'); - var readFile = RSVP.denodeify(fs.readFile); - var writeFile = RSVP.denodeify(fs.writeFile); - - readFile('myfile.txt').then(function(data){ - return writeFile('myfile2.txt', data); - }).then(function(){ - console.log('done') - }).catch(function(error){ - // Handle error - }); - ``` - - @method denodeify - @static - @for RSVP - @param {Function} nodeFunc a 'node-style' function that takes a callback as - its last argument. The callback expects an error to be passed as its first - argument (if an error occurred, otherwise null), and the value from the - operation as its second argument ('function(err, value){ }'). - @param {Boolean|Array} argumentNames An optional paramter that if set - to `true` causes the promise to fulfill with the callback's success arguments - as an array. This is useful if the node function has multiple success - paramters. If you set this paramter to an array with names, the promise will - fulfill with a hash with these names as keys and the success parameters as - values. - @return {Function} a function that wraps `nodeFunc` to return an - `RSVP.Promise` - @static - */ - __exports__["default"] = function denodeify(nodeFunc, options) { - var fn = function() { - var self = this; - var l = arguments.length; - var args = new Array(l + 1); - var arg; - var promiseInput = false; - - for (var i = 0; i < l; ++i) { - arg = arguments[i]; - - if (!promiseInput) { - // TODO: clean this up - promiseInput = needsPromiseInput(arg); - if (promiseInput === GET_THEN_ERROR) { - var p = new Promise(noop); - reject(p, GET_THEN_ERROR.value); - return p; - } else if (promiseInput && promiseInput !== true) { - arg = wrapThenable(promiseInput, arg); - } - } - args[i] = arg; - } - - var promise = new Promise(noop); - - args[l] = function(err, val) { - if (err) - reject(promise, err); - else if (options === undefined) - resolve(promise, val); - else if (options === true) - resolve(promise, arrayResult(arguments)); - else if (isArray(options)) - resolve(promise, makeObject(arguments, options)); - else - resolve(promise, val); - }; - - if (promiseInput) { - return handlePromiseInput(promise, args, nodeFunc, self); - } else { - return handleValueInput(promise, args, nodeFunc, self); - } - }; - - fn.__proto__ = nodeFunc; - - return fn; - } - - function handleValueInput(promise, args, nodeFunc, self) { - var result = tryApply(nodeFunc, self, args); - if (result === ERROR) { - reject(promise, result.value); - } - return promise; - } - - function handlePromiseInput(promise, args, nodeFunc, self){ - return Promise.all(args).then(function(args){ - var result = tryApply(nodeFunc, self, args); - if (result === ERROR) { - reject(promise, result.value); - } - return promise; - }); - } - - function needsPromiseInput(arg) { - if (arg && typeof arg === 'object') { - if (arg.constructor === Promise) { - return true; - } else { - return getThen(arg); - } - } else { - return false; - } - } - }); -enifed("rsvp/promise-hash", - ["./enumerator","./-internal","./utils","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __exports__) { - "use strict"; - var Enumerator = __dependency1__["default"]; - var PENDING = __dependency2__.PENDING; - var o_create = __dependency3__.o_create; - - function PromiseHash(Constructor, object, label) { - this._superConstructor(Constructor, object, true, label); - } - - __exports__["default"] = PromiseHash; - - PromiseHash.prototype = o_create(Enumerator.prototype); - PromiseHash.prototype._superConstructor = Enumerator; - PromiseHash.prototype._init = function() { - this._result = {}; - }; - - PromiseHash.prototype._validateInput = function(input) { - return input && typeof input === 'object'; - }; - - PromiseHash.prototype._validationError = function() { - return new Error('Promise.hash must be called with an object'); - }; - - PromiseHash.prototype._enumerate = function() { - var promise = this.promise; - var input = this._input; - var results = []; - - for (var key in input) { - if (promise._state === PENDING && input.hasOwnProperty(key)) { - results.push({ - position: key, - entry: input[key] - }); - } - } - - var length = results.length; - this._remaining = length; - var result; - - for (var i = 0; promise._state === PENDING && i < length; i++) { - result = results[i]; - this._eachEntry(result.entry, result.position); - } - }; - }); -enifed("rsvp/promise", - ["./config","./instrument","./utils","./-internal","./promise/all","./promise/race","./promise/resolve","./promise/reject","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __exports__) { - "use strict"; - var config = __dependency1__.config; - var instrument = __dependency2__["default"]; - - var isFunction = __dependency3__.isFunction; - var now = __dependency3__.now; - - var noop = __dependency4__.noop; - var subscribe = __dependency4__.subscribe; - var initializePromise = __dependency4__.initializePromise; - var invokeCallback = __dependency4__.invokeCallback; - var FULFILLED = __dependency4__.FULFILLED; - var REJECTED = __dependency4__.REJECTED; - - var all = __dependency5__["default"]; - var race = __dependency6__["default"]; - var Resolve = __dependency7__["default"]; - var Reject = __dependency8__["default"]; - - var guidKey = 'rsvp_' + now() + '-'; - var counter = 0; - - function needsResolver() { - throw new TypeError('You must pass a resolver function as the first argument to the promise constructor'); - } - - function needsNew() { - throw new TypeError("Failed to construct 'Promise': Please use the 'new' operator, this object constructor cannot be called as a function."); - } - __exports__["default"] = Promise; - /** - Promise objects represent the eventual result of an asynchronous operation. The - primary way of interacting with a promise is through its `then` method, which - registers callbacks to receive either a promise’s eventual value or the reason - why the promise cannot be fulfilled. - - Terminology - ----------- - - - `promise` is an object or function with a `then` method whose behavior conforms to this specification. - - `thenable` is an object or function that defines a `then` method. - - `value` is any legal JavaScript value (including undefined, a thenable, or a promise). - - `exception` is a value that is thrown using the throw statement. - - `reason` is a value that indicates why a promise was rejected. - - `settled` the final resting state of a promise, fulfilled or rejected. - - A promise can be in one of three states: pending, fulfilled, or rejected. - - Promises that are fulfilled have a fulfillment value and are in the fulfilled - state. Promises that are rejected have a rejection reason and are in the - rejected state. A fulfillment value is never a thenable. - - Promises can also be said to *resolve* a value. If this value is also a - promise, then the original promise's settled state will match the value's - settled state. So a promise that *resolves* a promise that rejects will - itself reject, and a promise that *resolves* a promise that fulfills will - itself fulfill. - - - Basic Usage: - ------------ - - ```js - var promise = new Promise(function(resolve, reject) { - // on success - resolve(value); - - // on failure - reject(reason); - }); - - promise.then(function(value) { - // on fulfillment - }, function(reason) { - // on rejection - }); - ``` - - Advanced Usage: - --------------- - - Promises shine when abstracting away asynchronous interactions such as - `XMLHttpRequest`s. - - ```js - function getJSON(url) { - return new Promise(function(resolve, reject){ - var xhr = new XMLHttpRequest(); - - xhr.open('GET', url); - xhr.onreadystatechange = handler; - xhr.responseType = 'json'; - xhr.setRequestHeader('Accept', 'application/json'); - xhr.send(); - - function handler() { - if (this.readyState === this.DONE) { - if (this.status === 200) { - resolve(this.response); - } else { - reject(new Error('getJSON: `' + url + '` failed with status: [' + this.status + ']')); - } - } - }; - }); - } - - getJSON('/posts.json').then(function(json) { - // on fulfillment - }, function(reason) { - // on rejection - }); - ``` - - Unlike callbacks, promises are great composable primitives. - - ```js - Promise.all([ - getJSON('/posts'), - getJSON('/comments') - ]).then(function(values){ - values[0] // => postsJSON - values[1] // => commentsJSON - - return values; - }); - ``` - - @class RSVP.Promise - @param {function} resolver - @param {String} label optional string for labeling the promise. - Useful for tooling. - @constructor - */ - function Promise(resolver, label) { - this._id = counter++; - this._label = label; - this._state = undefined; - this._result = undefined; - this._subscribers = []; - - if (config.instrument) { - instrument('created', this); - } - - if (noop !== resolver) { - if (!isFunction(resolver)) { - needsResolver(); - } - - if (!(this instanceof Promise)) { - needsNew(); - } - - initializePromise(this, resolver); - } - } - - Promise.cast = Resolve; // deprecated - Promise.all = all; - Promise.race = race; - Promise.resolve = Resolve; - Promise.reject = Reject; - - Promise.prototype = { - constructor: Promise, - - _guidKey: guidKey, - - _onerror: function (reason) { - config.trigger('error', reason); - }, - - /** - The primary way of interacting with a promise is through its `then` method, - which registers callbacks to receive either a promise's eventual value or the - reason why the promise cannot be fulfilled. - - ```js - findUser().then(function(user){ - // user is available - }, function(reason){ - // user is unavailable, and you are given the reason why - }); - ``` - - Chaining - -------- - - The return value of `then` is itself a promise. This second, 'downstream' - promise is resolved with the return value of the first promise's fulfillment - or rejection handler, or rejected if the handler throws an exception. - - ```js - findUser().then(function (user) { - return user.name; - }, function (reason) { - return 'default name'; - }).then(function (userName) { - // If `findUser` fulfilled, `userName` will be the user's name, otherwise it - // will be `'default name'` - }); - - findUser().then(function (user) { - throw new Error('Found user, but still unhappy'); - }, function (reason) { - throw new Error('`findUser` rejected and we're unhappy'); - }).then(function (value) { - // never reached - }, function (reason) { - // if `findUser` fulfilled, `reason` will be 'Found user, but still unhappy'. - // If `findUser` rejected, `reason` will be '`findUser` rejected and we're unhappy'. - }); - ``` - If the downstream promise does not specify a rejection handler, rejection reasons will be propagated further downstream. - - ```js - findUser().then(function (user) { - throw new PedagogicalException('Upstream error'); - }).then(function (value) { - // never reached - }).then(function (value) { - // never reached - }, function (reason) { - // The `PedgagocialException` is propagated all the way down to here - }); - ``` - - Assimilation - ------------ - - Sometimes the value you want to propagate to a downstream promise can only be - retrieved asynchronously. This can be achieved by returning a promise in the - fulfillment or rejection handler. The downstream promise will then be pending - until the returned promise is settled. This is called *assimilation*. - - ```js - findUser().then(function (user) { - return findCommentsByAuthor(user); - }).then(function (comments) { - // The user's comments are now available - }); - ``` - - If the assimliated promise rejects, then the downstream promise will also reject. - - ```js - findUser().then(function (user) { - return findCommentsByAuthor(user); - }).then(function (comments) { - // If `findCommentsByAuthor` fulfills, we'll have the value here - }, function (reason) { - // If `findCommentsByAuthor` rejects, we'll have the reason here - }); - ``` - - Simple Example - -------------- - - Synchronous Example - - ```javascript - var result; - - try { - result = findResult(); - // success - } catch(reason) { - // failure - } - ``` - - Errback Example - - ```js - findResult(function(result, err){ - if (err) { - // failure - } else { - // success - } - }); - ``` - - Promise Example; - - ```javascript - findResult().then(function(result){ - // success - }, function(reason){ - // failure - }); - ``` - - Advanced Example - -------------- - - Synchronous Example - - ```javascript - var author, books; - - try { - author = findAuthor(); - books = findBooksByAuthor(author); - // success - } catch(reason) { - // failure - } - ``` - - Errback Example - - ```js - - function foundBooks(books) { - - } - - function failure(reason) { - - } - - findAuthor(function(author, err){ - if (err) { - failure(err); - // failure - } else { - try { - findBoooksByAuthor(author, function(books, err) { - if (err) { - failure(err); - } else { - try { - foundBooks(books); - } catch(reason) { - failure(reason); - } - } - }); - } catch(error) { - failure(err); - } - // success - } - }); - ``` - - Promise Example; - - ```javascript - findAuthor(). - then(findBooksByAuthor). - then(function(books){ - // found books - }).catch(function(reason){ - // something went wrong - }); - ``` - - @method then - @param {Function} onFulfilled - @param {Function} onRejected - @param {String} label optional string for labeling the promise. - Useful for tooling. - @return {Promise} - */ - then: function(onFulfillment, onRejection, label) { - var parent = this; - var state = parent._state; - - if (state === FULFILLED && !onFulfillment || state === REJECTED && !onRejection) { - if (config.instrument) { - instrument('chained', this, this); - } - return this; - } - - parent._onerror = null; - - var child = new this.constructor(noop, label); - var result = parent._result; - - if (config.instrument) { - instrument('chained', parent, child); - } - - if (state) { - var callback = arguments[state - 1]; - config.async(function(){ - invokeCallback(state, child, callback, result); - }); - } else { - subscribe(parent, child, onFulfillment, onRejection); - } - - return child; - }, - - /** - `catch` is simply sugar for `then(undefined, onRejection)` which makes it the same - as the catch block of a try/catch statement. - - ```js - function findAuthor(){ - throw new Error('couldn't find that author'); - } - - // synchronous - try { - findAuthor(); - } catch(reason) { - // something went wrong - } - - // async with promises - findAuthor().catch(function(reason){ - // something went wrong - }); - ``` - - @method catch - @param {Function} onRejection - @param {String} label optional string for labeling the promise. - Useful for tooling. - @return {Promise} - */ - 'catch': function(onRejection, label) { - return this.then(null, onRejection, label); - }, - - /** - `finally` will be invoked regardless of the promise's fate just as native - try/catch/finally behaves - - Synchronous example: - - ```js - findAuthor() { - if (Math.random() > 0.5) { - throw new Error(); - } - return new Author(); - } - - try { - return findAuthor(); // succeed or fail - } catch(error) { - return findOtherAuther(); - } finally { - // always runs - // doesn't affect the return value - } - ``` - - Asynchronous example: - - ```js - findAuthor().catch(function(reason){ - return findOtherAuther(); - }).finally(function(){ - // author was either found, or not - }); - ``` - - @method finally - @param {Function} callback - @param {String} label optional string for labeling the promise. - Useful for tooling. - @return {Promise} - */ - 'finally': function(callback, label) { - var constructor = this.constructor; - - return this.then(function(value) { - return constructor.resolve(callback()).then(function(){ - return value; - }); - }, function(reason) { - return constructor.resolve(callback()).then(function(){ - throw reason; - }); - }, label); - } - }; - }); -enifed("rsvp/promise/all", - ["../enumerator","exports"], - function(__dependency1__, __exports__) { - "use strict"; - var Enumerator = __dependency1__["default"]; - - /** - `RSVP.Promise.all` accepts an array of promises, and returns a new promise which - is fulfilled with an array of fulfillment values for the passed promises, or - rejected with the reason of the first passed promise to be rejected. It casts all - elements of the passed iterable to promises as it runs this algorithm. - - Example: - - ```javascript - var promise1 = RSVP.resolve(1); - var promise2 = RSVP.resolve(2); - var promise3 = RSVP.resolve(3); - var promises = [ promise1, promise2, promise3 ]; - - RSVP.Promise.all(promises).then(function(array){ - // The array here would be [ 1, 2, 3 ]; - }); - ``` - - If any of the `promises` given to `RSVP.all` are rejected, the first promise - that is rejected will be given as an argument to the returned promises's - rejection handler. For example: - - Example: - - ```javascript - var promise1 = RSVP.resolve(1); - var promise2 = RSVP.reject(new Error("2")); - var promise3 = RSVP.reject(new Error("3")); - var promises = [ promise1, promise2, promise3 ]; - - RSVP.Promise.all(promises).then(function(array){ - // Code here never runs because there are rejected promises! - }, function(error) { - // error.message === "2" - }); - ``` - - @method all - @static - @param {Array} entries array of promises - @param {String} label optional string for labeling the promise. - Useful for tooling. - @return {Promise} promise that is fulfilled when all `promises` have been - fulfilled, or rejected if any of them become rejected. - @static - */ - __exports__["default"] = function all(entries, label) { - return new Enumerator(this, entries, true /* abort on reject */, label).promise; - } - }); -enifed("rsvp/promise/race", - ["../utils","../-internal","exports"], - function(__dependency1__, __dependency2__, __exports__) { - "use strict"; - var isArray = __dependency1__.isArray; - - var noop = __dependency2__.noop; - var resolve = __dependency2__.resolve; - var reject = __dependency2__.reject; - var subscribe = __dependency2__.subscribe; - var PENDING = __dependency2__.PENDING; - - /** - `RSVP.Promise.race` returns a new promise which is settled in the same way as the - first passed promise to settle. - - Example: - - ```javascript - var promise1 = new RSVP.Promise(function(resolve, reject){ - setTimeout(function(){ - resolve('promise 1'); - }, 200); - }); - - var promise2 = new RSVP.Promise(function(resolve, reject){ - setTimeout(function(){ - resolve('promise 2'); - }, 100); - }); - - RSVP.Promise.race([promise1, promise2]).then(function(result){ - // result === 'promise 2' because it was resolved before promise1 - // was resolved. - }); - ``` - - `RSVP.Promise.race` is deterministic in that only the state of the first - settled promise matters. For example, even if other promises given to the - `promises` array argument are resolved, but the first settled promise has - become rejected before the other promises became fulfilled, the returned - promise will become rejected: - - ```javascript - var promise1 = new RSVP.Promise(function(resolve, reject){ - setTimeout(function(){ - resolve('promise 1'); - }, 200); - }); - - var promise2 = new RSVP.Promise(function(resolve, reject){ - setTimeout(function(){ - reject(new Error('promise 2')); - }, 100); - }); - - RSVP.Promise.race([promise1, promise2]).then(function(result){ - // Code here never runs - }, function(reason){ - // reason.message === 'promise 2' because promise 2 became rejected before - // promise 1 became fulfilled - }); - ``` - - An example real-world use case is implementing timeouts: - - ```javascript - RSVP.Promise.race([ajax('foo.json'), timeout(5000)]) - ``` - - @method race - @static - @param {Array} promises array of promises to observe - @param {String} label optional string for describing the promise returned. - Useful for tooling. - @return {Promise} a promise which settles in the same way as the first passed - promise to settle. - */ - __exports__["default"] = function race(entries, label) { - /*jshint validthis:true */ - var Constructor = this; - - var promise = new Constructor(noop, label); - - if (!isArray(entries)) { - reject(promise, new TypeError('You must pass an array to race.')); - return promise; - } - - var length = entries.length; - - function onFulfillment(value) { - resolve(promise, value); - } - - function onRejection(reason) { - reject(promise, reason); - } - - for (var i = 0; promise._state === PENDING && i < length; i++) { - subscribe(Constructor.resolve(entries[i]), undefined, onFulfillment, onRejection); - } - - return promise; - } - }); -enifed("rsvp/promise/reject", - ["../-internal","exports"], - function(__dependency1__, __exports__) { - "use strict"; - var noop = __dependency1__.noop; - var _reject = __dependency1__.reject; - - /** - `RSVP.Promise.reject` returns a promise rejected with the passed `reason`. - It is shorthand for the following: - - ```javascript - var promise = new RSVP.Promise(function(resolve, reject){ - reject(new Error('WHOOPS')); - }); - - promise.then(function(value){ - // Code here doesn't run because the promise is rejected! - }, function(reason){ - // reason.message === 'WHOOPS' - }); - ``` - - Instead of writing the above, your code now simply becomes the following: - - ```javascript - var promise = RSVP.Promise.reject(new Error('WHOOPS')); - - promise.then(function(value){ - // Code here doesn't run because the promise is rejected! - }, function(reason){ - // reason.message === 'WHOOPS' - }); - ``` - - @method reject - @static - @param {Any} reason value that the returned promise will be rejected with. - @param {String} label optional string for identifying the returned promise. - Useful for tooling. - @return {Promise} a promise rejected with the given `reason`. - */ - __exports__["default"] = function reject(reason, label) { - /*jshint validthis:true */ - var Constructor = this; - var promise = new Constructor(noop, label); - _reject(promise, reason); - return promise; - } - }); -enifed("rsvp/promise/resolve", - ["../-internal","exports"], - function(__dependency1__, __exports__) { - "use strict"; - var noop = __dependency1__.noop; - var _resolve = __dependency1__.resolve; - - /** - `RSVP.Promise.resolve` returns a promise that will become resolved with the - passed `value`. It is shorthand for the following: - - ```javascript - var promise = new RSVP.Promise(function(resolve, reject){ - resolve(1); - }); - - promise.then(function(value){ - // value === 1 - }); - ``` - - Instead of writing the above, your code now simply becomes the following: - - ```javascript - var promise = RSVP.Promise.resolve(1); - - promise.then(function(value){ - // value === 1 - }); - ``` - - @method resolve - @static - @param {Any} value value that the returned promise will be resolved with - @param {String} label optional string for identifying the returned promise. - Useful for tooling. - @return {Promise} a promise that will become fulfilled with the given - `value` - */ - __exports__["default"] = function resolve(object, label) { - /*jshint validthis:true */ - var Constructor = this; - - if (object && typeof object === 'object' && object.constructor === Constructor) { - return object; - } - - var promise = new Constructor(noop, label); - _resolve(promise, object); - return promise; - } - }); -enifed("rsvp/race", - ["./promise","exports"], - function(__dependency1__, __exports__) { - "use strict"; - var Promise = __dependency1__["default"]; - - /** - This is a convenient alias for `RSVP.Promise.race`. - - @method race - @static - @for RSVP - @param {Array} array Array of promises. - @param {String} label An optional label. This is useful - for tooling. - */ - __exports__["default"] = function race(array, label) { - return Promise.race(array, label); - } - }); -enifed("rsvp/reject", - ["./promise","exports"], - function(__dependency1__, __exports__) { - "use strict"; - var Promise = __dependency1__["default"]; - - /** - This is a convenient alias for `RSVP.Promise.reject`. - - @method reject - @static - @for RSVP - @param {Any} reason value that the returned promise will be rejected with. - @param {String} label optional string for identifying the returned promise. - Useful for tooling. - @return {Promise} a promise rejected with the given `reason`. - */ - __exports__["default"] = function reject(reason, label) { - return Promise.reject(reason, label); - } - }); -enifed("rsvp/resolve", - ["./promise","exports"], - function(__dependency1__, __exports__) { - "use strict"; - var Promise = __dependency1__["default"]; - - /** - This is a convenient alias for `RSVP.Promise.resolve`. - - @method resolve - @static - @for RSVP - @param {Any} value value that the returned promise will be resolved with - @param {String} label optional string for identifying the returned promise. - Useful for tooling. - @return {Promise} a promise that will become fulfilled with the given - `value` - */ - __exports__["default"] = function resolve(value, label) { - return Promise.resolve(value, label); - } - }); -enifed("rsvp/rethrow", - ["exports"], - function(__exports__) { - "use strict"; - /** - `RSVP.rethrow` will rethrow an error on the next turn of the JavaScript event - loop in order to aid debugging. - - Promises A+ specifies that any exceptions that occur with a promise must be - caught by the promises implementation and bubbled to the last handler. For - this reason, it is recommended that you always specify a second rejection - handler function to `then`. However, `RSVP.rethrow` will throw the exception - outside of the promise, so it bubbles up to your console if in the browser, - or domain/cause uncaught exception in Node. `rethrow` will also throw the - error again so the error can be handled by the promise per the spec. - - ```javascript - function throws(){ - throw new Error('Whoops!'); - } - - var promise = new RSVP.Promise(function(resolve, reject){ - throws(); - }); - - promise.catch(RSVP.rethrow).then(function(){ - // Code here doesn't run because the promise became rejected due to an - // error! - }, function (err){ - // handle the error here - }); - ``` - - The 'Whoops' error will be thrown on the next turn of the event loop - and you can watch for it in your console. You can also handle it using a - rejection handler given to `.then` or `.catch` on the returned promise. - - @method rethrow - @static - @for RSVP - @param {Error} reason reason the promise became rejected. - @throws Error - @static - */ - __exports__["default"] = function rethrow(reason) { - setTimeout(function() { - throw reason; - }); - throw reason; - } - }); -enifed("rsvp/utils", - ["exports"], - function(__exports__) { - "use strict"; - function objectOrFunction(x) { - return typeof x === 'function' || (typeof x === 'object' && x !== null); - } - - __exports__.objectOrFunction = objectOrFunction;function isFunction(x) { - return typeof x === 'function'; - } - - __exports__.isFunction = isFunction;function isMaybeThenable(x) { - return typeof x === 'object' && x !== null; - } - - __exports__.isMaybeThenable = isMaybeThenable;var _isArray; - if (!Array.isArray) { - _isArray = function (x) { - return Object.prototype.toString.call(x) === '[object Array]'; - }; - } else { - _isArray = Array.isArray; - } - - var isArray = _isArray; - __exports__.isArray = isArray; - // Date.now is not available in browsers < IE9 - // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/now#Compatibility - var now = Date.now || function() { return new Date().getTime(); }; - __exports__.now = now; - function F() { } - - var o_create = (Object.create || function (o) { - if (arguments.length > 1) { - throw new Error('Second argument not supported'); - } - if (typeof o !== 'object') { - throw new TypeError('Argument must be an object'); - } - F.prototype = o; - return new F(); - }); - __exports__.o_create = o_create; - }); -requireModule("ember"); - -})(); diff --git a/vendor/assets/ember/production/ember-data.js b/vendor/assets/ember/production/ember-data.js deleted file mode 100644 index c3e8ca46..00000000 --- a/vendor/assets/ember/production/ember-data.js +++ /dev/null @@ -1,5 +0,0 @@ -// Fetched from channel: release, with url http://builds.emberjs.com/beta/ember-data.min.js -// Fetched on: 2014-11-24T13:02:16Z -(function(e){var r,t,i,a;(function(){var e;if(!Array.isArray){e=function(e){return Object.prototype.toString.call(e)==="[object Array]"}}else{e=Array.isArray}var n={},s={},o={};var u=false;r=function(r,t,i){if(!e(t)){i=t;t=[]}n[r]={deps:t,callback:i}};function d(e,r,t){var a=e.length;var n=new Array(a);var s;var o;for(var u=0,d=a;u=t){n=0;s.push([])}n+=r;var i=s.length-1;s[i].push(e)});return s}var s=[];t.forEach(function(e,r){var t=2048;var i=a(e,t);o.call(i,function(e){s.push(e)})});return s},pathForType:function(e){var r=Ember.String.camelize(e);return Ember.String.pluralize(r)},ajaxError:function(e,r){if(e&&typeof e==="object"){e.then=null}return e},ajaxSuccess:function(e,r){return r},ajax:function(e,r,t){var i=this;return new Ember.RSVP.Promise(function(n,s){var o=i.ajaxOptions(e,r,t);o.success=function(e,r,t){e=i.ajaxSuccess(t,e);if(e instanceof a){Ember.run(null,s,e)}else{Ember.run(null,n,e)}};o.error=function(e,r,t){Ember.run(null,s,i.ajaxError(e,e.responseText))};Ember.$.ajax(o)},"DS: RESTAdapter#ajax "+r+" to "+e)},ajaxOptions:function(e,r,t){var i=t||{};i.url=e;i.type=r;i.dataType="json";i.context=this;if(i.data&&r!=="GET"){i.contentType="application/json; charset=utf-8";i.data=JSON.stringify(i.data)}var a=s(this,"headers");if(a!==undefined){i.beforeSend=function(e){o.call(Ember.keys(a),function(r){e.setRequestHeader(r,a[r])})}}return i}});function u(e,r){if(typeof String.prototype.endsWith!=="function"){return e.indexOf(r,e.length-r.length)!==-1}else{return e.endsWith(r)}}});r("ember-data/core",["exports"],function(e){"use strict";var r;if("undefined"===typeof r){r=Ember.Namespace.create({VERSION:"1.0.0-beta.11"});if(Ember.libraries){Ember.libraries.registerCoreLibrary("Ember Data",r.VERSION)}}e["default"]=r});r("ember-data/ember-initializer",["ember-data/setup-container"],function(e){"use strict";var r=e["default"];var t=Ember.K;Ember.onLoad("Ember.Application",function(e){e.initializer({name:"ember-data",initialize:r});e.initializer({name:"store",after:"ember-data",initialize:t});e.initializer({name:"activeModelAdapter",before:"store",initialize:t});e.initializer({name:"transforms",before:"store",initialize:t});e.initializer({name:"data-adapter",before:"store",initialize:t});e.initializer({name:"injectStore",before:"store",initialize:t})})});r("ember-data/ext/date",[],function(){"use strict";Ember.Date=Ember.Date||{};var e=Date.parse,r=[1,4,5,6,7,10,11];Ember.Date.parse=function(t){var i,a,n=0;if(a=/^(\d{4}|[+\-]\d{6})(?:-(\d{2})(?:-(\d{2}))?)?(?:T(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{3}))?)?(?:(Z)|([+\-])(\d{2})(?::(\d{2}))?)?)?$/.exec(t)){for(var s=0,o;o=r[s];++s){a[o]=+a[o]||0}a[2]=(+a[2]||1)-1;a[3]=+a[3]||1;if(a[8]!=="Z"&&a[9]!==undefined){n=a[10]*60+a[11];if(a[9]==="+"){n=0-n}}i=Date.UTC(a[1],a[2],a[3],a[4],a[5]+n,a[6],a[7])}else{i=e?e(t):NaN}return i};if(Ember.EXTEND_PROTOTYPES===true||Ember.EXTEND_PROTOTYPES.Date){Date.parse=Ember.Date.parse}});r("ember-data/initializers/data_adapter",["ember-data/system/debug/debug_adapter","exports"],function(e,r){"use strict";var t=e["default"];r["default"]=function i(e){e.register("data-adapter:main",t)}});r("ember-data/initializers/store",["ember-data/serializers","ember-data/adapters","ember-data/system/container_proxy","ember-data/system/store","exports"],function(e,r,t,i,a){"use strict";var n=e.JSONSerializer;var s=e.RESTSerializer;var o=r.RESTAdapter;var u=t["default"];var d=i["default"];a["default"]=function c(e,r){e.register("store:main",e.lookupFactory("store:application")||r&&r.Store||d);var t=new u(e);t.registerDeprecations([{deprecated:"serializer:_default",valid:"serializer:-default"},{deprecated:"serializer:_rest",valid:"serializer:-rest"},{deprecated:"adapter:_rest",valid:"adapter:-rest"}]);e.register("serializer:-default",n);e.register("serializer:-rest",s);e.register("adapter:-rest",o);e.lookup("store:main")}});r("ember-data/initializers/store_injections",["exports"],function(e){"use strict";e["default"]=function r(e){e.injection("controller","store","store:main");e.injection("route","store","store:main");e.injection("serializer","store","store:main");e.injection("data-adapter","store","store:main")}});r("ember-data/initializers/transforms",["ember-data/transforms","exports"],function(e,r){"use strict";var t=e.BooleanTransform;var i=e.DateTransform;var a=e.StringTransform;var n=e.NumberTransform;r["default"]=function s(e){e.register("transform:boolean",t);e.register("transform:date",i);e.register("transform:number",n);e.register("transform:string",a)}});r("ember-data/serializers",["ember-data/serializers/json_serializer","ember-data/serializers/rest_serializer","exports"],function(e,r,t){"use strict";var i=e["default"];var a=r["default"];t.JSONSerializer=i;t.RESTSerializer=a});r("ember-data/serializers/embedded_records_mixin",["exports"],function(e){"use strict";var r=Ember.get;var t=Ember.EnumerableUtils.forEach;var i=Ember.String.camelize;var a=Ember.Mixin.create({normalize:function(e,r,t){var i=this._super(e,r,t);return n(this,this.store,e,i)},keyForRelationship:function(e,r){if(this.hasDeserializeRecordsOption(e)){return this.keyForAttribute(e)}else{return this._super(e,r)||e}},serializeBelongsTo:function(e,t,i){var a=i.key;if(this.noSerializeOptionSpecified(a)){this._super(e,t,i);return}var n=this.hasSerializeIdsOption(a);var s=this.hasSerializeRecordsOption(a);var o=e.get(a);var u;if(n){u=this.keyForRelationship(a,i.kind);if(!o){t[u]=null}else{t[u]=r(o,"id")}}else if(s){u=this.keyForAttribute(a);if(!o){t[u]=null}else{t[u]=o.serialize({includeId:true});this.removeEmbeddedForeignKey(e,o,i,t[u])}}},serializeHasMany:function(e,t,i){var a=i.key;if(this.noSerializeOptionSpecified(a)){this._super(e,t,i);return}var n=this.hasSerializeIdsOption(a);var s=this.hasSerializeRecordsOption(a);var o;if(n){o=this.keyForRelationship(a,i.kind);t[o]=r(e,a).mapBy("id")}else if(s){o=this.keyForAttribute(a);t[o]=r(e,a).map(function(r){var t=r.serialize({includeId:true});this.removeEmbeddedForeignKey(e,r,i,t);return t},this)}},removeEmbeddedForeignKey:function(e,r,t,i){if(t.kind==="hasMany"){return}else if(t.kind==="belongsTo"){var a=e.constructor.inverseFor(t.key);if(a){var n=a.name;var s=this.store.serializerFor(r.constructor);var o=s.keyForRelationship(n,a.kind);if(o){delete i[o]}}}},hasEmbeddedAlwaysOption:function(e){var r=this.attrsOption(e);return r&&r.embedded==="always"},hasSerializeRecordsOption:function(e){var r=this.hasEmbeddedAlwaysOption(e);var t=this.attrsOption(e);return r||t&&t.serialize==="records"},hasSerializeIdsOption:function(e){var r=this.attrsOption(e);return r&&(r.serialize==="ids"||r.serialize==="id")},noSerializeOptionSpecified:function(e){var r=this.attrsOption(e);return!(r&&(r.serialize||r.embedded))},hasDeserializeRecordsOption:function(e){var r=this.hasEmbeddedAlwaysOption(e);var t=this.attrsOption(e);return r||t&&t.deserialize==="records"},attrsOption:function(e){var r=this.get("attrs");return r&&(r[i(e)]||r[e])}});function n(e,r,t,i){t.eachRelationship(function(t,a){if(e.hasDeserializeRecordsOption(t)){var n=r.modelFor(a.type.typeKey);if(a.kind==="hasMany"){if(a.options.polymorphic){o(r,t,i)}else{s(r,t,n,i)}}if(a.kind==="belongsTo"){u(r,t,n,i)}}});return i}function s(e,r,i,a){if(!a[r]){return a}var n=[];var s=e.serializerFor(i.typeKey);t(a[r],function(r){var t=s.normalize(i,r,null);e.push(i,t);n.push(t.id)});a[r]=n;return a}function o(e,i,a){if(!a[i]){return a}var n=[];t(a[i],function(t){var i=t.type;var a=e.serializerFor(i);var s=e.modelFor(i);var o=r(a,"primaryKey");var u=a.normalize(s,t,null);e.push(s,u);n.push({id:u[o],type:i})});a[i]=n;return a}function u(e,r,t,i){if(!i[r]){return i}var a=e.serializerFor(t.typeKey);var n=a.normalize(t,i[r],null);e.push(t,n);i[r]=n.id;return i}e["default"]=a});r("ember-data/serializers/json_serializer",["exports"],function(e){"use strict";var r=Ember.get;var t=Ember.isNone;var i=Ember.ArrayPolyfills.map;var a=Ember.merge;e["default"]=Ember.Object.extend({primaryKey:"id",applyTransforms:function(e,r){e.eachTransformedAttribute(function t(e,i){if(!r.hasOwnProperty(e)){return}var a=this.transformFor(i);r[e]=a.deserialize(r[e])},this);return r},normalize:function(e,r){if(!r){return r}this.normalizeId(r);this.normalizeAttributes(e,r);this.normalizeRelationships(e,r);this.normalizeUsingDeclaredMapping(e,r);this.applyTransforms(e,r);return r},normalizePayload:function(e){return e},normalizeAttributes:function(e,r){var t;if(this.keyForAttribute){e.eachAttribute(function(e){t=this.keyForAttribute(e);if(e===t){return}if(!r.hasOwnProperty(t)){return}r[e]=r[t];delete r[t]},this)}},normalizeRelationships:function(e,r){var t;if(this.keyForRelationship){e.eachRelationship(function(e,i){t=this.keyForRelationship(e,i.kind);if(e===t){return}if(!r.hasOwnProperty(t)){return}r[e]=r[t];delete r[t]},this)}},normalizeUsingDeclaredMapping:function(e,t){var i=r(this,"attrs"),a,n;if(i){for(n in i){a=this._getMappedKey(n);if(!t.hasOwnProperty(a)){continue}if(a!==n){t[n]=t[a];delete t[a]}}}},normalizeId:function(e){var t=r(this,"primaryKey");if(t==="id"){return}e.id=e[t];delete e[t]},_getMappedKey:function(e){var t=r(this,"attrs");var i;if(t&&t[e]){i=t[e];if(i.key){i=i.key}if(typeof i==="string"){e=i}}return e},_canSerialize:function(e){var t=r(this,"attrs");return!t||!t[e]||t[e].serialize!==false},serialize:function(e,t){var i={};if(t&&t.includeId){var a=r(e,"id");if(a){i[r(this,"primaryKey")]=a}}e.eachAttribute(function(r,t){this.serializeAttribute(e,i,r,t)},this);e.eachRelationship(function(r,t){if(t.kind==="belongsTo"){this.serializeBelongsTo(e,i,t)}else if(t.kind==="hasMany"){this.serializeHasMany(e,i,t)}},this);return i},serializeIntoHash:function(e,r,t,i){a(e,this.serialize(t,i))},serializeAttribute:function(e,t,i,a){var n=a.type;if(this._canSerialize(i)){var s=r(e,i);if(n){var o=this.transformFor(n);s=o.serialize(s)}var u=this._getMappedKey(i);if(u===i&&this.keyForAttribute){u=this.keyForAttribute(i)}t[u]=s}},serializeBelongsTo:function(e,i,a){var n=a.key;if(this._canSerialize(n)){var s=r(e,n);var o=this._getMappedKey(n);if(o===n&&this.keyForRelationship){o=this.keyForRelationship(n,"belongsTo")}if(t(s)||t(r(s,"id"))){i[o]=null}else{i[o]=r(s,"id")}if(a.options.polymorphic){this.serializePolymorphicType(e,i,a)}}},serializeHasMany:function(e,t,i){var a=i.key;if(this._canSerialize(a)){var n;n=this._getMappedKey(a);if(n===a&&this.keyForRelationship){n=this.keyForRelationship(a,"hasMany")}var s=e.constructor.determineRelationshipType(i);if(s==="manyToNone"||s==="manyToMany"){t[n]=r(e,a).mapBy("id")}}},serializePolymorphicType:Ember.K,extract:function(e,r,t,i,a){this.extractMeta(e,r,t);var n="extract"+a.charAt(0).toUpperCase()+a.substr(1);return this[n](e,r,t,i,a)},extractFindAll:function(e,r,t,i,a){return this.extractArray(e,r,t,i,a)},extractFindQuery:function(e,r,t,i,a){return this.extractArray(e,r,t,i,a)},extractFindMany:function(e,r,t,i,a){return this.extractArray(e,r,t,i,a)},extractFindHasMany:function(e,r,t,i,a){return this.extractArray(e,r,t,i,a)},extractCreateRecord:function(e,r,t,i,a){return this.extractSave(e,r,t,i,a)},extractUpdateRecord:function(e,r,t,i,a){return this.extractSave(e,r,t,i,a)},extractDeleteRecord:function(e,r,t,i,a){return this.extractSave(e,r,t,i,a)},extractFind:function(e,r,t,i,a){return this.extractSingle(e,r,t,i,a)},extractFindBelongsTo:function(e,r,t,i,a){return this.extractSingle(e,r,t,i,a)},extractSave:function(e,r,t,i,a){return this.extractSingle(e,r,t,i,a)},extractSingle:function(e,r,t,i,a){t=this.normalizePayload(t);return this.normalize(r,t)},extractArray:function(e,r,t,a,n){var s=this.normalizePayload(t);var o=this;return i.call(s,function(e){return o.normalize(r,e)})},extractMeta:function(e,r,t){if(t&&t.meta){e.metaForType(r,t.meta);delete t.meta}},keyForAttribute:function(e){return e},keyForRelationship:function(e,r){return e},transformFor:function(e,r){var t=this.container.lookup("transform:"+e);return t}})});r("ember-data/serializers/rest_serializer",["ember-data/serializers/json_serializer","ember-inflector/system/string","exports"],function(e,r,t){"use strict";var i=e["default"];var a=Ember.get;var n=Ember.ArrayPolyfills.forEach;var s=Ember.ArrayPolyfills.map;var o=Ember.String.camelize;var u=r.singularize;function d(e){return e==null?null:e+""}var c=i.extend({normalize:function(e,r,t){this.normalizeId(r);this.normalizeAttributes(e,r);this.normalizeRelationships(e,r);this.normalizeUsingDeclaredMapping(e,r);if(this.normalizeHash&&this.normalizeHash[t]){this.normalizeHash[t](r)}this.applyTransforms(e,r);return r},extractSingle:function(e,r,t,i){var a=this.normalizePayload(t);var s=r.typeKey;var o;for(var u in a){var c=this.typeForRoot(u);if(!e.modelFactoryFor(c)){continue}var l=e.modelFor(c);var f=l.typeKey===s;var h=a[u];if(f&&Ember.typeOf(h)!=="array"){o=this.normalize(r,h,u);continue}n.call(h,function(r){var t=this.typeForRoot(u);var a=e.modelFor(t);var n=e.serializerFor(a);r=n.normalize(a,r,u);var s=f&&!i&&!o;var c=f&&d(r.id)===i;if(s||c){o=r}else{e.push(t,r)}},this)}return o},extractArray:function(e,r,t){var i=this.normalizePayload(t);var a=r.typeKey;var n;for(var o in i){var u=o;var d=false;if(o.charAt(0)==="_"){d=true;u=o.substr(1)}var c=this.typeForRoot(u);if(!e.modelFactoryFor(c)){continue}var l=e.modelFor(c);var f=e.serializerFor(l);var h=!d&&l.typeKey===a;var p=s.call(i[o],function(e){return f.normalize(l,e,o)},this);if(h){n=p}else{e.pushMany(c,p)}}return n},pushPayload:function(e,r){var t=this.normalizePayload(r);for(var i in t){var a=this.typeForRoot(i);if(!e.modelFactoryFor(a,i)){continue}var n=e.modelFor(a);var o=e.serializerFor(n);var u=s.call(Ember.makeArray(t[i]),function(e){return o.normalize(n,e,i)},this);e.pushMany(a,u)}},typeForRoot:function(e){return o(u(e))},serialize:function(e,r){return this._super.apply(this,arguments)},serializeIntoHash:function(e,r,t,i){e[r.typeKey]=this.serialize(t,i)},serializePolymorphicType:function(e,r,t){var i=t.key;var n=a(e,i);i=this.keyForAttribute?this.keyForAttribute(i):i;if(Ember.isNone(n)){r[i+"Type"]=null}else{r[i+"Type"]=Ember.String.camelize(n.constructor.typeKey)}}});t["default"]=c});r("ember-data/setup-container",["ember-data/initializers/store","ember-data/initializers/transforms","ember-data/initializers/store_injections","ember-data/initializers/data_adapter","activemodel-adapter/setup-container","exports"],function(e,r,t,i,a,n){"use strict";var s=e["default"];var o=r["default"];var u=t["default"];var d=i["default"];var c=a["default"];n["default"]=function l(e,r){d(e,r);o(e,r);u(e,r);s(e,r);c(e,r)}});r("ember-data/system/adapter",["exports"],function(e){"use strict";var r=Ember.get;var t=["description","fileName","lineNumber","message","name","number","stack"];function i(e){var r=Error.prototype.constructor.call(this,"The backend rejected the commit because it was invalid: "+Ember.inspect(e));this.errors=e;for(var i=0,a=t.length;i0;r--){t=e[r-1];i=t["deprecated"];a=t["valid"];this.registerDeprecation(i,a)}};e["default"]=r});r("ember-data/system/debug",["ember-data/system/debug/debug_info","ember-data/system/debug/debug_adapter","exports"],function(e,r,t){"use strict";var i=r["default"];t["default"]=i});r("ember-data/system/debug/debug_adapter",["ember-data/system/model","exports"],function(e,r){"use strict";var t=e.Model;var i=Ember.get;var a=Ember.String.capitalize;var n=Ember.String.underscore;r["default"]=Ember.DataAdapter.extend({getFilters:function(){return[{name:"isNew",desc:"New"},{name:"isModified",desc:"Modified"},{name:"isClean",desc:"Clean"}]},detect:function(e){return e!==t&&t.detect(e)},columnsForType:function(e){var r=[{name:"id",desc:"Id"}];var t=0;var s=this;i(e,"attributes").forEach(function(e,i){if(t++>s.attributeLimit){return false}var o=a(n(i).replace("_"," "));r.push({name:i,desc:o})});return r},getRecords:function(e){return this.get("store").all(e)},getRecordColumnValues:function(e){var r=this,t=0;var a={id:i(e,"id")};e.eachAttribute(function(n){if(t++>r.attributeLimit){return false}var s=i(e,n);a[n]=s});return a},getRecordKeywords:function(e){var r=[];var t=Ember.A(["id"]);e.eachAttribute(function(e){t.push(e)});t.forEach(function(t){r.push(i(e,t))});return r},getRecordFilterValues:function(e){return{isNew:e.get("isNew"),isModified:e.get("isDirty")&&!e.get("isNew"),isClean:!e.get("isDirty")}},getRecordColor:function(e){var r="black";if(e.get("isNew")){r="green"}else if(e.get("isDirty")){r="blue"}return r},observeRecord:function(e,r){var t=Ember.A(),i=this;var a=Ember.A(["id","isNew","isDirty"]);e.eachAttribute(function(e){a.push(e)});a.forEach(function(a){var n=function(){r(i.wrapRecord(e))};Ember.addObserver(e,a,n);t.push(function(){Ember.removeObserver(e,a,n)})});var n=function(){t.forEach(function(e){e()})};return n}})});r("ember-data/system/debug/debug_info",["ember-data/system/model","exports"],function(e,r){"use strict";var t=e.Model;t.reopen({_debugInfo:function(){var e=["id"],r={belongsTo:[],hasMany:[]},t=[];this.eachAttribute(function(r,t){e.push(r)},this);this.eachRelationship(function(e,i){r[i.kind].push(e);t.push(e)});var i=[{name:"Attributes",properties:e,expand:true},{name:"Belongs To",properties:r.belongsTo,expand:true},{name:"Has Many",properties:r.hasMany,expand:true},{name:"Flags",properties:["isLoaded","isDirty","isSaving","isDeleted","isError","isNew","isValid"]}];return{propertyInfo:{includeOtherProperties:true,groups:i,expensiveProperties:t}}}});r["default"]=t});r("ember-data/system/map",["exports"],function(e){"use strict";var r,t;function i(){Ember.OrderedSet.apply(this,arguments)}function a(){Ember.Map.apply(this,arguments)}function n(){Ember.MapWithDefault.apply(this,arguments)}var s=Ember.Map.create();s.set("key","value");var o=false;s.forEach(function(e,r){o=e==="key"&&r==="value"});a.prototype=Object.create(Ember.Map.prototype);n.prototype=Object.create(Ember.MapWithDefault.prototype);i.prototype=Object.create(Ember.OrderedSet.prototype);i.create=function(){return new i};function u(e){return function(r,t){e.call(this,t,r)}}if(o){r=function(e,r){this.__super$forEach(u(e),r)};t=function(e){this.remove(e)};a.prototype.__super$forEach=Ember.Map.prototype.forEach;a.prototype.forEach=r;a.prototype["delete"]=t;n.prototype.forEach=r;n.prototype.__super$forEach=Ember.MapWithDefault.prototype.forEach;n.prototype["delete"]=t;i.prototype["delete"]=t}n.constructor=n;a.constructor=a;n.create=function(e){if(e){return new n(e)}else{return new a}};a.create=function(){return new this.constructor};e["default"]=a;e.Map=a;e.MapWithDefault=n;e.OrderedSet=i});r("ember-data/system/model",["ember-data/system/model/model","ember-data/system/model/attributes","ember-data/system/model/states","ember-data/system/model/errors","exports"],function(e,r,t,i,a){"use strict";var n=e["default"];var s=r["default"];var o=t["default"];var u=i["default"];a.Model=n;a.RootState=o;a.attr=s;a.Errors=u});r("ember-data/system/model/attributes",["ember-data/system/model/model","ember-data/system/map","exports"],function(e,r,t){"use strict";var i=e["default"];var a=r.Map;var n=Ember.get;i.reopenClass({attributes:Ember.computed(function(){var e=a.create();this.eachComputedProperty(function(r,t){if(t.isAttribute){t.name=r;e.set(r,t)}});return e}).readOnly(),transformedAttributes:Ember.computed(function(){var e=a.create();this.eachAttribute(function(r,t){if(t.type){e.set(r,t.type)}});return e}).readOnly(),eachAttribute:function(e,r){n(this,"attributes").forEach(function(t,i){e.call(r,i,t)},r)},eachTransformedAttribute:function(e,r){n(this,"transformedAttributes").forEach(function(t,i){e.call(r,i,t)})}});i.reopen({eachAttribute:function(e,r){this.constructor.eachAttribute(e,r)}});function s(e,r,t){if(typeof r.defaultValue==="function"){return r.defaultValue.apply(null,arguments)}else{return r.defaultValue}}function o(e,r){return e._attributes.hasOwnProperty(r)||e._inFlightAttributes.hasOwnProperty(r)||e._data.hasOwnProperty(r) -}function u(e,r){if(e._attributes.hasOwnProperty(r)){return e._attributes[r]}else if(e._inFlightAttributes.hasOwnProperty(r)){return e._inFlightAttributes[r]}else{return e._data[r]}}t["default"]=function d(e,r){r=r||{};var t={type:e,isAttribute:true,options:r};return Ember.computed("data",function(e,t){if(arguments.length>1){var i=u(this,e);if(t!==i){this._attributes[e]=t;this.send("didSetProperty",{name:e,oldValue:i,originalValue:this._data[e],value:t})}return t}else if(o(this,e)){return u(this,e)}else{return s(this,r,e)}}).meta(t)}});r("ember-data/system/model/errors",["ember-data/system/map","exports"],function(e,r){"use strict";var t=Ember.get;var i=Ember.isEmpty;var a=Ember.EnumerableUtils.map;var n=e.MapWithDefault;r["default"]=Ember.Object.extend(Ember.Enumerable,Ember.Evented,{registerHandlers:function(e,r,t){this.on("becameInvalid",e,r);this.on("becameValid",e,t)},errorsByAttributeName:Ember.reduceComputed("content",{initialValue:function(){return n.create({defaultValue:function(){return Ember.A()}})},addedItem:function(e,r){e.get(r.attribute).pushObject(r);return e},removedItem:function(e,r){e.get(r.attribute).removeObject(r);return e}}),errorsFor:function(e){return t(this,"errorsByAttributeName").get(e)},messages:Ember.computed.mapBy("content","message"),content:Ember.computed(function(){return Ember.A()}),unknownProperty:function(e){var r=this.errorsFor(e);if(i(r)){return null}return r},nextObject:function(e,r,i){return t(this,"content").objectAt(e)},length:Ember.computed.oneWay("content.length").readOnly(),isEmpty:Ember.computed.not("length").readOnly(),add:function(e,r){var i=t(this,"isEmpty");r=this._findOrCreateMessages(e,r);t(this,"content").addObjects(r);this.notifyPropertyChange(e);this.enumerableContentDidChange();if(i&&!t(this,"isEmpty")){this.trigger("becameInvalid")}},_findOrCreateMessages:function(e,r){var t=this.errorsFor(e);return a(Ember.makeArray(r),function(r){return t.findBy("message",r)||{attribute:e,message:r}})},remove:function(e){if(t(this,"isEmpty")){return}var r=t(this,"content").rejectBy("attribute",e);t(this,"content").setObjects(r);this.notifyPropertyChange(e);this.enumerableContentDidChange();if(t(this,"isEmpty")){this.trigger("becameValid")}},clear:function(){if(t(this,"isEmpty")){return}t(this,"content").clear();this.enumerableContentDidChange();this.trigger("becameValid")},has:function(e){return!i(this.errorsFor(e))}})});r("ember-data/system/model/model",["ember-data/system/model/states","ember-data/system/model/errors","ember-data/system/promise_proxies","ember-data/system/relationships/relationship","exports"],function(e,r,i,a,n){"use strict";var s=e["default"];var o=r["default"];var u=i.PromiseObject;var d=a.createRelationshipFor;var c=Ember.get;var l=Ember.set;var f=Ember.merge;var h=Ember.RSVP.Promise;var p=Ember.ArrayPolyfills.forEach;var m=Ember.ArrayPolyfills.map;var y;var v=Ember.computed("currentState",function(e,r){return c(c(this,"currentState"),e)}).readOnly();var b=Object.create(null);var g=Object.create(null);function R(e){return g[e]||(g[e]=e.split("."))}function E(e){return b[e]||(b[e]=R(e)[0])}var _=Ember.Object.extend(Ember.Evented,{_recordArrays:undefined,_relationships:undefined,_loadingRecordArrays:undefined,isEmpty:v,isLoading:v,isLoaded:v,isDirty:v,isSaving:v,isDeleted:v,isNew:v,isValid:v,dirtyType:v,isError:false,isReloading:false,clientId:null,id:null,currentState:s.empty,errors:Ember.computed(function(){var e=o.create();e.registerHandlers(this,function(){this.send("becameInvalid")},function(){this.send("becameValid")});return e}).readOnly(),serialize:function(e){var r=c(this,"store");return r.serialize(this,e)},toJSON:function(e){if(!y){y=t("ember-data/serializers/json_serializer")["default"]}var r=y.create({container:this.container});return r.serialize(this,e)},didLoad:Ember.K,didUpdate:Ember.K,didCreate:Ember.K,didDelete:Ember.K,becameInvalid:Ember.K,becameError:Ember.K,data:Ember.computed(function(){this._data=this._data||{};return this._data}).readOnly(),_data:null,init:function(){this._super();this._setup()},_setup:function(){this._changesToSync={};this._deferredTriggers=[];this._data={};this._attributes={};this._inFlightAttributes={};this._relationships={};this._implicitRelationships=Object.create(null);var e=this;this.constructor.eachRelationship(function(r,t){e._relationships[r]=d(e,t,e.store)})},send:function(e,r){var t=c(this,"currentState");if(!t[e]){this._unhandledEvent(t,e,r)}return t[e](this,r)},transitionTo:function(e){var r=E(e);var t=c(this,"currentState");var i=t;do{if(i.exit){i.exit(this)}i=i.parentState}while(!i.hasOwnProperty(r));var a=R(e);var n=[],s=[],o,u;for(o=0,u=a.length;o0;if(!i){e.send("rolledBack")}},pushedData:Ember.K,becomeDirty:Ember.K,willCommit:function(e){e.transitionTo("inFlight")},reloadRecord:function(e,t){t(r(e,"store").reloadRecord(e))},rolledBack:function(e){e.transitionTo("loaded.saved")},becameInvalid:function(e){e.transitionTo("invalid")},rollback:function(e){e.rollback()}},inFlight:{isSaving:true,didSetProperty:i,becomeDirty:Ember.K,pushedData:Ember.K,unloadRecord:function(e){},willCommit:Ember.K,didCommit:function(e){var t=r(this,"dirtyType");e.transitionTo("saved");e.send("invokeLifecycleCallbacks",t)},becameInvalid:function(e){e.transitionTo("invalid");e.send("invokeLifecycleCallbacks")},becameError:function(e){e.transitionTo("uncommitted");e.triggerLater("becameError",e)}},invalid:{isValid:false,deleteRecord:function(e){e.transitionTo("deleted.uncommitted");e.disconnectRelationships()},didSetProperty:function(e,t){r(e,"errors").remove(t.name);i(e,t)},becomeDirty:Ember.K,willCommit:function(e){r(e,"errors").clear();e.transitionTo("inFlight")},rolledBack:function(e){r(e,"errors").clear()},becameValid:function(e){e.transitionTo("uncommitted")},invokeLifecycleCallbacks:function(e){e.triggerLater("becameInvalid",e)},exit:function(e){e._inFlightAttributes={}}}};function n(e){var r={},t;for(var i in e){t=e[i];if(t&&typeof t==="object"){r[i]=n(t)}else{r[i]=t}}return r}function s(e,r){for(var t in r){e[t]=r[t]}return e}function o(e){var r=n(a);return s(r,e)}var u=o({dirtyType:"created",isNew:true});u.uncommitted.rolledBack=function(e){e.transitionTo("deleted.saved")};var d=o({dirtyType:"updated"});u.uncommitted.deleteRecord=function(e){e.disconnectRelationships();e.transitionTo("deleted.saved")};u.uncommitted.rollback=function(e){a.uncommitted.rollback.apply(this,arguments);e.transitionTo("deleted.saved")};u.uncommitted.propertyWasReset=Ember.K;function c(e){}d.inFlight.unloadRecord=c;d.uncommitted.deleteRecord=function(e){e.transitionTo("deleted.uncommitted");e.disconnectRelationships()};var l={isEmpty:false,isLoading:false,isLoaded:false,isDirty:false,isSaving:false,isDeleted:false,isNew:false,isValid:true,rolledBack:Ember.K,unloadRecord:function(e){e.clearRelationships();e.transitionTo("deleted.saved")},propertyWasReset:Ember.K,empty:{isEmpty:true,loadingData:function(e,r){e._loadingPromise=r;e.transitionTo("loading")},loadedData:function(e){e.transitionTo("loaded.created.uncommitted");e.notifyPropertyChange("data")},pushedData:function(e){e.transitionTo("loaded.saved");e.triggerLater("didLoad")}},loading:{isLoading:true,exit:function(e){e._loadingPromise=null},pushedData:function(e){e.transitionTo("loaded.saved");e.triggerLater("didLoad");t(e,"isError",false)},becameError:function(e){e.triggerLater("becameError",e)},notFound:function(e){e.transitionTo("empty")}},loaded:{initialState:"saved",isLoaded:true,loadingData:Ember.K,saved:{setup:function(e){var r=e._attributes;var t=false;for(var i in r){if(r.hasOwnProperty(i)){t=true;break}}if(t){e.adapterDidDirty()}},didSetProperty:i,pushedData:Ember.K,becomeDirty:function(e){e.transitionTo("updated.uncommitted")},willCommit:function(e){e.transitionTo("updated.inFlight")},reloadRecord:function(e,t){t(r(e,"store").reloadRecord(e))},deleteRecord:function(e){e.transitionTo("deleted.uncommitted");e.disconnectRelationships()},unloadRecord:function(e){e.clearRelationships();e.transitionTo("deleted.saved")},didCommit:function(e){e.send("invokeLifecycleCallbacks",r(e,"lastDirtyType"))},notFound:Ember.K},created:u,updated:d},deleted:{initialState:"uncommitted",dirtyType:"deleted",isDeleted:true,isLoaded:true,isDirty:true,setup:function(e){e.updateRecordArrays()},uncommitted:{willCommit:function(e){e.transitionTo("inFlight")},rollback:function(e){e.rollback()},becomeDirty:Ember.K,deleteRecord:Ember.K,rolledBack:function(e){e.transitionTo("loaded.saved")}},inFlight:{isSaving:true,unloadRecord:c,willCommit:Ember.K,didCommit:function(e){e.transitionTo("saved");e.send("invokeLifecycleCallbacks")},becameError:function(e){e.transitionTo("uncommitted");e.triggerLater("becameError",e)}},saved:{isDirty:false,setup:function(e){var t=r(e,"store");t.dematerializeRecord(e)},invokeLifecycleCallbacks:function(e){e.triggerLater("didDelete",e);e.triggerLater("didCommit",e)},willCommit:Ember.K,didCommit:Ember.K}},invokeLifecycleCallbacks:function(e,r){if(r==="created"){e.triggerLater("didCreate",e)}else{e.triggerLater("didUpdate",e)}e.triggerLater("didCommit",e)}};function f(e,r,t){e=s(r?Ember.create(r):{},e);e.parentState=r;e.stateName=t;for(var i in e){if(!e.hasOwnProperty(i)||i==="parentState"||i==="stateName"){continue}if(typeof e[i]==="object"){e[i]=f(e[i],e,t+"."+i)}}return e}l=f(l,null,"root");e["default"]=l});r("ember-data/system/promise_proxies",["exports"],function(e){"use strict";var r=Ember.RSVP.Promise;var t=Ember.get;var i=Ember.ArrayProxy.extend(Ember.PromiseProxyMixin);var a=Ember.ObjectProxy.extend(Ember.PromiseProxyMixin);var n=function(e,t){return a.create({promise:r.resolve(e,t)})};var s=function(e,t){return i.create({promise:r.resolve(e,t)})};var o=i.extend({reload:function(){return t(this,"content").reload()}});var u=function(e,t){return o.create({promise:r.resolve(e,t)})};e.PromiseArray=i;e.PromiseObject=a;e.PromiseManyArray=o;e.promiseArray=s;e.promiseObject=n;e.promiseManyArray=u});r("ember-data/system/record_array_manager",["ember-data/system/record_arrays","ember-data/system/map","exports"],function(e,r,t){"use strict";var i=e.RecordArray;var a=e.FilteredRecordArray;var n=e.AdapterPopulatedRecordArray;var s=e.ManyArray;var o=r.MapWithDefault;var u=r.OrderedSet;var d=Ember.get;var c=Ember.EnumerableUtils.forEach;t["default"]=Ember.Object.extend({init:function(){this.filteredRecordArrays=o.create({defaultValue:function(){return[]}});this.changedRecords=[];this._adapterPopulatedRecordArrays=[]},recordDidChange:function(e){if(this.changedRecords.push(e)!==1){return}Ember.run.schedule("actions",this,this.updateRecordArrays)},recordArraysForRecord:function(e){e._recordArrays=e._recordArrays||u.create();return e._recordArrays},updateRecordArrays:function(){c(this.changedRecords,function(e){if(d(e,"isDeleted")){this._recordWasDeleted(e)}else{this._recordWasChanged(e)}},this);this.changedRecords.length=0},_recordWasDeleted:function(e){var r=e._recordArrays;if(!r){return}r.forEach(function(r){r.removeRecord(e)});e._recordArrays=null},_recordWasChanged:function(e){var r=e.constructor;var t=this.filteredRecordArrays.get(r);var i;c(t,function(t){i=d(t,"filterFunction");this.updateRecordArray(t,i,r,e)},this);var a=e._loadingRecordArrays;if(a){for(var n=0,s=a.length;n0){a=i(this,"content").slice(e,e+r);this.get("relationship").removeRecords(a)}if(t){this.get("relationship").addRecords(t,e)}},reload:function(){return this.relationship.reload()},createRecord:function(e){var r=i(this,"store");var t=i(this,"type");var a;a=r.createRecord.call(r,t,e);this.pushObject(a);return a}})});r("ember-data/system/record_arrays/record_array",["ember-data/system/promise_proxies","exports"],function(e,r){"use strict";var t=e.PromiseArray;var i=Ember.get;r["default"]=Ember.ArrayProxy.extend(Ember.Evented,{type:null,content:null,isLoaded:false,isUpdating:false,store:null,objectAtContent:function(e){var r=i(this,"content");return r.objectAt(e)},update:function(){if(i(this,"isUpdating")){return}var e=i(this,"store");var r=i(this,"type");return e.fetchAll(r,this)},addRecord:function(e,r){var t=i(this,"content");if(r===undefined){t.addObject(e)}else{if(!t.contains(e)){t.insertAt(r,e)}}},pushRecord:function(e){i(this,"content").pushObject(e)},removeRecord:function(e){i(this,"content").removeObject(e)},save:function(){var e="DS: RecordArray#save "+i(this,"type");var r=Ember.RSVP.all(this.invoke("save"),e).then(function(e){return Ember.A(e)},null,"DS: RecordArray#save apply Ember.NativeArray");return t.create({promise:r})},_dissociateFromOwnRecords:function(){var e=this;this.forEach(function(r){var t=r._recordArrays;if(t){t["delete"](e)}})},willDestroy:function(){this._dissociateFromOwnRecords();this._super()}})});r("ember-data/system/relationship-meta",["ember-inflector/system","exports"],function(e,r){"use strict";var t=e.singularize;function i(e,r){var i,a;i=r.type||r.key;if(typeof i==="string"){if(r.kind==="hasMany"){i=t(i)}a=e.modelFor(i)}else{a=r.type}return a}r.typeForRelationshipMeta=i;function a(e,r){return{key:r.key,kind:r.kind,type:i(e,r),options:r.options,parentType:r.parentType,isRelationship:true}}r.relationshipFromMeta=a});r("ember-data/system/relationships",["./relationships/belongs_to","./relationships/has_many","ember-data/system/relationships/ext","exports"],function(e,r,t,i){"use strict";var a=e["default"];var n=r["default"];i.belongsTo=a;i.hasMany=n});r("ember-data/system/relationships/belongs_to",["ember-data/system/model","exports"],function(e,r){"use strict";var t=e.Model;function i(e,r){if(typeof e==="object"){r=e;e=undefined}else{}r=r||{};var t={type:e,isRelationship:true,options:r,kind:"belongsTo",key:null};return Ember.computed(function(e,r){if(arguments.length>1){if(r===undefined){r=null}if(r&&r.then){this._relationships[e].setRecordPromise(r)}else{this._relationships[e].setRecord(r)}}return this._relationships[e].getRecord()}).meta(t)}t.reopen({notifyBelongsToAdded:function(e,r){this.notifyPropertyChange(e)},notifyBelongsToRemoved:function(e){this.notifyPropertyChange(e)}});r["default"]=i});r("ember-data/system/relationships/ext",["ember-data/system/relationship-meta","ember-data/system/model","ember-data/system/map"],function(e,r,t){"use strict";var i=e.typeForRelationshipMeta;var a=e.relationshipFromMeta;var n=r.Model;var s=t.Map;var o=t.MapWithDefault;var u=Ember.get;var d=Ember.ArrayPolyfills.filter;n.reopen({didDefineProperty:function(e,r,t){if(t instanceof Ember.ComputedProperty){var i=t.meta();i.parentType=e.constructor}}});n.reopenClass({typeForRelationship:function(e){var r=u(this,"relationshipsByName").get(e);return r&&r.type},inverseMap:Ember.computed(function(){return Object.create(null)}),inverseFor:function(e){var r=u(this,"inverseMap");if(r[e]){return r[e]}else{var t=this._findInverseFor(e);r[e]=t;return t}},_findInverseFor:function(e){var r=this.typeForRelationship(e);if(!r){return null}var t=this.metaForProperty(e).options;if(t.inverse===null){return null}var i,a,n;if(t.inverse){i=t.inverse;n=Ember.get(r,"relationshipsByName").get(i);a=n.kind}else{var s=c(this,r);if(s.length===0){return null}var o=d.call(s,function(t){var i=r.metaForProperty(t.name).options;return e===i.inverse});if(o.length===1){s=o}i=s[0].name;a=s[0].kind}function c(r,t,i){var a=i||[];var n=u(t,"relationships");if(!n){return}var s=n.get(r);s=d.call(s,function(r){var i=t.metaForProperty(r.name).options;if(!i.inverse){return true}return e===i.inverse});if(s){a.push.apply(a,s)}if(r.superclass){c(r.superclass,t,a)}return a}return{type:r,name:i,kind:a}},relationships:Ember.computed(function(){var e=new o({defaultValue:function(){return[]}});this.eachComputedProperty(function(r,t){if(t.isRelationship){t.key=r;var a=e.get(i(this.store,t));a.push({name:r,kind:t.kind})}});return e}).cacheable(false).readOnly(),relationshipNames:Ember.computed(function(){var e={hasMany:[],belongsTo:[]};this.eachComputedProperty(function(r,t){if(t.isRelationship){e[t.kind].push(r)}});return e}),relatedTypes:Ember.computed(function(){var e;var r=Ember.A();this.eachComputedProperty(function(t,a){if(a.isRelationship){a.key=t;e=i(this.store,a);if(!r.contains(e)){r.push(e)}}});return r}).cacheable(false).readOnly(),relationshipsByName:Ember.computed(function(){var e=s.create();this.eachComputedProperty(function(r,t){if(t.isRelationship){t.key=r;var n=a(this.store,t);n.type=i(this.store,t);e.set(r,n)}});return e}).cacheable(false).readOnly(),fields:Ember.computed(function(){var e=s.create();this.eachComputedProperty(function(r,t){if(t.isRelationship){e.set(r,t.kind)}else if(t.isAttribute){e.set(r,"attribute")}});return e}).readOnly(),eachRelationship:function(e,r){u(this,"relationshipsByName").forEach(function(t,i){e.call(r,i,t)})},eachRelatedType:function(e,r){u(this,"relatedTypes").forEach(function(t){e.call(r,t)})},determineRelationshipType:function(e){var r=e.key;var t=e.kind;var i=this.inverseFor(r);var a,n;if(!i){return t==="belongsTo"?"oneToNone":"manyToNone"}a=i.name;n=i.kind;if(n==="belongsTo"){return t==="belongsTo"?"oneToOne":"manyToOne"}else{return t==="belongsTo"?"oneToMany":"manyToMany"}}});n.reopen({eachRelationship:function(e,r){this.constructor.eachRelationship(e,r)},relationshipFor:function(e){return u(this.constructor,"relationshipsByName").get(e)},inverseFor:function(e){return this.constructor.inverseFor(e)}})});r("ember-data/system/relationships/has_many",["ember-data/system/model","exports"],function(e,r){"use strict";var t=e.Model;function i(e,r){if(typeof e==="object"){r=e;e=undefined}r=r||{};var t={type:e,isRelationship:true,options:r,kind:"hasMany",key:null};return Ember.computed(function(e){var r=this._relationships[e];return r.getRecords()}).meta(t).readOnly()}t.reopen({notifyHasManyAdded:function(e,r,t){var i=this._relationships[e];var a=i.manyArray;a.addRecord(r,t);this.notifyPropertyChange(e)},notifyHasManyRemoved:function(e,r){var t=this._relationships[e];var i=t.manyArray;i.removeRecord(r)}});r["default"]=i});r("ember-data/system/relationships/relationship",["ember-data/system/promise_proxies","ember-data/system/map","exports"],function(e,r,t){"use strict";var i=e.PromiseManyArray;var a=e.PromiseObject;var n=r.OrderedSet;var s=function(e,r,t,i){this.members=new n;this.store=e;this.key=i.key;this.inverseKey=t;this.record=r;this.key=i.key;this.isAsync=i.options.async;this.relationshipMeta=i;this.inverseKeyForImplicit=this.store.modelFor(this.record.constructor).typeKey+this.key;this.linkPromise=null};s.prototype={constructor:s,destroy:Ember.K,clear:function(){this.members.forEach(function(e){this.removeRecord(e)},this)},disconnect:function(){this.members.forEach(function(e){this.removeRecordFromInverse(e)},this)},reconnect:function(){this.members.forEach(function(e){this.addRecordToInverse(e)},this)},removeRecords:function(e){var r=this;e.forEach(function(e){r.removeRecord(e)})},addRecords:function(e,r){var t=this;e.forEach(function(e){t.addRecord(e,r);if(r!==undefined){r++}})},addRecord:function(e,r){if(!this.members.has(e)){this.members.add(e);this.notifyRecordRelationshipAdded(e,r);if(this.inverseKey){e._relationships[this.inverseKey].addRecord(this.record)}else{if(!e._implicitRelationships[this.inverseKeyForImplicit]){e._implicitRelationships[this.inverseKeyForImplicit]=new s(this.store,e,this.key,{options:{}})}e._implicitRelationships[this.inverseKeyForImplicit].addRecord(this.record)}this.record.updateRecordArrays()}},removeRecord:function(e){if(this.members.has(e)){this.removeRecordFromOwn(e);if(this.inverseKey){this.removeRecordFromInverse(e)}else{if(e._implicitRelationships[this.inverseKeyForImplicit]){e._implicitRelationships[this.inverseKeyForImplicit].removeRecord(this.record)}}}},addRecordToInverse:function(e){if(this.inverseKey){e._relationships[this.inverseKey].addRecord(this.record)}},removeRecordFromInverse:function(e){var r=e._relationships[this.inverseKey];if(r){r.removeRecordFromOwn(this.record)}},removeRecordFromOwn:function(e){this.members["delete"](e);this.notifyRecordRelationshipRemoved(e);this.record.updateRecordArrays()},updateLink:function(e){if(e!==this.link){this.link=e;this.linkPromise=null;this.record.notifyPropertyChange(this.key)}},findLink:function(){if(this.linkPromise){return this.linkPromise}else{var e=this.fetchLink();this.linkPromise=e;return e.then(function(e){return e})}},updateRecordsFromAdapter:function(e){this.computeChanges(e)},notifyRecordRelationshipAdded:Ember.K,notifyRecordRelationshipRemoved:Ember.K};var o=function(e,r,t,i){this._super$constructor(e,r,t,i);this.belongsToType=i.type;this.manyArray=e.recordArrayManager.createManyArray(this.belongsToType,Ember.A());this.manyArray.relationship=this;this.isPolymorphic=i.options.polymorphic;this.manyArray.isPolymorphic=this.isPolymorphic};o.prototype=Object.create(s.prototype);o.prototype.constructor=o;o.prototype._super$constructor=s;o.prototype.destroy=function(){this.manyArray.destroy()};o.prototype.notifyRecordRelationshipAdded=function(e,r){this.record.notifyHasManyAdded(this.key,e,r)};o.prototype.notifyRecordRelationshipRemoved=function(e){this.record.notifyHasManyRemoved(this.key,e)};o.prototype.reload=function(){var e=this;if(this.link){return this.fetchLink()}else{return this.store.scheduleFetchMany(this.manyArray.toArray()).then(function(){e.manyArray.set("isLoaded",true);return e.manyArray})}};o.prototype.computeChanges=function(e){var r=this.members;var t=[];var i;var a;var n;e=d(e);r.forEach(function(r){if(e.has(r))return;t.push(r)});this.removeRecords(t);var s=this.manyArray;e=e.toArray();i=e.length;for(n=0;n1){I(i,t,r,c,n).then(o).then(u(n)).then(null,d(n))}else if(c.length===1){var l=Ember.A(e).findBy("record",a[0]);s(l)}else{}})}else{y(e,s)}},getById:function(e,r){if(this.hasRecordForId(e,r)){return this.recordForId(e,r)}else{return null}},reloadRecord:function(e){var r=e.constructor;var t=this.adapterFor(r);var i=f(e,"id");return this.scheduleFetch(e)},hasRecordForId:function(e,r){var t=this.modelFor(e);var i=z(r);return!!this.typeMapFor(t).idToRecord[i]},recordForId:function(e,r){var t=this.modelFor(e);var i=z(r);var a=this.typeMapFor(t).idToRecord;var n=a[i];if(!n||!a[i]){n=this.buildRecord(t,i)}return n},findMany:function(e){var r=this;return g.all(b(e,function(e){return r._findByRecord(e)}))},findHasMany:function(e,r,t){var i=this.adapterFor(e.constructor);return L(i,this,e,r,t)},findBelongsTo:function(e,r,t){var i=this.adapterFor(e.constructor);return j(i,this,e,r,t)},findQuery:function(e,r){var t=this.modelFor(e);var i=this.recordArrayManager.createAdapterPopulatedRecordArray(t,r);var a=this.adapterFor(t);return c(U(a,this,t,r,i))},findAll:function(e){var r=this.modelFor(e);return this.fetchAll(r,this.all(r))},fetchAll:function(e,r){var t=this.adapterFor(e);var i=this.typeMapFor(e).metadata.since;h(r,"isUpdating",true);return c(K(t,this,e,i))},didUpdateAll:function(e){var r=this.typeMapFor(e).findAllCache;h(r,"isUpdating",false)},all:function(e){var r=this.modelFor(e);var t=this.typeMapFor(r);var i=t.findAllCache;if(i){return i}var a=this.recordArrayManager.createRecordArray(r);t.findAllCache=a;return a},unloadAll:function(e){var r=this.modelFor(e);var t=this.typeMapFor(r);var i=t.records.slice();var a;for(var n=0;nE;R--){o=n[R-1];g=o[0];if(g.test(e)){break}}o=o||[];g=o[0];u=o[1];d=e.replace(g,u);return d}};e["default"]=o});r("ember-inflector/system/string",["./inflector","exports"],function(e,r){"use strict";var t=e["default"];function i(e){return t.inflector.pluralize(e)}function a(e){return t.inflector.singularize(e)}r.pluralize=i;r.singularize=a});e.DS=t("ember-data")["default"]})(this); diff --git a/vendor/assets/ember/production/ember.js b/vendor/assets/ember/production/ember.js deleted file mode 100644 index 0ea9acd3..00000000 --- a/vendor/assets/ember/production/ember.js +++ /dev/null @@ -1,14 +0,0 @@ -// Fetched from channel: release, with url http://builds.emberjs.com/release/ember.min.js -// Fetched on: 2014-11-24T13:02:10Z -!function(){var e,t,r,n,i;!function(){if(i=this.Ember=this.Ember||{},"undefined"==typeof i&&(i={}),"undefined"==typeof i.__loader){var a={},s={};e=function(e,t,r){a[e]={deps:t,callback:r}},n=r=t=function(e){function r(t){if("."!==t.charAt(0))return t;for(var r=t.split("/"),n=e.split("/").slice(0,-1),i=0,a=r.length;a>i;i++){var s=r[i];if(".."===s)n.pop();else{if("."===s)continue;n.push(s)}}return n.join("/")}if(s.hasOwnProperty(e))return s[e];if(s[e]={},!a[e])throw new Error("Could not find module "+e);for(var n,i=a[e],o=i.deps,u=i.callback,l=[],c=0,h=o.length;h>c;c++)l.push("exports"===o[c]?n={}:t(r(o[c])));var p=u.apply(this,l);return s[e]=n||p},n._eak_seen=a,i.__loader={define:e,require:r,registry:a}}else e=i.__loader.define,n=r=t=i.__loader.require}(),e("backburner",["backburner/utils","backburner/platform","backburner/binary-search","backburner/deferred-action-queues","exports"],function(e,t,r,n,i){"use strict";function a(e,t){this.queueNames=e,this.options=t||{},this.options.defaultQueue||(this.options.defaultQueue=e[0]),this.instanceStack=[],this._debouncees=[],this._throttlers=[],this._timers=[]}function s(e){return e.onError||e.onErrorTarget&&e.onErrorTarget[e.onErrorMethod]}function o(e){e.begin(),e._autorun=E.setTimeout(function(){e._autorun=null,e.end()})}function u(e,t,r){var n=g();(!e._laterTimer||tr;r+=2)e.schedule(e.options.defaultQueue,null,t[r])}),e._timers.length&&u(e,e._timers[0],e._timers[0]-i)}function c(e,t,r){return p(e,t,r)}function h(e,t,r){return p(e,t,r)}function p(e,t,r){for(var n,i=-1,a=0,s=r.length;s>a;a++)if(n=r[a],n[0]===e&&n[1]===t){i=a;break}return i}var m=e.each,f=e.isString,d=e.isFunction,v=e.isNumber,b=e.isCoercableNumber,y=e.wrapInTryCatch,g=e.now,_=t.needsIETryCatchFix,w=r["default"],x=n["default"],C=[].slice,O=[].pop,E=this;if(a.prototype={begin:function(){var e=this.options,t=e&&e.onBegin,r=this.currentInstance;r&&this.instanceStack.push(r),this.currentInstance=new x(this.queueNames,e),t&&t(this.currentInstance,r)},end:function(){var e=this.options,t=e&&e.onEnd,r=this.currentInstance,n=null,i=!1;try{r.flush()}finally{i||(i=!0,this.currentInstance=null,this.instanceStack.length&&(n=this.instanceStack.pop(),this.currentInstance=n),t&&t(r,n))}},run:function(e,t){var r=s(this.options);this.begin(),t||(t=e,e=null),f(t)&&(t=e[t]);var n=C.call(arguments,2),i=!1;if(r)try{return t.apply(e,n)}catch(a){r(a)}finally{i||(i=!0,this.end())}else try{return t.apply(e,n)}finally{i||(i=!0,this.end())}},defer:function(e,t,r){r||(r=t,t=null),f(r)&&(r=t[r]);var n,i=this.DEBUG?new Error:void 0,a=arguments.length;if(a>3){n=new Array(a-3);for(var s=3;a>s;s++)n[s-3]=arguments[s]}else n=void 0;return this.currentInstance||o(this),this.currentInstance.schedule(e,t,r,n,!1,i)},deferOnce:function(e,t,r){r||(r=t,t=null),f(r)&&(r=t[r]);var n,i=this.DEBUG?new Error:void 0,a=arguments.length;if(a>3){n=new Array(a-3);for(var s=3;a>s;s++)n[s-3]=arguments[s]}else n=void 0;return this.currentInstance||o(this),this.currentInstance.schedule(e,t,r,n,!0,i)},setTimeout:function(){function e(){if(y)try{i.apply(o,r)}catch(e){y(e)}else i.apply(o,r)}for(var t=arguments.length,r=new Array(t),n=0;t>n;n++)r[n]=arguments[n];var i,a,o,l,c,h,p=r.length;if(0!==p){if(1===p)i=r.shift(),a=0;else if(2===p)l=r[0],c=r[1],d(c)||d(l[c])?(o=r.shift(),i=r.shift(),a=0):b(c)?(i=r.shift(),a=r.shift()):(i=r.shift(),a=0);else{var m=r[r.length-1];a=b(m)?r.pop():0,l=r[0],h=r[1],d(h)||f(h)&&null!==l&&h in l?(o=r.shift(),i=r.shift()):i=r.shift()}var v=g()+parseInt(a,10);f(i)&&(i=o[i]);var y=s(this.options),_=w(v,this._timers);return this._timers.splice(_,0,v,e),u(this,v,a),e}},throttle:function(e,t){var r,n,i,a,s=this,o=arguments,u=O.call(o);return v(u)||f(u)?(r=u,u=!0):r=O.call(o),r=parseInt(r,10),i=h(e,t,this._throttlers),i>-1?this._throttlers[i]:(a=E.setTimeout(function(){u||s.run.apply(s,o);var r=h(e,t,s._throttlers);r>-1&&s._throttlers.splice(r,1)},r),u&&this.run.apply(this,o),n=[e,t,a],this._throttlers.push(n),n)},debounce:function(e,t){var r,n,i,a,s=this,o=arguments,u=O.call(o);return v(u)||f(u)?(r=u,u=!1):r=O.call(o),r=parseInt(r,10),n=c(e,t,this._debouncees),n>-1&&(i=this._debouncees[n],this._debouncees.splice(n,1),clearTimeout(i[2])),a=E.setTimeout(function(){u||s.run.apply(s,o);var r=c(e,t,s._debouncees);r>-1&&s._debouncees.splice(r,1)},r),u&&-1===n&&s.run.apply(s,o),i=[e,t,a],s._debouncees.push(i),i},cancelTimers:function(){var e=function(e){clearTimeout(e[2])};m(this._throttlers,e),this._throttlers=[],m(this._debouncees,e),this._debouncees=[],this._laterTimer&&(clearTimeout(this._laterTimer),this._laterTimer=null),this._timers=[],this._autorun&&(clearTimeout(this._autorun),this._autorun=null)},hasTimers:function(){return!!this._timers.length||!!this._debouncees.length||!!this._throttlers.length||this._autorun},cancel:function(e){var t=typeof e;if(e&&"object"===t&&e.queue&&e.method)return e.queue.cancel(e);if("function"!==t)return"[object Array]"===Object.prototype.toString.call(e)?this._cancelItem(h,this._throttlers,e)||this._cancelItem(c,this._debouncees,e):void 0;for(var r=0,n=this._timers.length;n>r;r+=2)if(this._timers[r+1]===e)return this._timers.splice(r,2),0===r&&(this._laterTimer&&(clearTimeout(this._laterTimer),this._laterTimer=null),this._timers.length>0&&u(this,this._timers[0],this._timers[0]-g())),!0},_cancelItem:function(e,t,r){var n,i;return r.length<3?!1:(i=e(r[0],r[1],t),i>-1&&(n=t[i],n[2]===r[2])?(t.splice(i,1),clearTimeout(r[2]),!0):!1)}},a.prototype.schedule=a.prototype.defer,a.prototype.scheduleOnce=a.prototype.deferOnce,a.prototype.later=a.prototype.setTimeout,_){var P=a.prototype.run;a.prototype.run=y(P);var A=a.prototype.end;a.prototype.end=y(A)}i["default"]=a}),e("backburner.umd",["./backburner"],function(t){"use strict";var r=t["default"];"function"==typeof e&&e.amd?e(function(){return r}):"undefined"!=typeof module&&module.exports?module.exports=r:"undefined"!=typeof this&&(this.Backburner=r)}),e("backburner/binary-search",["exports"],function(e){"use strict";e["default"]=function(e,t){for(var r,n,i=0,a=t.length-2;a>i;)n=(a-i)/2,r=i+n-n%2,e>=t[r]?i=r+2:a=r;return e>=t[i]?i+2:i}}),e("backburner/deferred-action-queues",["./utils","./queue","exports"],function(e,t,r){"use strict";function n(e,t){var r=this.queues={};this.queueNames=e=e||[],this.options=t,s(e,function(e){r[e]=new u(e,t[e],t)})}function i(e){throw new Error("You attempted to schedule an action in a queue ("+e+") that doesn't exist")}function a(e,t){for(var r,n,i=0,a=t;a>=i;i++)if(r=e.queueNames[i],n=e.queues[r],n._queue.length)return i;return-1}var s=e.each,o=e.isString,u=t["default"];n.prototype={schedule:function(e,t,r,n,a,s){var o=this.queues,u=o[e];return u||i(e),a?u.pushUnique(t,r,n,s):u.push(t,r,n,s)},invoke:function(e,t,r){r&&r.length>0?t.apply(e,r):t.call(e)},invokeWithOnError:function(e,t,r,n,i){try{r&&r.length>0?t.apply(e,r):t.call(e)}catch(a){n(a,i)}},flush:function(){for(var e,t,r,n,i=this.queues,s=this.queueNames,u=0,l=s.length,c=this.options,h=c.onError||c.onErrorTarget&&c.onErrorTarget[c.onErrorMethod],p=h?this.invokeWithOnError:this.invoke;l>u;){e=s[u],t=i[e],r=t._queueBeingFlushed=t._queue.slice(),t._queue=[],t.targetQueues=Object.create(null);var m,f,d,v,b=t.options,y=b&&b.before,g=b&&b.after,_=0,w=r.length;for(w&&y&&y();w>_;)m=r[_],f=r[_+1],d=r[_+2],v=r[_+3],o(f)&&(f=m[f]),f&&p(m,f,d,h,v),_+=4;t._queueBeingFlushed=null,w&&g&&g(),-1!==(n=a(this,u))?u=n:u++}}},r["default"]=n}),e("backburner/platform",["exports"],function(e){"use strict";var t=function(e,t){try{t()}catch(e){}return!!e}();e.needsIETryCatchFix=t}),e("backburner/queue",["exports"],function(e){"use strict";function t(e,t,r){this.name=e,this.globalOptions=r||{},this.options=t,this._queue=[],this.targetQueues=Object.create(null),this._queueBeingFlushed=void 0}t.prototype={push:function(e,t,r,n){var i=this._queue;return i.push(e,t,r,n),{queue:this,target:e,method:t}},pushUniqueWithoutGuid:function(e,t,r,n){for(var i=this._queue,a=0,s=i.length;s>a;a+=4){var o=i[a],u=i[a+1];if(o===e&&u===t)return i[a+2]=r,void(i[a+3]=n)}i.push(e,t,r,n)},targetQueue:function(e,t,r,n,i){for(var a=this._queue,s=0,o=e.length;o>s;s+=4){var u=e[s],l=e[s+1];if(u===r)return a[l+2]=n,void(a[l+3]=i)}e.push(r,a.push(t,r,n,i)-4)},pushUniqueWithGuid:function(e,t,r,n,i){var a=this.targetQueues[e];return a?this.targetQueue(a,t,r,n,i):this.targetQueues[e]=[r,this._queue.push(t,r,n,i)-4],{queue:this,target:t,method:r}},pushUnique:function(e,t,r,n){var i=(this._queue,this.globalOptions.GUID_KEY);if(e&&i){var a=e[i];if(a)return this.pushUniqueWithGuid(a,e,t,r,n)}return this.pushUniqueWithoutGuid(e,t,r,n),{queue:this,target:e,method:t}},flush:function(){var e,t,r,n,i,a=this._queue,s=this.globalOptions,o=this.options,u=o&&o.before,l=o&&o.after,c=s.onError||s.onErrorTarget&&s.onErrorTarget[s.onErrorMethod],h=a.length;for(this.targetQueues=Object.create(null),h&&u&&u(),i=0;h>i;i+=4)if(e=a[i],t=a[i+1],r=a[i+2],n=a[i+3],r&&r.length>0)if(c)try{t.apply(e,r)}catch(p){c(p)}else t.apply(e,r);else if(c)try{t.call(e)}catch(p){c(p)}else t.call(e);h&&l&&l(),a.length>h?(this._queue=a.slice(h),this.flush()):this._queue.length=0},cancel:function(e){var t,r,n,i,a=this._queue,s=e.target,o=e.method,u=this.globalOptions.GUID_KEY;if(u&&this.targetQueues&&s){var l=this.targetQueues[s[u]];if(l)for(n=0,i=l.length;i>n;n++)l[n]===o&&l.splice(n,1)}for(n=0,i=a.length;i>n;n+=4)if(t=a[n],r=a[n+1],t===s&&r===o)return a.splice(n,4),!0;if(a=this._queueBeingFlushed)for(n=0,i=a.length;i>n;n+=4)if(t=a[n],r=a[n+1],t===s&&r===o)return a[n+1]=null,!0}},e["default"]=t}),e("backburner/utils",["exports"],function(e){"use strict";function t(e,t){for(var r=0;r-1){try{if(e.existsSync(s)){var o,u=e.readFileSync(s,{encoding:"utf8"}),l=u.split("/").slice(-1)[0].trim(),c=u.split(" ")[1];if(c){var h=t.join(a,c.trim());o=e.readFileSync(h)}else o=l;i.push(o.slice(0,10))}}catch(p){console.error(p.stack)}return i.join(".")}return n}}),e("container",["container/container","exports"],function(e,t){"use strict";i.MODEL_FACTORY_INJECTIONS=!1,i.ENV&&"undefined"!=typeof i.ENV.MODEL_FACTORY_INJECTIONS&&(i.MODEL_FACTORY_INJECTIONS=!!i.ENV.MODEL_FACTORY_INJECTIONS);var r=e["default"];t["default"]=r}),e("container/container",["ember-metal/core","ember-metal/keys","ember-metal/dictionary","exports"],function(e,t,r,n){"use strict";function i(e){this.parent=e,this.children=[],this.resolver=e&&e.resolver||function(){},this.registry=C(e?e.registry:null),this.cache=C(e?e.cache:null),this.factoryCache=C(e?e.factoryCache:null),this.resolveCache=C(e?e.resolveCache:null),this.typeInjections=C(e?e.typeInjections:null),this.injections=C(null),this.normalizeCache=C(null),this.factoryTypeInjections=C(e?e.factoryTypeInjections:null),this.factoryInjections=C(null),this._options=C(e?e._options:null),this._typeOptions=C(e?e._typeOptions:null)}function a(e,t){var r=e.resolveCache[t];if(r)return r;var n=e.resolver(t)||e.registry[t];return e.resolveCache[t]=n,n}function s(e,t){return e.cache[t]?!0:!!e.resolve(t)}function o(e,t,r){if(r=r||{},e.cache[t]&&r.singleton!==!1)return e.cache[t];var n=d(e,t);return void 0!==n?(l(e,t)&&r.singleton!==!1&&(e.cache[t]=n),n):void 0}function u(e){throw new Error(e+" is not currently supported on child containers")}function l(e,t){var r=h(e,t,"singleton");return r!==!1}function c(e,t){var r={};if(!t)return r;for(var n,i,a=0,s=t.length;s>a;a++){if(n=t[a],i=o(e,n.fullName),void 0===i)throw new Error("Attempting to inject an unknown injection: `"+n.fullName+"`");r[n.property]=i}return r}function h(e,t,r){var n=e._options[t];if(n&&void 0!==n[r])return n[r];var i=t.split(":")[0];return n=e._typeOptions[i],n?n[r]:void 0}function p(e,t){var r=e.factoryCache;if(r[t])return r[t];var n=e.resolve(t);if(void 0!==n){var i=t.split(":")[0];if(!n||"function"!=typeof n.extend||!w.MODEL_FACTORY_INJECTIONS&&"model"===i)return r[t]=n,n;var a=m(e,t),s=f(e,t);s._toString=e.makeToString(n,t);var o=n.extend(a);return o.reopenClass(s),r[t]=o,o}}function m(e,t){var r=t.split(":"),n=r[0],i=[];return i=i.concat(e.typeInjections[n]||[]),i=i.concat(e.injections[t]||[]),i=c(e,i),i._debugContainerKey=t,i.container=e,i}function f(e,t){var r=t.split(":"),n=r[0],i=[];return i=i.concat(e.factoryTypeInjections[n]||[]),i=i.concat(e.factoryInjections[t]||[]),i=c(e,i),i._debugContainerKey=t,i}function d(e,t){var r=p(e,t);if(h(e,t,"instantiate")===!1)return r;if(r){if("function"!=typeof r.create)throw new Error("Failed to create an instance of '"+t+"'. Most likely an improperly defined class or an invalid module export.");return"function"==typeof r.extend?r.create():r.create(m(e,t))}}function v(e,t){for(var r,n,i=e.cache,a=x(i),s=0,o=a.length;o>s;s++)r=a[s],n=i[r],h(e,r,"instantiate")!==!1&&t(n)}function b(e){v(e,function(e){e.destroy()}),e.cache.dict=C(null)}function y(e,t,r,n){var i=e[t];i||(i=[],e[t]=i),i.push({property:r,fullName:n})}function g(e){if(!O.test(e))throw new TypeError("Invalid Fullname, expected: `type:name` got: "+e);return!0}function _(e,t,r,n){var i=e[t]=e[t]||[];i.push({property:r,fullName:n})}var w=e["default"],x=t["default"],C=r["default"];i.prototype={parent:null,children:null,resolver:null,registry:null,cache:null,typeInjections:null,injections:null,_options:null,_typeOptions:null,child:function(){var e=new i(this);return this.children.push(e),e},set:function(e,t,r){e[t]=r},register:function(e,t,r){if(void 0===t)throw new TypeError("Attempting to register an unknown factory: `"+e+"`");var n=this.normalize(e);if(n in this.cache)throw new Error("Cannot re-register: `"+e+"`, as it has already been looked up.");this.registry[n]=t,this._options[n]=r||{}},unregister:function(e){var t=this.normalize(e);delete this.registry[t],delete this.cache[t],delete this.factoryCache[t],delete this.resolveCache[t],delete this._options[t]},resolve:function(e){return a(this,this.normalize(e))},describe:function(e){return e},normalizeFullName:function(e){return e},normalize:function(e){return this.normalizeCache[e]||(this.normalizeCache[e]=this.normalizeFullName(e))},makeToString:function(e){return e.toString()},lookup:function(e,t){return o(this,this.normalize(e),t)},lookupFactory:function(e){return p(this,this.normalize(e))},has:function(e){return s(this,this.normalize(e))},optionsForType:function(e,t){this.parent&&u("optionsForType"),this._typeOptions[e]=t},options:function(e,t){this.optionsForType(e,t)},typeInjection:function(e,t,r){this.parent&&u("typeInjection");var n=r.split(":")[0];if(n===e)throw new Error("Cannot inject a `"+r+"` on other "+e+"(s). Register the `"+r+"` as a different type and perform the typeInjection.");y(this.typeInjections,e,t,r)},injection:function(e,t,r){this.parent&&u("injection"),g(r);var n=this.normalize(r);if(-1===e.indexOf(":"))return this.typeInjection(e,t,n);var i=this.normalize(e);if(this.cache[i])throw new Error("Attempted to register an injection for a type that has already been looked up. ('"+i+"', '"+t+"', '"+r+"')");_(this.injections,i,t,n)},factoryTypeInjection:function(e,t,r){this.parent&&u("factoryTypeInjection"),y(this.factoryTypeInjections,e,t,this.normalize(r))},factoryInjection:function(e,t,r){this.parent&&u("injection");var n=this.normalize(e),i=this.normalize(r);if(g(r),-1===e.indexOf(":"))return this.factoryTypeInjection(n,t,i);if(this.factoryCache[n])throw new Error("Attempted to register a factoryInjection for a type that has already been looked up. ('"+n+"', '"+t+"', '"+r+"')");_(this.factoryInjections,n,t,i)},destroy:function(){for(var e=0,t=this.children.length;t>e;e++)this.children[e].destroy();this.children=[],v(this,function(e){e.destroy()}),this.parent=void 0,this.isDestroyed=!0},reset:function(){for(var e=0,t=this.children.length;t>e;e++)b(this.children[e]);b(this)}};var O=/^[^:]+.+:[^:]+$/;n["default"]=i}),e("ember-application",["ember-metal/core","ember-runtime/system/lazy_load","ember-application/system/dag","ember-application/system/resolver","ember-application/system/application","ember-application/ext/controller"],function(e,t,r,n,i){"use strict";var a=e["default"],s=t.runLoadHooks,o=r["default"],u=n.Resolver,l=n["default"],c=i["default"];a.Application=c,a.DAG=o,a.Resolver=u,a.DefaultResolver=l,s("Ember.Application",c)}),e("ember-application/ext/controller",["ember-metal/core","ember-metal/property_get","ember-metal/property_set","ember-metal/error","ember-metal/utils","ember-metal/computed","ember-runtime/mixins/controller","ember-routing/system/controller_for","exports"],function(e,t,r,n,i,a,s,o,u){"use strict";function l(e,t,r){var n,i,a,s=[];for(i=0,a=r.length;a>i;i++)n=r[i],-1===n.indexOf(":")&&(n="controller:"+n),t.has(n)||s.push(n);if(s.length)throw new h(p(e)+" needs [ "+s.join(", ")+" ] but "+(s.length>1?"they":"it")+" could not be found")}var c=(e["default"],t.get),h=(r.set,n["default"]),p=i.inspect,m=a.computed,f=s["default"],d=(i.meta,o["default"]),v=m(function(){var e=this;return{needs:c(e,"needs"),container:c(e,"container"),unknownProperty:function(t){var r,n,i,a=this.needs;for(n=0,i=a.length;i>n;n++)if(r=a[n],r===t)return this.container.lookup("controller:"+t);var s=p(e)+"#needs does not include `"+t+"`. To access the "+t+" controller from "+p(e)+", "+p(e)+" should have a `needs` property that is an array of the controllers it has access to.";throw new ReferenceError(s)},setUnknownProperty:function(t){throw new Error("You cannot overwrite the value of `controllers."+t+"` of "+p(e))}}});f.reopen({concatenatedProperties:["needs"],needs:[],init:function(){var e=c(this,"needs"),t=c(e,"length");t>0&&(this.container&&l(this,this.container,e),c(this,"controllers")),this._super.apply(this,arguments)},controllerFor:function(e){return d(c(this,"container"),e)},controllers:v}),u["default"]=f}),e("ember-application/system/application",["ember-metal","ember-metal/property_get","ember-metal/property_set","ember-runtime/system/lazy_load","ember-application/system/dag","ember-runtime/system/namespace","ember-runtime/mixins/deferred","ember-application/system/resolver","ember-metal/platform","ember-metal/run_loop","ember-metal/utils","container/container","ember-runtime/controllers/controller","ember-metal/enumerable_utils","ember-runtime/controllers/object_controller","ember-runtime/controllers/array_controller","ember-handlebars/controls/select","ember-views/system/event_dispatcher","ember-views/system/jquery","ember-routing/system/route","ember-routing/system/router","ember-routing/location/hash_location","ember-routing/location/history_location","ember-routing/location/auto_location","ember-routing/location/none_location","ember-routing/system/cache","ember-metal/core","ember-handlebars-compiler","exports"],function(e,r,n,i,a,s,o,u,l,c,h,p,m,f,d,v,b,y,g,_,w,x,C,O,E,P,A,T,N){"use strict";function S(e){var t=[];for(var r in e)t.push(r);return t}function V(e){function t(e){return n.resolve(e)}e.get("resolver");var r=e.get("resolver")||e.get("Resolver")||z,n=r.create({namespace:e});return t.describe=function(e){return n.lookupDescription(e)},t.makeToString=function(e,t){return n.makeToString(e,t)},t.normalize=function(e){return n.normalize?n.normalize(e):e},t.__resolver__=n,t}var I,k=e["default"],D=r.get,j=n.set,M=i.runLoadHooks,R=a["default"],L=s["default"],H=o["default"],z=u["default"],q=l.create,F=c["default"],B=(h.canInvoke,p["default"]),U=m["default"],K=f["default"],W=d["default"],G=v["default"],Q=b["default"],$=y["default"],Y=g["default"],J=_["default"],Z=w["default"],X=x["default"],et=C["default"],tt=O["default"],rt=E["default"],nt=P["default"],it=A.K,at=T["default"],st=L.extend(H,{_suppressDeferredDeprecation:!0,rootElement:"body",eventDispatcher:null,customEvents:null,_readinessDeferrals:1,init:function(){if(this.$||(this.$=Y),this.__container__=this.buildContainer(),this.Router=this.defaultRouter(),this._super(),this.scheduleInitialize(),k.libraries.registerCoreLibrary("Handlebars"+(at.compile?"":"-runtime"),at.VERSION),k.libraries.registerCoreLibrary("jQuery",Y().jquery),k.LOG_VERSION){k.LOG_VERSION=!1;var e=K.map(k.libraries,function(e){return D(e,"name.length")}),t=Math.max.apply(this,e);k.libraries.each(function(e){new Array(t-e.length+1).join(" ")})}},buildContainer:function(){var e=this.__container__=st.buildContainer(this);return e},defaultRouter:function(){if(this.Router!==!1){var e=this.__container__;return this.Router&&(e.unregister("router:main"),e.register("router:main",this.Router)),e.lookupFactory("router:main")}},scheduleInitialize:function(){var e=this;!this.$||this.$.isReady?F.schedule("actions",e,"_initialize"):this.$().ready(function(){F(e,"_initialize")})},deferReadiness:function(){this._readinessDeferrals++},advanceReadiness:function(){this._readinessDeferrals--,0===this._readinessDeferrals&&F.once(this,this.didBecomeReady)},register:function(){var e=this.__container__;e.register.apply(e,arguments)},inject:function(){var e=this.__container__;e.injection.apply(e,arguments)},initialize:function(){},_initialize:function(){if(!this.isDestroyed){if(this.Router){var e=this.__container__;e.unregister("router:main"),e.register("router:main",this.Router)}return this.runInitializers(),M("application",this),this.advanceReadiness(),this}},reset:function(){function e(){var e=this.__container__.lookup("router:main");e.reset(),F(this.__container__,"destroy"),this.buildContainer(),F.schedule("actions",this,function(){this._initialize()})}this._readinessDeferrals=1,F.join(this,e)},runInitializers:function(){for(var e,t=D(this.constructor,"initializers"),r=S(t),n=this.__container__,i=new R,a=this,s=0;sa;a++)r(o[u[a]],t,n,i);t(e,i),i.pop()}}function n(){this.names=[],this.vertices=Object.create(null)}function i(e){this.name=e,this.incoming={},this.incomingNames=[],this.hasOutgoing=!1,this.value=null}var a=e["default"];n.prototype.add=function(e){if(!e)throw new Error("Can't add Vertex without name");if(void 0!==this.vertices[e])return this.vertices[e];var t=new i(e);return this.vertices[e]=t,this.names.push(e),t},n.prototype.map=function(e,t){this.add(e).value=t},n.prototype.addEdge=function(e,t){function n(e,r){if(e.name===t)throw new a("cycle detected: "+t+" <- "+r.join(" <- "))}if(e&&t&&e!==t){var i=this.add(e),s=this.add(t);s.incoming.hasOwnProperty(e)||(r(i,n),i.hasOutgoing=!0,s.incoming[e]=i,s.incomingNames.push(e))}},n.prototype.topsort=function(e){var t,n,i={},a=this.vertices,s=this.names,o=s.length;for(t=0;o>t;t++)n=a[s[t]],n.hasOutgoing||r(n,e,i)},n.prototype.addEdges=function(e,t,r,n){var i;if(this.map(e,t),r)if("string"==typeof r)this.addEdge(e,r);else for(i=0;i-1&&(i=i.replace(/\.(.)/g,function(e){return e.charAt(1).toUpperCase()})),n.indexOf("_")>-1&&(i=i.replace(/_(.)/g,function(e){return e.charAt(1).toUpperCase()})),r+":"+i}return e},resolve:function(e){var t,r=this.parseName(e),n=r.resolveMethodName;if(!r.name||!r.type)throw new TypeError("Invalid fullName: `"+e+"`, must be of the form `type:name` ");return this[n]&&(t=this[n](r)),t||(t=this.resolveOther(r)),r.root&&r.root.LOG_RESOLVER&&this._logLookup(t,r),t},parseName:function(e){return this._parseNameCache[e]||(this._parseNameCache[e]=this._parseName(e))},_parseName:function(e){var t=e.split(":"),r=t[0],n=t[1],i=n,a=c(this,"namespace"),s=a;if("template"!==r&&-1!==i.indexOf("/")){var o=i.split("/");i=o[o.length-1];var u=m(o.slice(0,-1).join("."));s=v.byName(u)}return{fullName:e,type:r,fullNameWithoutType:n,name:i,root:s,resolveMethodName:"resolve"+p(r)}},lookupDescription:function(e){var t=this.parseName(e);if("template"===t.type)return"template at "+t.fullNameWithoutType.replace(/\./g,"/");var r=t.root+"."+p(t.name);return"model"!==t.type&&(r+=p(t.type)),r},makeToString:function(e){return e.toString()},useRouterNaming:function(e){e.name=e.name.replace(/\./g,"_"),"basic"===e.name&&(e.name="")},resolveTemplate:function(e){var t=e.fullNameWithoutType.replace(/\./g,"/");return l.TEMPLATES[t]?l.TEMPLATES[t]:(t=f(t),l.TEMPLATES[t]?l.TEMPLATES[t]:void 0)},resolveView:function(e){return this.useRouterNaming(e),this.resolveOther(e)},resolveController:function(e){return this.useRouterNaming(e),this.resolveOther(e)},resolveRoute:function(e){return this.useRouterNaming(e),this.resolveOther(e)},resolveModel:function(e){var t=p(e.name),r=c(e.root,t);return r?r:void 0},resolveHelper:function(e){return this.resolveOther(e)||b.helpers[e.fullNameWithoutType]},resolveOther:function(e){var t=p(e.name)+p(e.type),r=c(e.root,t);return r?r:void 0},_logLookup:function(e,t){var r,n;r=e?"[✓]":"[ ]",n=t.fullName.length>60?".":new Array(60-t.fullName.length).join("."),h.info(r,t.fullName,n,this.lookupDescription(t.fullName))}})}),e("ember-extension-support",["ember-metal/core","ember-extension-support/data_adapter","ember-extension-support/container_debug_adapter"],function(e,t,r){"use strict";var n=e["default"],i=t["default"],a=r["default"];n.DataAdapter=i,n.ContainerDebugAdapter=a}),e("ember-extension-support/container_debug_adapter",["ember-metal/core","ember-runtime/system/native_array","ember-metal/utils","ember-runtime/system/string","ember-runtime/system/namespace","ember-runtime/system/object","exports"],function(e,t,r,n,i,a,s){"use strict";var o=e["default"],u=t.A,l=r.typeOf,c=n.dasherize,h=n.classify,p=i["default"],m=a["default"];s["default"]=m.extend({container:null,resolver:null,canCatalogEntriesByType:function(e){return"model"===e||"template"===e?!1:!0},catalogEntriesByType:function(e){var t=u(p.NAMESPACES),r=u(),n=new RegExp(h(e)+"$");return t.forEach(function(e){if(e!==o)for(var t in e)if(e.hasOwnProperty(t)&&n.test(t)){var i=e[t];"class"===l(i)&&r.push(c(t.replace(n,"")))}}),r}})}),e("ember-extension-support/data_adapter",["ember-metal/core","ember-metal/property_get","ember-metal/run_loop","ember-runtime/system/string","ember-runtime/system/namespace","ember-runtime/system/object","ember-runtime/system/native_array","ember-application/system/application","exports"],function(e,t,r,n,i,a,s,o,u){"use strict";var l=e["default"],c=t.get,h=r["default"],p=n.dasherize,m=i["default"],f=a["default"],d=s.A,v=o["default"];u["default"]=f.extend({init:function(){this._super(),this.releaseMethods=d()},container:null,containerDebugAdapter:void 0,attributeLimit:3,releaseMethods:d(),getFilters:function(){return d()},watchModelTypes:function(e,t){var r,n=this.getModelTypes(),i=this,a=d();r=n.map(function(e){var r=e.klass,n=i.wrapModelType(r,e.name);return a.push(i.observeModelType(r,t)),n}),e(r);var s=function(){a.forEach(function(e){e()}),i.releaseMethods.removeObject(s)};return this.releaseMethods.pushObject(s),s},_nameToClass:function(e){return"string"==typeof e&&(e=this.container.lookupFactory("model:"+e)),e},watchRecords:function(e,t,r,n){var i,a=this,s=d(),o=this.getRecords(e),u=function(e){r([e])},c=o.map(function(e){return s.push(a.observeRecord(e,u)),a.wrapRecord(e)}),h=function(e,r,i,o){for(var l=r;r+o>l;l++){var c=e.objectAt(l),h=a.wrapRecord(c);s.push(a.observeRecord(c,u)),t([h])}i&&n(r,i)},p={didChange:h,willChange:l.K};return o.addArrayObserver(a,p),i=function(){s.forEach(function(e){e()}),o.removeArrayObserver(a,p),a.releaseMethods.removeObject(i) -},t(c),this.releaseMethods.pushObject(i),i},willDestroy:function(){this._super(),this.releaseMethods.forEach(function(e){e()})},detect:function(){return!1},columnsForType:function(){return d()},observeModelType:function(e,t){var r=this,n=this.getRecords(e),i=function(){t([r.wrapModelType(e)])},a={didChange:function(){h.scheduleOnce("actions",this,i)},willChange:l.K};n.addArrayObserver(this,a);var s=function(){n.removeArrayObserver(r,a)};return s},wrapModelType:function(e,t){var r,n=this.getRecords(e);return r={name:t||e.toString(),count:c(n,"length"),columns:this.columnsForType(e),object:e}},getModelTypes:function(){var e,t=this,r=this.get("containerDebugAdapter");return e=r.canCatalogEntriesByType("model")?r.catalogEntriesByType("model"):this._getObjectsOnNamespaces(),e=d(e).map(function(e){return{klass:t._nameToClass(e),name:e}}),e=d(e).filter(function(e){return t.detect(e.klass)}),d(e)},_getObjectsOnNamespaces:function(){var e=d(m.NAMESPACES),t=d(),r=this;return e.forEach(function(e){for(var n in e)if(e.hasOwnProperty(n)&&r.detect(e[n])){var i=p(n);e instanceof v||!e.toString()||(i=e+"/"+i),t.push(i)}}),t},getRecords:function(){return d()},wrapRecord:function(e){var t={object:e};return t.columnValues=this.getRecordColumnValues(e),t.searchKeywords=this.getRecordKeywords(e),t.filterValues=this.getRecordFilterValues(e),t.color=this.getRecordColor(e),t},getRecordColumnValues:function(){return{}},getRecordKeywords:function(){return d()},getRecordFilterValues:function(){return{}},getRecordColor:function(){return null},observeRecord:function(){return function(){}}})}),e("ember-extension-support/initializers",[],function(){"use strict"}),e("ember-handlebars-compiler",["ember-metal/core","exports"],function(e,n){var i=e["default"];"undefined"==typeof i.assert&&(i.assert=function(){}),"undefined"==typeof i.FEATURES&&(i.FEATURES={isEnabled:function(){}});var a,s,o=Object.create||function(e){function t(){}return t.prototype=e,new t},u=i.imports&&i.imports.Handlebars||this&&this.Handlebars;u||"function"!=typeof r||(u=r("handlebars"));var l=i.Handlebars=o(u);l.helper=function(e,r){a||(a=t("ember-views/views/view")["default"]),s||(s=t("ember-views/views/component")["default"]),a.detect(r)?l.registerHelper(e,l.makeViewHelper(r)):l.registerBoundHelper.apply(null,arguments)},l.makeViewHelper=function(e){return function(t){return l.helpers.view.call(this,e,t)}},l.helpers=o(u.helpers),l.Compiler=function(){},u.Compiler&&(l.Compiler.prototype=o(u.Compiler.prototype)),l.Compiler.prototype.compiler=l.Compiler,l.JavaScriptCompiler=function(){},u.JavaScriptCompiler&&(l.JavaScriptCompiler.prototype=o(u.JavaScriptCompiler.prototype),l.JavaScriptCompiler.prototype.compiler=l.JavaScriptCompiler),l.JavaScriptCompiler.prototype.namespace="Ember.Handlebars",l.JavaScriptCompiler.prototype.initializeBuffer=function(){return"''"},l.JavaScriptCompiler.prototype.appendToBuffer=function(e){return"data.buffer.push("+e+");"};var c=/helpers\.(.*?)\)/,h=/helpers\['(.*?)'/,p=/(.*blockHelperMissing\.call\(.*)(stack[0-9]+)(,.*)/;l.JavaScriptCompiler.stringifyLastBlockHelperMissingInvocation=function(e){var t=e[e.length-1],r=(c.exec(t)||h.exec(t))[1],n=p.exec(t);e[e.length-1]=n[1]+"'"+r+"'"+n[3]};var m=l.JavaScriptCompiler.stringifyLastBlockHelperMissingInvocation,f=l.JavaScriptCompiler.prototype.blockValue;l.JavaScriptCompiler.prototype.blockValue=function(){f.apply(this,arguments),m(this.source)};var d=l.JavaScriptCompiler.prototype.ambiguousBlockValue;l.JavaScriptCompiler.prototype.ambiguousBlockValue=function(){d.apply(this,arguments),m(this.source)},l.Compiler.prototype.mustache=function(e){if(!e.params.length&&!e.hash){var t=new u.AST.IdNode([{part:"_triageMustache"}]);e.escaped||(e.hash=e.hash||new u.AST.HashNode([]),e.hash.pairs.push(["unescaped",new u.AST.StringNode("true")])),e=new u.AST.MustacheNode([t].concat([e.id]),e.hash,!e.escaped)}return u.Compiler.prototype.mustache.call(this,e)},l.precompile=function(e,t){var r=u.parse(e),n={knownHelpers:{action:!0,unbound:!0,"bind-attr":!0,template:!0,view:!0,_triageMustache:!0},data:!0,stringParams:!0};t=void 0===t?!0:t;var i=(new l.Compiler).compile(r,n);return(new l.JavaScriptCompiler).compile(i,n,void 0,t)},u.compile&&(l.compile=function(e){var t=u.parse(e),r={data:!0,stringParams:!0},n=(new l.Compiler).compile(t,r),i=(new l.JavaScriptCompiler).compile(n,r,void 0,!0),a=l.template(i);return a.isMethod=!1,a}),n["default"]=l}),e("ember-handlebars",["ember-handlebars-compiler","ember-metal/core","ember-runtime/system/lazy_load","ember-handlebars/loader","ember-handlebars/ext","ember-handlebars/string","ember-handlebars/helpers/shared","ember-handlebars/helpers/binding","ember-handlebars/helpers/collection","ember-handlebars/helpers/view","ember-handlebars/helpers/unbound","ember-handlebars/helpers/debug","ember-handlebars/helpers/each","ember-handlebars/helpers/template","ember-handlebars/helpers/partial","ember-handlebars/helpers/yield","ember-handlebars/helpers/loc","ember-handlebars/controls/checkbox","ember-handlebars/controls/select","ember-handlebars/controls/text_area","ember-handlebars/controls/text_field","ember-handlebars/controls/text_support","ember-handlebars/controls","ember-handlebars/component_lookup","ember-handlebars/views/handlebars_bound_view","ember-handlebars/views/metamorph_view","exports"],function(e,t,r,n,i,a,s,o,u,l,c,h,p,m,f,d,v,b,y,g,_,w,x,C,O,E,P){"use strict";var A=e["default"],T=t["default"],N=r.runLoadHooks,S=n["default"],V=i.normalizePath,I=i.template,k=i.makeBoundHelper,D=i.registerBoundHelper,j=i.resolveHash,M=i.resolveParams,R=i.getEscaped,L=i.handlebarsGet,H=i.evaluateUnboundHelper,z=i.helperMissingHelper,q=i.blockHelperMissingHelper,F=s["default"],B=o.bind,U=o._triageMustacheHelper,K=o.resolveHelper,W=o.bindHelper,G=o.boundIfHelper,Q=o.unboundIfHelper,$=o.withHelper,Y=o.ifHelper,J=o.unlessHelper,Z=o.bindAttrHelper,X=o.bindAttrHelperDeprecated,et=o.bindClasses,tt=u["default"],rt=l.ViewHelper,nt=l.viewHelper,it=c["default"],at=h.logHelper,st=h.debuggerHelper,ot=p.EachView,ut=p.GroupedEach,lt=p.eachHelper,ct=m["default"],ht=f["default"],pt=d["default"],mt=v["default"],ft=b["default"],dt=y.Select,vt=y.SelectOption,bt=y.SelectOptgroup,yt=g["default"],gt=_["default"],_t=w["default"],wt=x.inputHelper,xt=x.textareaHelper,Ct=C["default"],Ot=O._HandlebarsBoundView,Et=O.SimpleHandlebarsView,Pt=E._wrapMap,At=E._SimpleMetamorphView,Tt=E._MetamorphView,Nt=E._Metamorph;A.bootstrap=S,A.template=I,A.makeBoundHelper=k,A.registerBoundHelper=D,A.resolveHash=j,A.resolveParams=M,A.resolveHelper=K,A.get=L,A.getEscaped=R,A.evaluateUnboundHelper=H,A.bind=B,A.bindClasses=et,A.EachView=ot,A.GroupedEach=ut,A.resolvePaths=F,A.ViewHelper=rt,A.normalizePath=V,T.Handlebars=A,T.ComponentLookup=Ct,T._SimpleHandlebarsView=Et,T._HandlebarsBoundView=Ot,T._SimpleMetamorphView=At,T._MetamorphView=Tt,T._Metamorph=Nt,T._metamorphWrapMap=Pt,T.TextSupport=_t,T.Checkbox=ft,T.Select=dt,T.SelectOption=vt,T.SelectOptgroup=bt,T.TextArea=yt,T.TextField=gt,T.TextSupport=_t,A.registerHelper("helperMissing",z),A.registerHelper("blockHelperMissing",q),A.registerHelper("bind",W),A.registerHelper("boundIf",G),A.registerHelper("_triageMustache",U),A.registerHelper("unboundIf",Q),A.registerHelper("with",$),A.registerHelper("if",Y),A.registerHelper("unless",J),A.registerHelper("bind-attr",Z),A.registerHelper("bindAttr",X),A.registerHelper("collection",tt),A.registerHelper("log",at),A.registerHelper("debugger",st),A.registerHelper("each",lt),A.registerHelper("loc",mt),A.registerHelper("partial",ht),A.registerHelper("template",ct),A.registerHelper("yield",pt),A.registerHelper("view",nt),A.registerHelper("unbound",it),A.registerHelper("input",wt),A.registerHelper("textarea",xt),N("Ember.Handlebars",A),P["default"]=A}),e("ember-handlebars/component_lookup",["ember-runtime/system/object","exports"],function(e,t){"use strict";var r=e["default"],n=r.extend({lookupFactory:function(e,t){t=t||this.container;var r="component:"+e,n="template:components/"+e,a=t&&t.has(n);a&&t.injection(r,"layout",n);var s=t.lookupFactory(r);return a||s?(s||(t.register(r,i.Component),s=t.lookupFactory(r)),s):void 0}});t["default"]=n}),e("ember-handlebars/controls",["ember-handlebars/controls/checkbox","ember-handlebars/controls/text_field","ember-handlebars/controls/text_area","ember-metal/core","ember-handlebars-compiler","ember-handlebars/ext","exports"],function(e,t,r,n,i,a,s){"use strict";function o(e,t,r){return"ID"===t.hashTypes[r]?f(e,t.hash[r],t):t.hash[r]}function u(e){var t=e.hash,r=e.hashTypes,n=o(this,e,"type"),i=t.on;return"checkbox"===n?(delete t.type,delete r.type,d.view.call(this,c,e)):(delete t.on,t.onEvent=i||"enter",d.view.call(this,h,e))}function l(e){e.hash,e.hashTypes;return d.view.call(this,p,e)}var c=e["default"],h=t["default"],p=r["default"],m=(n["default"],i["default"]),f=a.handlebarsGet,d=m.helpers;s.inputHelper=u,s.textareaHelper=l}),e("ember-handlebars/controls/checkbox",["ember-metal/property_get","ember-metal/property_set","ember-views/views/view","exports"],function(e,t,r,n){"use strict";var i=e.get,a=t.set,s=r["default"];n["default"]=s.extend({instrumentDisplay:'{{input type="checkbox"}}',classNames:["ember-checkbox"],tagName:"input",attributeBindings:["type","checked","indeterminate","disabled","tabindex","name","autofocus","required","form"],type:"checkbox",checked:!1,disabled:!1,indeterminate:!1,init:function(){this._super(),this.on("change",this,this._updateElementValue)},didInsertElement:function(){this._super(),i(this,"element").indeterminate=!!i(this,"indeterminate")},_updateElementValue:function(){a(this,"checked",this.$().prop("checked"))}})}),e("ember-handlebars/controls/select",["ember-handlebars-compiler","ember-metal/enumerable_utils","ember-metal/property_get","ember-metal/property_set","ember-views/views/view","ember-views/views/collection_view","ember-metal/utils","ember-metal/is_none","ember-metal/computed","ember-runtime/system/native_array","ember-metal/mixin","ember-metal/properties","exports"],function(e,t,r,n,a,s,o,u,l,c,h,p,m){"use strict";var f=e["default"],d=t.forEach,v=t.indexOf,b=t.indexesOf,y=t.replace,g=r.get,_=n.set,w=a["default"],x=s["default"],C=o.isArray,O=u["default"],E=l.computed,P=c.A,A=h.observer,T=p.defineProperty,N=(f.compile,w.extend({instrumentDisplay:"Ember.SelectOption",tagName:"option",attributeBindings:["value","selected"],defaultTemplate:function(e,t){t={data:t.data,hash:{}},f.helpers.bind.call(e,"view.label",t)},init:function(){this.labelPathDidChange(),this.valuePathDidChange(),this._super()},selected:E(function(){var e=g(this,"content"),t=g(this,"parentView.selection");return g(this,"parentView.multiple")?t&&v(t,e.valueOf())>-1:e==t}).property("content","parentView.selection"),labelPathDidChange:A("parentView.optionLabelPath",function(){var e=g(this,"parentView.optionLabelPath");e&&T(this,"label",E(function(){return g(this,e)}).property(e))}),valuePathDidChange:A("parentView.optionValuePath",function(){var e=g(this,"parentView.optionValuePath");e&&T(this,"value",E(function(){return g(this,e)}).property(e))})})),S=x.extend({instrumentDisplay:"Ember.SelectOptgroup",tagName:"optgroup",attributeBindings:["label"],selectionBinding:"parentView.selection",multipleBinding:"parentView.multiple",optionLabelPathBinding:"parentView.optionLabelPath",optionValuePathBinding:"parentView.optionValuePath",itemViewClassBinding:"parentView.optionView"}),V=w.extend({instrumentDisplay:"Ember.Select",tagName:"select",classNames:["ember-select"],defaultTemplate:i.Handlebars.template(function(e,t,r,n,a){function s(e,t){var n,i="";return t.buffer.push('"),i}function o(e,t){var n;n=r.each.call(e,"view.groupedContent",{hash:{},hashTypes:{},hashContexts:{},inverse:f.noop,fn:f.program(4,u,t),contexts:[e],types:["ID"],data:t}),t.buffer.push(n||0===n?n:"")}function u(e,t){t.buffer.push(m(r.view.call(e,"view.groupView",{hash:{content:"content",label:"label"},hashTypes:{content:"ID",label:"ID"},hashContexts:{content:e,label:e},contexts:[e],types:["ID"],data:t})))}function l(e,t){var n;n=r.each.call(e,"view.content",{hash:{},hashTypes:{},hashContexts:{},inverse:f.noop,fn:f.program(7,c,t),contexts:[e],types:["ID"],data:t}),t.buffer.push(n||0===n?n:"")}function c(e,t){t.buffer.push(m(r.view.call(e,"view.optionView",{hash:{content:""},hashTypes:{content:"ID"},hashContexts:{content:e},contexts:[e],types:["ID"],data:t})))}this.compilerInfo=[4,">= 1.0.0"],r=this.merge(r,i.Handlebars.helpers),a=a||{};var h,p="",m=this.escapeExpression,f=this;return h=r["if"].call(t,"view.prompt",{hash:{},hashTypes:{},hashContexts:{},inverse:f.noop,fn:f.program(1,s,a),contexts:[t],types:["ID"],data:a}),(h||0===h)&&a.buffer.push(h),h=r["if"].call(t,"view.optionGroupPath",{hash:{},hashTypes:{},hashContexts:{},inverse:f.program(6,l,a),fn:f.program(3,o,a),contexts:[t],types:["ID"],data:a}),(h||0===h)&&a.buffer.push(h),p}),attributeBindings:["multiple","disabled","tabindex","name","required","autofocus","form","size"],multiple:!1,disabled:!1,required:!1,content:null,selection:null,value:E(function(e,t){if(2===arguments.length)return t;var r=g(this,"optionValuePath").replace(/^content\.?/,"");return r?g(this,"selection."+r):g(this,"selection")}).property("selection"),prompt:null,optionLabelPath:"content",optionValuePath:"content",optionGroupPath:null,groupView:S,groupedContent:E(function(){var e=g(this,"optionGroupPath"),t=P(),r=g(this,"content")||[];return d(r,function(r){var n=g(r,e);g(t,"lastObject.label")!==n&&t.pushObject({label:n,content:P()}),g(t,"lastObject.content").push(r)}),t}).property("optionGroupPath","content.@each"),optionView:N,_change:function(){g(this,"multiple")?this._changeMultiple():this._changeSingle()},selectionDidChange:A("selection.@each",function(){var e=g(this,"selection");if(g(this,"multiple")){if(!C(e))return void _(this,"selection",P([e]));this._selectionDidChangeMultiple()}else this._selectionDidChangeSingle()}),valueDidChange:A("value",function(){var e,t=g(this,"content"),r=g(this,"value"),n=g(this,"optionValuePath").replace(/^content\.?/,""),i=n?g(this,"selection."+n):g(this,"selection");r!==i&&(e=t?t.find(function(e){return r===(n?g(e,n):e)}):null,this.set("selection",e))}),_triggerChange:function(){var e=g(this,"selection"),t=g(this,"value");O(e)||this.selectionDidChange(),O(t)||this.valueDidChange(),this._change()},_changeSingle:function(){var e=this.$()[0].selectedIndex,t=g(this,"content"),r=g(this,"prompt");if(t&&g(t,"length")){if(r&&0===e)return void _(this,"selection",null);r&&(e-=1),_(this,"selection",t.objectAt(e))}},_changeMultiple:function(){var e=this.$("option:selected"),t=g(this,"prompt"),r=t?1:0,n=g(this,"content"),i=g(this,"selection");if(n&&e){var a=e.map(function(){return this.index-r}).toArray(),s=n.objectsAt(a);C(i)?y(i,0,g(i,"length"),s):_(this,"selection",s)}},_selectionDidChangeSingle:function(){var e=this.get("element");if(e){var t=g(this,"content"),r=g(this,"selection"),n=t?v(t,r):-1,i=g(this,"prompt");i&&(n+=1),e&&(e.selectedIndex=n)}},_selectionDidChangeMultiple:function(){var e,t=g(this,"content"),r=g(this,"selection"),n=t?b(t,r):[-1],i=g(this,"prompt"),a=i?1:0,s=this.$("option");s&&s.each(function(){e=this.index>-1?this.index-a:-1,this.selected=v(n,e)>-1})},init:function(){this._super(),this.on("didInsertElement",this,this._triggerChange),this.on("change",this,this._change)}});m["default"]=V,m.Select=V,m.SelectOption=N,m.SelectOptgroup=S}),e("ember-handlebars/controls/text_area",["ember-metal/property_get","ember-views/views/component","ember-handlebars/controls/text_support","ember-metal/mixin","exports"],function(e,t,r,n,i){"use strict";var a=e.get,s=t["default"],o=r["default"],u=n.observer;i["default"]=s.extend(o,{instrumentDisplay:"{{textarea}}",classNames:["ember-text-area"],tagName:"textarea",attributeBindings:["rows","cols","name","selectionEnd","selectionStart","wrap","lang","dir"],rows:null,cols:null,_updateElementValue:u("value",function(){var e=a(this,"value"),t=this.$();t&&e!==t.val()&&t.val(e)}),init:function(){this._super(),this.on("didInsertElement",this,this._updateElementValue)}})}),e("ember-handlebars/controls/text_field",["ember-metal/property_get","ember-metal/property_set","ember-views/views/component","ember-handlebars/controls/text_support","exports"],function(e,t,r,n,i){"use strict";var a=(e.get,t.set,r["default"]),s=n["default"];i["default"]=a.extend(s,{instrumentDisplay:'{{input type="text"}}',classNames:["ember-text-field"],tagName:"input",attributeBindings:["type","value","size","pattern","name","min","max","accept","autocomplete","autosave","formaction","formenctype","formmethod","formnovalidate","formtarget","height","inputmode","list","multiple","step","lang","dir","width"],value:"",type:"text",size:null,pattern:null,min:null,max:null})}),e("ember-handlebars/controls/text_support",["ember-metal/property_get","ember-metal/property_set","ember-metal/mixin","ember-runtime/mixins/target_action_support","exports"],function(e,t,r,n,i){"use strict";function a(e,t,r){var n=s(t,e),i=s(t,"onEvent"),a=s(t,"value");(i===e||"keyPress"===i&&"key-press"===e)&&t.sendAction("action",a),t.sendAction(e,a),(n||i===e)&&(s(t,"bubbles")||r.stopPropagation())}var s=e.get,o=t.set,u=r.Mixin,l=n["default"],c=u.create(l,{value:"",attributeBindings:["placeholder","disabled","maxlength","tabindex","readonly","autofocus","form","selectionDirection","spellcheck","required","title","autocapitalize","autocorrect"],placeholder:null,disabled:!1,maxlength:null,init:function(){this._super(),this.on("focusOut",this,this._elementValueDidChange),this.on("change",this,this._elementValueDidChange),this.on("paste",this,this._elementValueDidChange),this.on("cut",this,this._elementValueDidChange),this.on("input",this,this._elementValueDidChange),this.on("keyUp",this,this.interpretKeyEvents)},action:null,onEvent:"enter",bubbles:!1,interpretKeyEvents:function(e){var t=c.KEY_EVENTS,r=t[e.keyCode];return this._elementValueDidChange(),r?this[r](e):void 0},_elementValueDidChange:function(){o(this,"value",this.$().val())},insertNewline:function(e){a("enter",this,e),a("insert-newline",this,e)},cancel:function(e){a("escape-press",this,e)},focusIn:function(e){a("focus-in",this,e)},focusOut:function(e){a("focus-out",this,e)},keyPress:function(e){a("key-press",this,e)}});c.KEY_EVENTS={13:"insertNewline",27:"cancel"},i["default"]=c}),e("ember-handlebars/ext",["ember-metal/core","ember-runtime/system/string","ember-handlebars-compiler","ember-metal/property_get","ember-metal/error","ember-metal/mixin","ember-views/views/view","ember-handlebars/views/metamorph_view","ember-metal/path_cache","ember-metal/is_empty","ember-metal/cache","exports"],function(e,r,n,i,a,s,o,u,l,c,h,p){"use strict";function m(e,t,r){var n,i,a=r&&r.keywords||{};return n=q.get(t),a.hasOwnProperty(n)&&(e=a[n],i=!0,t=t===n?"":t.substr(n.length+1)),{root:e,path:t,isKeyword:i}}function f(e,t,r){var n,i=r&&r.data,a=m(e,t,i);return e=a.root,t=a.path,(e||""===t)&&(n=k(e,t)),M(t)&&(void 0===n&&e!==N.lookup&&(e=N.lookup,n=k(e,t)),e===N.lookup||null===e),n}function d(e,t){return e.lookupFactory("view:"+t)}function v(e){var t;return M(e)?t=k(e):void 0}function b(e,t,r,n){var i,a,s;if(n&&(a=n.data,s=n.types&&n.types[0]),"string"==typeof t){if("STRING"===s&&r&&(i=d(r,t)),i||(i=v(t)),!i){if(a){var o=m(e,t,a);e=o.root,t=o.path}i=e&&k(e,t),i||(i=d(r,t))}}else i=t;return"string"==typeof i&&a&&a.view&&(i=b(a.view,i,r,{data:a,types:["ID"]})),i}function y(e,t,r){var n=f(e,t,r);return null===n||void 0===n?n="":n instanceof Handlebars.SafeString||(n=String(n)),r.hash.unescaped||(n=Handlebars.Utils.escapeExpression(n)),n}function g(e,t,r){for(var n,i,a=[],s=r.types,o=0,u=t.length;u>o;o++)n=t[o],i=s[o],a.push("ID"===i?f(e,n,r):n);return a}function _(e,t,r){var n,i={},a=r.hashTypes;for(var s in t)t.hasOwnProperty(s)&&(n=a[s],i[s]="ID"===n?f(e,t[s],r):t[s]);return i}function w(e){A||(A=t("ember-handlebars/helpers/binding").resolveHelper);var r,n="",i=arguments[arguments.length-1],a=A(i.data.view.container,e);if(a)return a.apply(this,L.call(arguments,1));throw r="%@ Handlebars error: Could not find property '%@' on object %@.",i.data&&(n=i.data.view),new D(S(r,[n,e,this]))}function x(e){A||(A=t("ember-handlebars/helpers/binding").resolveHelper);var r=arguments[arguments.length-1],n=A(r.data.view.container,e);return n?n.apply(this,L.call(arguments,1)):I.helperMissing.call(this,e)}function C(e){var t=L.call(arguments,1),r=O.apply(this,t);V.registerHelper(e,r)}function O(e){function r(){var t,r,i,a,s,o=L.call(arguments,0,-1),u=o.length,l=arguments[arguments.length-1],c=[],h=l.data,p=h.isUnbound?L.call(l.types,1):l.types,f=l.hash,d=l.hashTypes,v=h.view,b=l.contexts,y=b&&b.length?b[0]:this,g="",_=T.prototype.normalizedValue,w=f.boundOptions={};for(i in f)j.test(i)?w[i.slice(0,-7)]=f[i]:"ID"===d[i]&&(w[i]=f[i]);var x=[];for(h.properties=[],t=0;u>t;++t)if(h.properties.push(o[t]),"ID"===p[t]){var C=m(y,o[t],h);c.push(C),x.push(C)}else c.push(h.isUnbound?{path:o[t]}:null);if(h.isUnbound)return E(this,e,c,l);var O=new T(null,null,!l.hash.unescaped,l.data);O.normalizedValue=function(){var r,n=[];for(r in w)w.hasOwnProperty(r)&&(s=m(y,w[r],h),O.path=s.path,O.pathRoot=s.root,f[r]=_.call(O));for(t=0;u>t;++t)s=c[t],s?(O.path=s.path,O.pathRoot=s.root,n.push(_.call(O))):n.push(o[t]);return n.push(l),e.apply(y,n)},v.appendChild(O);for(a in w)w.hasOwnProperty(a)&&x.push(m(y,w[a],h));for(t=0,r=x.length;r>t;++t)s=x[t],v.registerObserver(s.root,s.path,O,O.rerender);if("ID"===p[0]&&0!==c.length){var P=c[0],A=P.root,N=P.path;R(N)||(g=N+".");for(var S=0,V=n.length;V>S;S++)v.registerObserver(A,g+n[S],O,O.rerender)}}T||(T=t("ember-handlebars/views/handlebars_bound_view").SimpleHandlebarsView);var n=L.call(arguments,1);return r._rawFunction=e,r}function E(e,t,r,n){var i,a,s,o,u,l=[],c=n.hash,h=c.boundOptions,p=L.call(n.types,1);for(u in h)h.hasOwnProperty(u)&&(c[u]=f(e,h[u],n));for(i=0,a=r.length;a>i;++i)s=r[i],o=p[i],l.push("ID"===o?f(s.root,s.path,n):s.path);return l.push(n),t.apply(e,l)}function P(e){var t=H(e);return t.isTop=!0,t}var A,T,N=e["default"],S=r.fmt,V=n["default"],I=V.helpers,k=i.get,D=a["default"],j=s.IS_BINDING,M=(o["default"],u._Metamorph,l.isGlobal),R=c["default"],L=[].slice,H=V.template,z=h["default"],q=new z(1e3,function(e){return e.split(".",1)[0]});p.getEscaped=y,p.resolveParams=g,p.resolveHash=_,p.helperMissingHelper=w,p.blockHelperMissingHelper=x,p.registerBoundHelper=C,p.template=P,p.normalizePath=m,p.makeBoundHelper=O,p.handlebarsGet=f,p.handlebarsGetView=b,p.evaluateUnboundHelper=E}),e("ember-handlebars/helpers/binding",["ember-metal/core","ember-handlebars-compiler","ember-metal/property_get","ember-metal/property_set","ember-metal/utils","ember-runtime/system/string","ember-metal/platform","ember-metal/is_none","ember-metal/enumerable_utils","ember-metal/array","ember-views/views/view","ember-metal/run_loop","ember-metal/observer","ember-metal/binding","ember-views/system/jquery","ember-handlebars/ext","ember-metal/keys","ember-metal/cache","ember-handlebars/views/handlebars_bound_view","exports"],function(e,t,r,n,i,a,s,o,u,l,c,h,p,m,f,d,v,b,y,g){"use strict";function _(e){return!z(e)}function w(e,t,r,n,i,a){var s,o,u,l=t.data,c=t.fn,h=t.inverse,p=l.view,m=this||window;if(s=et(m,e,l),l.insideGroup){o=function(){for(;p._contextView;)p=p._contextView;B.once(p,"rerender")};var f,d,v=tt(m,e,t);v=i?i(v):v,d=r?m:v,n(v)?f=c:h&&(f=h),f(d,{data:t.data})}else{var b=Z,y={preserveContext:r,shouldDisplayFunc:n,valueNormalizerFunc:i,displayTemplate:c,inverseTemplate:h,path:e,pathRoot:m,previousContext:m,isEscaped:!t.hash.unescaped,templateData:t.data,templateHash:t.hash,helperName:t.helperName};t.isWithHelper&&(b=st);var g=p.createChildView(b,y);p.appendChild(g),o=function(){B.scheduleOnce("render",g,"rerenderIfNeeded")}}if("object"==typeof this&&""!==s.path&&(p.registerObserver(s.root,s.path,o),a))for(u=0;ua;a++){var s=e.objectAt(a);r.data.keywords[r.hash.keyword]=s,i(s,{data:n})}}},rerenderContainingView:function(){var e=this;T.scheduleOnce("render",this,function(){e.destroyed||e.containingView.rerender()})},destroy:function(){this.removeContentObservers(),this.content&&this.removeArrayObservers(),this.destroyed=!0}},b.EachView=M,b.GroupedEach=R,b.eachHelper=y}),e("ember-handlebars/helpers/loc",["ember-runtime/system/string","exports"],function(e,t){"use strict";var r=e.loc;t["default"]=r}),e("ember-handlebars/helpers/partial",["ember-metal/core","ember-metal/is_none","ember-handlebars/ext","ember-handlebars/helpers/binding","exports"],function(e,t,r,n,i){"use strict";function a(e){return!o(e)}function s(e,t,r){var n=t.split("/"),i=n[n.length-1];n[n.length-1]="_"+i;var a=r.data.view,s=n.join("/"),o=a.templateForName(s),u=!o&&a.templateForName(t);(o=o||u)(e,{data:r.data})}var o=(e["default"],t.isNone),u=r.handlebarsGet,l=n.bind;i["default"]=function(e,t){var r=t.contexts&&t.contexts.length?t.contexts[0]:this;return t.helperName=t.helperName||"partial","ID"===t.types[0]?(t.fn=function(t,r){var n=u(t,e,r);s(t,n,r)},l.call(r,e,t,!0,a)):void s(r,e,t)}}),e("ember-handlebars/helpers/shared",["ember-handlebars/ext","exports"],function(e,t){"use strict";var r=e.handlebarsGet;t["default"]=function(e){for(var t=[],n=e.contexts,i=e.roots,a=e.data,s=0,o=n.length;o>s;s++)t.push(r(i[s],n[s],{data:a}));return t}}),e("ember-handlebars/helpers/template",["ember-metal/core","ember-handlebars-compiler","exports"],function(e,t,r){"use strict";var n=(e["default"],t["default"]),i=n.helpers;r["default"]=function(e,t){return t.helperName=t.helperName||"template",i.partial.apply(this,arguments)}}),e("ember-handlebars/helpers/unbound",["ember-handlebars-compiler","ember-handlebars/helpers/binding","ember-handlebars/ext","exports"],function(e,t,r,n){"use strict";var i=e["default"],a=i.helpers,s=t.resolveHelper,o=r.handlebarsGet,u=[].slice;n["default"]=function(e,t){var r,n,i,l,c=arguments[arguments.length-1],h=c.data.view.container;return l=this,arguments.length>2?(c.data.isUnbound=!0,r=s(h,e)||a.helperMissing,i=r.apply(l,u.call(arguments,1)),delete c.data.isUnbound,i):(n=t.contexts&&t.contexts.length?t.contexts[0]:l,o(n,e,t))}}),e("ember-handlebars/helpers/view",["ember-metal/core","ember-runtime/system/object","ember-metal/property_get","ember-metal/property_set","ember-metal/mixin","ember-views/system/jquery","ember-views/views/view","ember-metal/binding","ember-metal/keys","ember-handlebars/ext","ember-runtime/system/string","exports"],function(e,t,r,n,i,a,s,o,u,l,c,h){"use strict";function p(e,t){var r=t.hash,n=t.hashTypes;for(var i in r)if("ID"===n[i]){var a=r[i];d.test(i)||(r[i+"Binding"]=a,n[i+"Binding"]="STRING",delete r[i],delete n[i])}r.hasOwnProperty("idBinding")&&(r.id=_(e,r.idBinding,t),n.id="STRING",delete r.idBinding,delete n.idBinding)}function m(e,t){return e&&e.data&&e.data.isRenderData&&(t=e,e=t.data&&t.data.view&&t.data.view.container?t.data.view.container.lookupFactory("view:toplevel"):v),t.helperName=t.helperName||"view",x.helper(this,e,t)}var f=(e["default"],t["default"]),d=(r.get,n.set,i.IS_BINDING),v=(a["default"],s["default"]),b=o.isGlobalPath,y=u["default"],g=l.normalizePath,_=l.handlebarsGet,w=l.handlebarsGetView,x=(c["default"],f.create({propertiesFromHTMLOptions:function(e){var t=e.hash,r=e.data,n=t["class"],i={helperName:e.helperName||""};t.id&&(i.elementId=t.id),t.tag&&(i.tagName=t.tag),n&&(n=n.split(" "),i.classNames=n),t.classBinding&&(i.classNameBindings=t.classBinding.split(" ")),t.classNameBindings&&(void 0===i.classNameBindings&&(i.classNameBindings=[]),i.classNameBindings=i.classNameBindings.concat(t.classNameBindings.split(" "))),t.attributeBindings&&(i.attributeBindings=null);for(var a,s=y(t),o=0,u=s.length;u>o;o++){var l=s[o],c=d.test(l);"classNameBindings"!==l&&(i[l]=t[l]),c&&"string"==typeof i[l]&&(a=this.contextualizeBindingPath(t[l],r),a&&(i[l]=a))}if(i.classNameBindings)for(var h=0,p=i.classNameBindings.length;p>h;h++){var m=i.classNameBindings[h];if("string"==typeof m){var f=v._parsePropertyPath(m);""!==f.path&&(a=this.contextualizeBindingPath(f.path,r),a&&(i.classNameBindings[h]=a+f.classNames))}}return i},contextualizeBindingPath:function(e,t){var r=g(null,e,t);return r.isKeyword?"templateData.keywords."+e:b(e)?null:"this"===e||""===e?"_parentView.context":"_parentView.context."+e},helper:function(e,t,r){var n,i,a=r.data,s=r.fn;p(e,r);var o=this.container||a&&a.view&&a.view.container;n=w(e,t,o,r),i=v.detectInstance(n)?n:n.proto();var u=this.propertiesFromHTMLOptions(r,e),l=a.view;u.templateData=a,s&&(u.template=s),i.controller||i.controllerBinding||u.controller||u.controllerBinding||(u._context=e),l.appendChild(n,u)},instanceHelper:function(e,t,r){var n=r.data,i=r.fn;p(e,r);var a=this.propertiesFromHTMLOptions(r,e),s=n.view;a.templateData=n,i&&(a.template=i),t.controller||t.controllerBinding||a.controller||a.controllerBinding||(a._context=e),s.appendChild(t,a)}}));h.ViewHelper=x,h.viewHelper=m}),e("ember-handlebars/helpers/yield",["ember-metal/core","ember-metal/property_get","exports"],function(e,t,r){"use strict";var n=(e["default"],t.get);r["default"]=function(e){for(var t=e.data.view;t&&!n(t,"layout");)t=t._contextView?t._contextView:n(t,"_parentView");t._yield(this,e)}}),e("ember-handlebars/loader",["ember-handlebars/component_lookup","ember-views/system/jquery","ember-metal/error","ember-runtime/system/lazy_load","ember-handlebars-compiler","exports"],function(e,t,r,n,a,s){"use strict";function o(e){var t='script[type="text/x-handlebars"], script[type="text/x-raw-handlebars"]';h(t,e).each(function(){var e=h(this),t="text/x-raw-handlebars"===e.attr("type")?h.proxy(Handlebars.compile,Handlebars):h.proxy(f.compile,f),r=e.attr("data-template-name")||e.attr("id")||"application",n=t(e.html());if(void 0!==i.TEMPLATES[r])throw new p('Template named "'+r+'" already exists.');i.TEMPLATES[r]=n,e.remove()})}function u(){o(h(document))}function l(e){e.register("component-lookup:main",c)}var c=e["default"],h=t["default"],p=r["default"],m=n.onLoad,f=a["default"];m("Ember.Application",function(e){e.initializer({name:"domTemplates",initialize:u}),e.initializer({name:"registerComponentLookup",after:"domTemplates",initialize:l})}),s["default"]=o}),e("ember-handlebars/string",["ember-runtime/system/string","exports"],function(e,t){"use strict";function r(e){return"string"!=typeof e&&(e=""+e),new Handlebars.SafeString(e)}var n=e["default"];n.htmlSafe=r,(i.EXTEND_PROTOTYPES===!0||i.EXTEND_PROTOTYPES.String)&&(String.prototype.htmlSafe=function(){return r(this)}),t["default"]=r}),e("ember-handlebars/views/handlebars_bound_view",["ember-handlebars-compiler","ember-metal/core","ember-metal/error","ember-metal/property_get","ember-metal/property_set","ember-metal/merge","ember-metal/run_loop","ember-views/views/view","ember-handlebars/string","ember-views/views/states","ember-handlebars/views/metamorph_view","ember-handlebars/ext","ember-metal/utils","exports"],function(e,t,r,n,i,a,s,o,u,l,c,h,p,m){"use strict";function f(e,t,r,n){this.path=e,this.pathRoot=t,this.isEscaped=r,this.templateData=n,this[b.GUID_KEY]=S(),this._lastNormalizedValue=void 0,this.state="preRender",this.updateId=null,this._parentView=null,this.buffer=null,this._morph=null}var d=e["default"],v=d.SafeString,b=t["default"],y=b.K,g=r["default"],_=n.get,w=i.set,x=a["default"],C=s["default"],O=(o["default"],u["default"]),E=l.cloneStates,P=l.states,A=P,T=c["default"],N=h.handlebarsGet,S=p.uuid;f.prototype={isVirtual:!0,isView:!0,destroy:function(){this.updateId&&(C.cancel(this.updateId),this.updateId=null),this._parentView&&this._parentView.removeChild(this),this.morph=null,this.state="destroyed"},propertyWillChange:y,propertyDidChange:y,normalizedValue:function(){var e,t,r=this.path,n=this.pathRoot,i=this.isEscaped;return""===r?e=n:(t=this.templateData,e=N(n,r,{data:t})),i||e instanceof v||(e=O(e)),e},render:function(e){var t=this.normalizedValue();this._lastNormalizedValue=t,e._element=t},rerender:function(){switch(this.state){case"preRender":case"destroyed":break;case"inBuffer":throw new g("Something you did tried to replace an {{expression}} before it was inserted into the DOM.");case"hasElement":case"inDOM":this.updateId=C.scheduleOnce("render",this,"update")}return this},update:function(){this.updateId=null;var e=this.normalizedValue();e!==this._lastNormalizedValue&&(this._lastNormalizedValue=e,this._morph.update(e))},_transitionTo:function(e){this.state=e}},P=E(A),x(P._default,{rerenderIfNeeded:y}),x(P.inDOM,{rerenderIfNeeded:function(e){e.normalizedValue()!==e._lastNormalizedValue&&e.rerender()}});var V=T.extend({instrumentName:"boundHandlebars",_states:P,shouldDisplayFunc:null,preserveContext:!1,previousContext:null,displayTemplate:null,inverseTemplate:null,path:null,pathRoot:null,normalizedValue:function(){var e,t,r=_(this,"path"),n=_(this,"pathRoot"),i=_(this,"valueNormalizerFunc");return""===r?e=n:(t=_(this,"templateData"),e=N(n,r,{data:t})),i?i(e):e},rerenderIfNeeded:function(){this.currentState.rerenderIfNeeded(this)},render:function(e){var t=_(this,"isEscaped"),r=_(this,"shouldDisplayFunc"),n=_(this,"preserveContext"),i=_(this,"previousContext"),a=_(this,"inverseTemplate"),s=_(this,"displayTemplate"),o=this.normalizedValue();if(this._lastNormalizedValue=o,r(o))if(w(this,"template",s),n)w(this,"_context",i);else{if(!s)return null===o||void 0===o?o="":o instanceof v||(o=String(o)),t&&(o=Handlebars.Utils.escapeExpression(o)),void e.push(o);w(this,"_context",o)}else a?(w(this,"template",a),n?w(this,"_context",i):w(this,"_context",o)):w(this,"template",function(){return""});return this._super(e)}});m._HandlebarsBoundView=V,m.SimpleHandlebarsView=f}),e("ember-handlebars/views/metamorph_view",["ember-metal/core","ember-views/views/core_view","ember-views/views/view","ember-metal/mixin","ember-metal/run_loop","exports"],function(e,t,r,n,i,a){"use strict";var s=(e["default"],t["default"]),o=r["default"],u=n.Mixin,l=(i["default"],u.create({isVirtual:!0,tagName:"",instrumentName:"metamorph",init:function(){this._super()}}));a._Metamorph=l;var c=o.extend(l);a._MetamorphView=c;var h=s.extend(l);a._SimpleMetamorphView=h,a["default"]=o.extend(l)}),e("ember-metal-views",["ember-metal-views/renderer","exports"],function(e,t){"use strict";var r=e["default"];t.Renderer=r}),e("ember-metal-views/renderer",["morph","exports"],function(e,t){"use strict";function r(){this._uuid=0,this._views=new Array(2e3),this._queue=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],this._parents=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],this._elements=new Array(17),this._inserts={},this._dom=new u}function n(e,t,r){var n=this._views;n[0]=e;var i=void 0===r?-1:r,a=0,s=1,o=t?t._level+1:0,u=null==t?e:t._root,l=!!u._morph,c=this._queue;c[0]=0;for(var h,p,m,f=1,d=-1,v=this._parents,b=t||null,y=this._elements,g=null,_=null,w=0,x=e;f;){if(y[w]=g,x._morph||(x._morph=null),x._root=u,this.uuid(x),x._level=o+w,x._elementCreated&&this.remove(x,!1,!0),this.willCreateElement(x),_=x._morph&&x._morph.contextualElement,!_&&b&&b._childViewsMorph&&(_=b._childViewsMorph.contextualElement),!_&&x._didCreateElementWithoutMorph&&(_=document.body),g=this.createElement(x,_),v[w++]=d,d=a,b=x,c[f++]=a,h=this.childViews(x))for(p=h.length-1;p>=0;p--)m=h[p],a=s++,n[a]=m,c[f++]=a,x=m;for(a=c[--f],x=n[a];d===a;){if(w--,x._elementCreated=!0,this.didCreateElement(x),l&&this.willInsertElement(x),0===w){f--;break}d=v[w],b=-1===d?t:n[d],this.insertElement(x,b,g,-1),a=c[--f],x=n[a],g=y[w],y[w]=null}}for(this.insertElement(x,t,g,i),p=s-1;p>=0;p--)l&&(n[p]._elementInserted=!0,this.didInsertElement(n[p])),n[p]=null;return g}function i(e,t,r){var n=this.uuid(e);if(this._inserts[n]&&(this.cancelRender(this._inserts[n]),this._inserts[n]=void 0),e._elementCreated){var i,a,s,o,u,l,c,h=[],p=[],m=e._morph;for(h.push(e),i=0;il;l++)o.push(u[l]);for(i=0;il;l++)p.push(u[l]);for(m&&!r&&m.destroy(),i=0,a=h.length;a>i;i++)this.afterRemove(h[i],!1);for(i=0,a=p.length;a>i;i++)this.afterRemove(p[i],!0);r&&(e._morph=m)}}function a(e,t,r,n){null!==r&&void 0!==r&&(e._morph?e._morph.update(r):t&&(e._morph=-1===n?t._childViewsMorph.append(r):t._childViewsMorph.insert(n,r)))}function s(e){e._elementCreated&&this.willDestroyElement(e),e._elementInserted&&this.willRemoveElement(e)}function o(e,t){e._elementInserted=!1,e._morph=null,e._childViewsMorph=null,e._elementCreated&&(e._elementCreated=!1,this.didDestroyElement(e)),t&&this.destroyView(e)}var u=e.DOMHelper;r.prototype.uuid=function(e){return void 0===e._uuid&&(e._uuid=++this._uuid,e._renderer=this),e._uuid},r.prototype.scheduleInsert=function(e,t){if(e._morph||e._elementCreated)throw new Error("You cannot insert a View that has already been rendered");e._morph=t;var r=this.uuid(e);this._inserts[r]=this.scheduleRender(this,function(){this._inserts[r]=null,this.renderTree(e)})},r.prototype.appendTo=function(e,t){var r=this._dom.appendMorph(t);this.scheduleInsert(e,r)},r.prototype.replaceIn=function(e,t){var r=this._dom.createMorph(t,null,null);this.scheduleInsert(e,r)},r.prototype.remove=i,r.prototype.destroy=function(e){this.remove(e,!0)},r.prototype.renderTree=n,r.prototype.insertElement=a,r.prototype.beforeRemove=s,r.prototype.afterRemove=o;var l=function(){};r.prototype.willCreateElement=l,r.prototype.createElement=l,r.prototype.didCreateElement=l,r.prototype.willInsertElement=l,r.prototype.didInsertElement=l,r.prototype.willRemoveElement=l,r.prototype.willDestroyElement=l,r.prototype.didDestroyElement=l,r.prototype.destroyView=l,r.prototype.childViews=l,t["default"]=r}),e("ember-metal",["ember-metal/core","ember-metal/merge","ember-metal/instrumentation","ember-metal/utils","ember-metal/error","ember-metal/enumerable_utils","ember-metal/cache","ember-metal/platform","ember-metal/array","ember-metal/logger","ember-metal/property_get","ember-metal/events","ember-metal/observer_set","ember-metal/property_events","ember-metal/properties","ember-metal/property_set","ember-metal/map","ember-metal/get_properties","ember-metal/set_properties","ember-metal/watch_key","ember-metal/chains","ember-metal/watch_path","ember-metal/watching","ember-metal/expand_properties","ember-metal/computed","ember-metal/computed_macros","ember-metal/observer","ember-metal/mixin","ember-metal/binding","ember-metal/run_loop","ember-metal/libraries","ember-metal/is_none","ember-metal/is_empty","ember-metal/is_blank","ember-metal/is_present","ember-metal/keys","exports"],function(e,r,n,i,a,s,o,u,l,c,h,p,m,f,d,v,b,y,g,_,w,x,C,O,E,P,A,T,N,S,V,I,k,D,j,M,R){"use strict";var L=e["default"],H=r["default"],z=n.instrument,q=n.subscribe,F=n.unsubscribe,B=n.reset,U=i.generateGuid,K=i.GUID_KEY,W=i.guidFor,G=i.META_DESC,Q=i.EMPTY_META,$=i.meta,Y=i.getMeta,J=i.setMeta,Z=i.metaPath,X=i.inspect,et=i.typeOf,tt=i.tryCatchFinally,rt=i.isArray,nt=i.makeArray,it=i.canInvoke,at=i.tryInvoke,st=i.tryFinally,ot=i.wrap,ut=i.apply,lt=i.applyStr,ct=i.uuid,ht=a["default"],pt=s["default"],mt=o["default"],ft=u.create,dt=u.hasPropertyAccessors,vt=l.filter,bt=l.forEach,yt=l.indexOf,gt=l.map,_t=c["default"],wt=h.get,xt=h.getWithDefault,Ct=h.normalizeTuple,Ot=h._getPath,Et=p.on,Pt=p.addListener,At=p.removeListener,Tt=p.suspendListener,Nt=p.suspendListeners,St=p.sendEvent,Vt=p.hasListeners,It=p.watchedEvents,kt=p.listenersFor,Dt=p.listenersDiff,jt=p.listenersUnion,Mt=m["default"],Rt=f.propertyWillChange,Lt=f.propertyDidChange,Ht=f.overrideChains,zt=f.beginPropertyChanges,qt=f.endPropertyChanges,Ft=f.changeProperties,Bt=d.Descriptor,Ut=d.defineProperty,Kt=v.set,Wt=v.trySet,Gt=b.OrderedSet,Qt=b.Map,$t=b.MapWithDefault,Yt=y["default"],Jt=g["default"],Zt=_.watchKey,Xt=_.unwatchKey,er=w.flushPendingChains,tr=w.removeChainWatcher,rr=w.ChainNode,nr=w.finishChains,ir=x.watchPath,ar=x.unwatchPath,sr=C.watch,or=C.isWatching,ur=C.unwatch,lr=C.rewatch,cr=C.destroy,hr=O["default"],pr=E.ComputedProperty,mr=E.computed,fr=E.cacheFor,dr=A.addObserver,vr=A.observersFor,br=A.removeObserver,yr=A.addBeforeObserver,gr=A._suspendBeforeObserver,_r=A._suspendObserver,wr=A._suspendBeforeObservers,xr=A._suspendObservers,Cr=A.beforeObserversFor,Or=A.removeBeforeObserver,Er=T.IS_BINDING,Pr=T.mixin,Ar=T.Mixin,Tr=T.required,Nr=T.aliasMethod,Sr=T.observer,Vr=T.immediateObserver,Ir=T.beforeObserver,kr=N.Binding,Dr=N.isGlobalPath,jr=N.bind,Mr=N.oneWay,Rr=S["default"],Lr=V["default"],Hr=I.isNone,zr=I.none,qr=k.isEmpty,Fr=k.empty,Br=D["default"],Ur=j["default"],Kr=M["default"],Wr=L.Instrumentation={};Wr.instrument=z,Wr.subscribe=q,Wr.unsubscribe=F,Wr.reset=B,L.instrument=z,L.subscribe=q,L._Cache=mt,L.generateGuid=U,L.GUID_KEY=K,L.create=ft,L.keys=Kr,L.platform={defineProperty:Ut,hasPropertyAccessors:dt};var Gr=L.ArrayPolyfills={};Gr.map=gt,Gr.forEach=bt,Gr.filter=vt,Gr.indexOf=yt,L.Error=ht,L.guidFor=W,L.META_DESC=G,L.EMPTY_META=Q,L.meta=$,L.getMeta=Y,L.setMeta=J,L.metaPath=Z,L.inspect=X,L.typeOf=et,L.tryCatchFinally=tt,L.isArray=rt,L.makeArray=nt,L.canInvoke=it,L.tryInvoke=at,L.tryFinally=st,L.wrap=ot,L.apply=ut,L.applyStr=lt,L.uuid=ct,L.Logger=_t,L.get=wt,L.getWithDefault=xt,L.normalizeTuple=Ct,L._getPath=Ot,L.EnumerableUtils=pt,L.on=Et,L.addListener=Pt,L.removeListener=At,L._suspendListener=Tt,L._suspendListeners=Nt,L.sendEvent=St,L.hasListeners=Vt,L.watchedEvents=It,L.listenersFor=kt,L.listenersDiff=Dt,L.listenersUnion=jt,L._ObserverSet=Mt,L.propertyWillChange=Rt,L.propertyDidChange=Lt,L.overrideChains=Ht,L.beginPropertyChanges=zt,L.endPropertyChanges=qt,L.changeProperties=Ft,L.Descriptor=Bt,L.defineProperty=Ut,L.set=Kt,L.trySet=Wt,L.OrderedSet=Gt,L.Map=Qt,L.MapWithDefault=$t,L.getProperties=Yt,L.setProperties=Jt,L.watchKey=Zt,L.unwatchKey=Xt,L.flushPendingChains=er,L.removeChainWatcher=tr,L._ChainNode=rr,L.finishChains=nr,L.watchPath=ir,L.unwatchPath=ar,L.watch=sr,L.isWatching=or,L.unwatch=ur,L.rewatch=lr,L.destroy=cr,L.expandProperties=hr,L.ComputedProperty=pr,L.computed=mr,L.cacheFor=fr,L.addObserver=dr,L.observersFor=vr,L.removeObserver=br,L.addBeforeObserver=yr,L._suspendBeforeObserver=gr,L._suspendBeforeObservers=wr,L._suspendObserver=_r,L._suspendObservers=xr,L.beforeObserversFor=Cr,L.removeBeforeObserver=Or,L.IS_BINDING=Er,L.required=Tr,L.aliasMethod=Nr,L.observer=Sr,L.immediateObserver=Vr,L.beforeObserver=Ir,L.mixin=Pr,L.Mixin=Ar,L.oneWay=Mr,L.bind=jr,L.Binding=kr,L.isGlobalPath=Dr,L.run=Rr,L.libraries=Lr,L.libraries.registerCoreLibrary("Ember",L.VERSION),L.isNone=Hr,L.none=zr,L.isEmpty=qr,L.empty=Fr,L.isBlank=Br,L.isPresent=Ur,L.merge=H,L.onerror=null,L.__loader.registry["ember-debug"]&&t("ember-debug"),R["default"]=L}),e("ember-metal/alias",["ember-metal/property_get","ember-metal/property_set","ember-metal/error","ember-metal/properties","ember-metal/computed","ember-metal/platform","ember-metal/utils","ember-metal/dependent_keys","exports"],function(e,t,r,n,i,a,s,o,u){"use strict";function l(e){return new c(e)}function c(e){this.altKey=e,this._dependentKeys=[e]}function h(e,t){throw new d('Cannot set read-only property "'+t+'" on object: '+w(e))}function p(e,t,r){return b(e,t,null),f(e,t,r)}var m=e.get,f=t.set,d=r["default"],v=n.Descriptor,b=n.defineProperty,y=i.ComputedProperty,g=a.create,_=s.meta,w=s.inspect,x=o.addDependentKeys,C=o.removeDependentKeys;u.alias=l,u.AliasedProperty=c,c.prototype=g(v.prototype),c.prototype.get=function(e){return m(e,this.altKey)},c.prototype.set=function(e,t,r){return f(e,this.altKey,r)},c.prototype.willWatch=function(e,t){x(this,e,t,_(e))},c.prototype.didUnwatch=function(e,t){C(this,e,t,_(e))},c.prototype.setup=function(e,t){var r=_(e);r.watching[t]&&x(this,e,t,r)},c.prototype.teardown=function(e,t){var r=_(e);r.watching[t]&&C(this,e,t,r)},c.prototype.readOnly=function(){return this.set=h,this},c.prototype.oneWay=function(){return this.set=p,this},c.prototype._meta=void 0,c.prototype.meta=y.prototype.meta}),e("ember-metal/array",["exports"],function(e){"use strict";var t=Array.prototype,r=function(e){return e&&Function.prototype.toString.call(e).indexOf("[native code]")>-1},n=function(e,t){return r(e)?e:t},a=n(t.map,function(e){if(void 0===this||null===this||"function"!=typeof e)throw new TypeError;for(var t=Object(this),r=t.length>>>0,n=new Array(r),i=arguments[1],a=0;r>a;a++)a in t&&(n[a]=e.call(i,t[a],a,t));return n}),s=n(t.forEach,function(e){if(void 0===this||null===this||"function"!=typeof e)throw new TypeError;for(var t=Object(this),r=t.length>>>0,n=arguments[1],i=0;r>i;i++)i in t&&e.call(n,t[i],i,t)}),o=n(t.indexOf,function(e,t){null===t||void 0===t?t=0:0>t&&(t=Math.max(0,this.length+t));for(var r=t,n=this.length;n>r;r++)if(this[r]===e)return r;return-1}),u=n(t.lastIndexOf,function(e,t){var r,n=this.length;for(t=void 0===t?n-1:0>t?Math.ceil(t):Math.floor(t),0>t&&(t+=n),r=t;r>=0;r--)if(this[r]===e)return r;return-1}),l=n(t.filter,function(e,t){var r,n,i=[],a=this.length;for(r=0;a>r;r++)this.hasOwnProperty(r)&&(n=this[r],e.call(t,n,r,this)&&i.push(n));return i});i.SHIM_ES5&&(t.map=t.map||a,t.forEach=t.forEach||s,t.filter=t.filter||l,t.indexOf=t.indexOf||o,t.lastIndexOf=t.lastIndexOf||u),e.map=a,e.forEach=s,e.filter=l,e.indexOf=o,e.lastIndexOf=u}),e("ember-metal/binding",["ember-metal/core","ember-metal/property_get","ember-metal/property_set","ember-metal/utils","ember-metal/observer","ember-metal/run_loop","ember-metal/path_cache","exports"],function(e,t,r,n,i,a,s,o){"use strict";function u(e,t){return f(w(t)?m.lookup:e,t)}function l(e,t){this._direction=void 0,this._from=t,this._to=e,this._readyToSync=void 0,this._oneWay=void 0}function c(e,t){for(var r in t)t.hasOwnProperty(r)&&(e[r]=t[r])}function h(e,t,r){return new l(t,r).connect(e)}function p(e,t,r){return new l(t,r).oneWay().connect(e)}var m=e["default"],f=t.get,d=(r.set,r.trySet),v=n.guidFor,b=i.addObserver,y=i.removeObserver,g=i._suspendObserver,_=a["default"],w=s.isGlobal;m.LOG_BINDINGS=!1||!!m.ENV.LOG_BINDINGS,l.prototype={copy:function(){var e=new l(this._to,this._from);return this._oneWay&&(e._oneWay=!0),e},from:function(e){return this._from=e,this},to:function(e){return this._to=e,this},oneWay:function(){return this._oneWay=!0,this},toString:function(){var e=this._oneWay?"[oneWay]":"";return"Ember.Binding<"+v(this)+">("+this._from+" -> "+this._to+")"+e},connect:function(e){var t=this._from,r=this._to;return d(e,r,u(e,t)),b(e,t,this,this.fromDidChange),this._oneWay||b(e,r,this,this.toDidChange),this._readyToSync=!0,this},disconnect:function(e){var t=!this._oneWay;return y(e,this._from,this,this.fromDidChange),t&&y(e,this._to,this,this.toDidChange),this._readyToSync=!1,this},fromDidChange:function(e){this._scheduleSync(e,"fwd")},toDidChange:function(e){this._scheduleSync(e,"back")},_scheduleSync:function(e,t){var r=this._direction;void 0===r&&(_.schedule("sync",this,this._sync,e),this._direction=t),"back"===r&&"fwd"===t&&(this._direction="fwd")},_sync:function(e){var t=m.LOG_BINDINGS;if(!e.isDestroyed&&this._readyToSync){var r=this._direction,n=this._from,i=this._to;if(this._direction=void 0,"fwd"===r){var a=u(e,this._from);t&&m.Logger.log(" ",this.toString(),"->",a,e),this._oneWay?d(e,i,a):g(e,i,this,this.toDidChange,function(){d(e,i,a)})}else if("back"===r){var s=f(e,this._to);t&&m.Logger.log(" ",this.toString(),"<-",s,e),g(e,n,this,this.fromDidChange,function(){d(w(n)?m.lookup:e,n,s)})}}}},c(l,{from:function(e){var t=this;return new t(void 0,e)},to:function(e){var t=this;return new t(e,void 0)},oneWay:function(e,t){var r=this;return new r(void 0,e).oneWay(t)}}),o.bind=h,o.oneWay=p,o.Binding=l,o.isGlobalPath=w}),e("ember-metal/cache",["ember-metal/dictionary","exports"],function(e,t){"use strict";function r(e,t){this.store=n(null),this.size=0,this.misses=0,this.hits=0,this.limit=e,this.func=t}var n=e["default"];t["default"]=r;var i=function(){};r.prototype={set:function(e,t){return this.limit>this.size&&(this.size++,this.store[e]=void 0===t?i:t),t},get:function(e){var t=this.store[e];return void 0===t?(this.misses++,t=this.set(e,this.func(e))):t===i?(this.hits++,t=void 0):this.hits++,t},purge:function(){this.store=n(null),this.size=0,this.hits=0,this.misses=0}}}),e("ember-metal/chains",["ember-metal/core","ember-metal/property_get","ember-metal/utils","ember-metal/array","ember-metal/watch_key","exports"],function(e,t,r,n,i,a){"use strict";function s(e){return e.match(x)[0]}function o(){if(0!==C.length){var e=C;C=[],b.call(e,function(e){e[0].add(e[1])}),w("Watching an undefined global, Ember expects watched globals to be setup by the time the run loop is flushed, check for typos",0===C.length)}}function u(e,t,r){if(e&&"object"==typeof e){var n=_(e),i=n.chainWatchers;n.hasOwnProperty("chainWatchers")||(i=n.chainWatchers={}),i[t]||(i[t]=[]),i[t].push(r),y(e,t,n)}}function l(e,t,r){if(e&&"object"==typeof e){var n=e.__ember_meta__;if(!n||n.hasOwnProperty("chainWatchers")){var i=n&&n.chainWatchers;if(i&&i[t]){i=i[t];for(var a=0,s=i.length;s>a;a++)if(i[a]===r){i.splice(a,1);break}}g(e,t,n)}}}function c(e,t,r){this._parent=e,this._key=t,this._watching=void 0===r,this._value=r,this._paths={},this._watching&&(this._object=e.value(),this._object&&u(this._object,this._key,this)),this._parent&&"@each"===this._parent._key&&this.value()}function h(e,t){if(!e)return void 0;var r=e.__ember_meta__;if(r&&r.proto===e)return void 0;if("@each"===t)return f(e,t);var n=r&&r.descs[t];return n&&n._cacheable?t in r.cache?r.cache[t]:void 0:f(e,t)}function p(e){var t,r,n,i=e.__ember_meta__;if(i){if(r=i.chainWatchers)for(var a in r)if(r.hasOwnProperty(a)&&(n=r[a]))for(var s=0,o=n.length;o>s;s++)n[s].didChange(null);t=i.chains,t&&t.value()!==e&&(_(e).chains=t=t.copy(e))}}var m=e["default"],f=t.get,d=t.normalizeTuple,v=r.meta,b=n.forEach,y=i.watchKey,g=i.unwatchKey,_=v,w=m.warn,x=/^([^\.]+)/,C=[];a.flushPendingChains=o;var O=c.prototype;O.value=function(){if(void 0===this._value&&this._watching){var e=this._parent.value();this._value=h(e,this._key)}return this._value},O.destroy=function(){if(this._watching){var e=this._object;e&&l(e,this._key,this),this._watching=!1}},O.copy=function(e){var t,r=new c(null,null,e),n=this._paths;for(t in n)n[t]<=0||r.add(t);return r},O.add=function(e){var t,r,n,i,a;if(a=this._paths,a[e]=(a[e]||0)+1,t=this.value(),r=d(t,e),r[0]&&r[0]===t)e=r[1],n=s(e),e=e.slice(n.length+1);else{if(!r[0])return C.push([this,e]),void(r.length=0);i=r[0],n=e.slice(0,0-(r[1].length+1)),e=r[1]}r.length=0,this.chain(n,e,i)},O.remove=function(e){var t,r,n,i,a;a=this._paths,a[e]>0&&a[e]--,t=this.value(),r=d(t,e),r[0]===t?(e=r[1],n=s(e),e=e.slice(n.length+1)):(i=r[0],n=e.slice(0,0-(r[1].length+1)),e=r[1]),r.length=0,this.unchain(n,e)},O.count=0,O.chain=function(e,t,r){var n,i=this._chains;i||(i=this._chains={}),n=i[e],n||(n=i[e]=new c(this,e,r)),n.count++,t&&(e=s(t),t=t.slice(e.length+1),n.chain(e,t))},O.unchain=function(e,t){var r=this._chains,n=r[e];t&&t.length>1&&(e=s(t),t=t.slice(e.length+1),n.unchain(e,t)),n.count--,n.count<=0&&(delete r[n._key],n.destroy())},O.willChange=function(e){var t=this._chains;if(t)for(var r in t)t.hasOwnProperty(r)&&t[r].willChange(e);this._parent&&this._parent.chainWillChange(this,this._key,1,e)},O.chainWillChange=function(e,t,r,n){this._key&&(t=this._key+"."+t),this._parent?this._parent.chainWillChange(this,t,r+1,n):(r>1&&n.push(this.value(),t),t="this."+t,this._paths[t]>0&&n.push(this.value(),t))},O.chainDidChange=function(e,t,r,n){this._key&&(t=this._key+"."+t),this._parent?this._parent.chainDidChange(this,t,r+1,n):(r>1&&n.push(this.value(),t),t="this."+t,this._paths[t]>0&&n.push(this.value(),t))},O.didChange=function(e){if(this._watching){var t=this._parent.value();t!==this._object&&(l(this._object,this._key,this),this._object=t,u(t,this._key,this)),this._value=void 0,this._parent&&"@each"===this._parent._key&&this.value()}var r=this._chains;if(r)for(var n in r)r.hasOwnProperty(n)&&r[n].didChange(e);null!==e&&this._parent&&this._parent.chainDidChange(this,this._key,1,e)},a.finishChains=p,a.removeChainWatcher=l,a.ChainNode=c}),e("ember-metal/computed",["ember-metal/core","ember-metal/property_get","ember-metal/property_set","ember-metal/utils","ember-metal/expand_properties","ember-metal/error","ember-metal/properties","ember-metal/property_events","ember-metal/dependent_keys","exports"],function(e,t,r,n,i,a,s,o,u,l){"use strict";function c(){}function h(e,t){e.__ember_arity__=e.length,this.func=e,this._cacheable=t&&void 0!==t.cacheable?t.cacheable:!0,this._dependentKeys=t&&t.dependentKeys,this._readOnly=t&&(void 0!==t.readOnly||!!t.readOnly)||!1}function p(e){for(var t=0,r=e.length;r>t;t++)e[t].didChange(null)}function m(e){var t;if(arguments.length>1&&(t=A.call(arguments),e=t.pop()),"function"!=typeof e)throw new g("Computed Property declared without a property function");var r=new h(e);return t&&r.property.apply(r,t),r}function f(e,t){var r=e.__ember_meta__,n=r&&r.cache,i=n&&n[t];return i===c?void 0:i}var d=(e["default"],t.get,r.set),v=n.meta,b=n.inspect,y=i["default"],g=a["default"],_=s.Descriptor,w=s.defineProperty,x=o.propertyWillChange,C=o.propertyDidChange,O=u.addDependentKeys,E=u.removeDependentKeys,P=v,A=[].slice;h.prototype=new _;var T=h.prototype;T._dependentKeys=void 0,T._suspended=void 0,T._meta=void 0,T.cacheable=function(e){return this._cacheable=e!==!1,this},T["volatile"]=function(){return this.cacheable(!1)},T.readOnly=function(e){return this._readOnly=void 0===e||!!e,this -},T.property=function(){var e,t=function(t){e.push(t)};e=[];for(var r=0,n=arguments.length;n>r;r++)y(arguments[r],t);return this._dependentKeys=e,this},T.meta=function(e){return 0===arguments.length?this._meta||{}:(this._meta=e,this)},T.didChange=function(e,t){if(this._cacheable&&this._suspended!==e){var r=P(e);void 0!==r.cache[t]&&(r.cache[t]=void 0,E(this,e,t,r))}},T.get=function(e,t){var r,n,i,a;if(this._cacheable){i=P(e),n=i.cache;var s=n[t];if(s===c)return void 0;if(void 0!==s)return s;r=this.func.call(e,t),n[t]=void 0===r?c:r,a=i.chainWatchers&&i.chainWatchers[t],a&&p(a),O(this,e,t,i)}else r=this.func.call(e,t);return r},T.set=function(e,t,r){var n=this._suspended;this._suspended=e;try{this._set(e,t,r)}finally{this._suspended=n}},T._set=function(e,t,r){var n,i,a,s=this._cacheable,o=this.func,u=P(e,s),l=u.cache,h=!1;if(this._readOnly)throw new g('Cannot set read-only property "'+t+'" on object: '+b(e));if(s&&void 0!==l[t]&&(l[t]!==c&&(i=l[t]),h=!0),n=o.wrappedFunction?o.wrappedFunction.__ember_arity__:o.__ember_arity__,3===n)a=o.call(e,t,r,i);else{if(2!==n)return w(e,t,null,i),void d(e,t,r);a=o.call(e,t,r)}if(!h||i!==a){var p=u.watching[t];return p&&x(e,t),h&&(l[t]=void 0),s&&(h||O(this,e,t,u),l[t]=void 0===a?c:a),p&&C(e,t),a}},T.teardown=function(e,t){var r=P(e);return t in r.cache&&E(this,e,t,r),this._cacheable&&delete r.cache[t],null},f.set=function(e,t,r){e[t]=void 0===r?c:r},f.get=function(e,t){var r=e[t];return r===c?void 0:r},f.remove=function(e,t){e[t]=void 0},l.ComputedProperty=h,l.computed=m,l.cacheFor=f}),e("ember-metal/computed_macros",["ember-metal/core","ember-metal/property_get","ember-metal/property_set","ember-metal/computed","ember-metal/is_empty","ember-metal/is_none","ember-metal/alias"],function(e,t,r,n,i,a,s){"use strict";function o(e,t){for(var r={},n=0;nt}),u("gte",function(e,t){return c(this,e)>=t}),u("lt",function(e,t){return c(this,e)1?(h(this,e,r),r):c(this,e)})}}),e("ember-metal/core",["exports"],function(e){"use strict";"undefined"==typeof i&&(i={});{var t=(i.imports=i.imports||this,i.exports=i.exports||this);i.lookup=i.lookup||this}t.Em=t.Ember=i,i.isNamespace=!0,i.toString=function(){return"Ember"},i.VERSION="1.8.1",i.ENV||(i.ENV="undefined"!=typeof EmberENV?EmberENV:"undefined"!=typeof ENV?ENV:{}),i.config=i.config||{},"undefined"==typeof i.ENV.DISABLE_RANGE_API&&(i.ENV.DISABLE_RANGE_API=!0),"undefined"==typeof MetamorphENV&&(t.MetamorphENV={}),MetamorphENV.DISABLE_RANGE_API=i.ENV.DISABLE_RANGE_API,i.FEATURES=i.ENV.FEATURES||{},i.FEATURES.isEnabled=function(e){var t=i.FEATURES[e];return i.ENV.ENABLE_ALL_FEATURES?!0:t===!0||t===!1||void 0===t?t:i.ENV.ENABLE_OPTIONAL_FEATURES?!0:!1},i.EXTEND_PROTOTYPES=i.ENV.EXTEND_PROTOTYPES,"undefined"==typeof i.EXTEND_PROTOTYPES&&(i.EXTEND_PROTOTYPES=!0),i.LOG_STACKTRACE_ON_DEPRECATION=i.ENV.LOG_STACKTRACE_ON_DEPRECATION!==!1,i.SHIM_ES5=i.ENV.SHIM_ES5===!1?!1:i.EXTEND_PROTOTYPES,i.LOG_VERSION=i.ENV.LOG_VERSION===!1?!1:!0;var r=function(){return this},r=r;e.K=r,i.K=r,"undefined"==typeof i.assert&&(i.assert=i.K),"undefined"==typeof i.warn&&(i.warn=i.K),"undefined"==typeof i.debug&&(i.debug=i.K),"undefined"==typeof i.runInDebug&&(i.runInDebug=i.K),"undefined"==typeof i.deprecate&&(i.deprecate=i.K),"undefined"==typeof i.deprecateFunc&&(i.deprecateFunc=function(e,t){return t}),e["default"]=i}),e("ember-metal/dependent_keys",["ember-metal/platform","ember-metal/watching","exports"],function(e,t,r){function n(e,t){var r=e[t];return r?e.hasOwnProperty(t)||(r=e[t]=o(r)):r=e[t]={},r}function i(e){return n(e,"deps")}function a(e,t,r,a){var s,o,l,c,h,p=e._dependentKeys;if(p)for(s=i(a),o=0,l=p.length;l>o;o++)c=p[o],h=n(s,c),h[r]=(h[r]||0)+1,u(t,c,a)}function s(e,t,r,a){var s,o,u,c,h,p=e._dependentKeys;if(p)for(s=i(a),o=0,u=p.length;u>o;o++)c=p[o],h=n(s,c),h[r]=(h[r]||0)-1,l(t,c,a)}var o=e.create,u=t.watch,l=t.unwatch;r.addDependentKeys=a,r.removeDependentKeys=s}),e("ember-metal/deprecate_property",["ember-metal/core","ember-metal/platform","ember-metal/properties","ember-metal/property_get","ember-metal/property_set","exports"],function(e,t,r,n,i,a){"use strict";function s(e,t,r){function n(){}o&&u(e,t,{configurable:!0,enumerable:!1,set:function(e){n(),c(this,r,e)},get:function(){return n(),l(this,r)}})}var o=(e["default"],t.hasPropertyAccessors),u=r.defineProperty,l=n.get,c=i.set;a.deprecateProperty=s}),e("ember-metal/dictionary",["ember-metal/platform","exports"],function(e,t){"use strict";var r=e.create;t["default"]=function(e){var t=r(e);return t._dict=null,delete t._dict,t}}),e("ember-metal/enumerable_utils",["ember-metal/array","exports"],function(e,t){"use strict";function r(e,t,r){return e.map?e.map(t,r):d.call(e,t,r)}function n(e,t,r){return e.forEach?e.forEach(t,r):m.call(e,t,r)}function i(e,t,r){return e.filter?e.filter(t,r):p.call(e,t,r)}function a(e,t,r){return e.indexOf?e.indexOf(t,r):f.call(e,t,r)}function s(e,t){return void 0===t?[]:r(t,function(t){return a(e,t)})}function o(e,t){var r=a(e,t);-1===r&&e.push(t)}function u(e,t){var r=a(e,t);-1!==r&&e.splice(r,1)}function l(e,t,r,n){for(var i,a,s=[].concat(n),o=[],u=6e4,l=t,c=r;s.length;)i=c>u?u:c,0>=i&&(i=0),a=s.splice(0,u),a=[l,i].concat(a),l+=u,c-=i,o=o.concat(v.apply(e,a));return o}function c(e,t,r,n){return e.replace?e.replace(t,r,n):l(e,t,r,n)}function h(e,t){var r=[];return n(e,function(e){a(t,e)>=0&&r.push(e)}),r}var p=e.filter,m=e.forEach,f=e.indexOf,d=e.map,v=Array.prototype.splice;t.map=r,t.forEach=n,t.filter=i,t.indexOf=a,t.indexesOf=s,t.addObject=o,t.removeObject=u,t._replace=l,t.replace=c,t.intersection=h,t["default"]={_replace:l,addObject:o,filter:i,forEach:n,indexOf:a,indexesOf:s,intersection:h,map:r,removeObject:u,replace:c}}),e("ember-metal/error",["ember-metal/platform","exports"],function(e,t){"use strict";function r(){var e=Error.apply(this,arguments);Error.captureStackTrace&&Error.captureStackTrace(this,i.Error);for(var t=0;t=0;i-=3)if(t===e[i]&&r===e[i+1]){n=i;break}return n}function a(e,t){var r,n=O(e,!0);return n.listeners||(n.listeners={}),n.hasOwnProperty("listeners")||(n.listeners=x(n.listeners)),r=n.listeners[t],r&&!n.listeners.hasOwnProperty(t)?r=n.listeners[t]=n.listeners[t].slice():r||(r=n.listeners[t]=[]),r}function s(e,t,r){var n=e.__ember_meta__,a=n&&n.listeners&&n.listeners[t];if(a)for(var s=a.length-3;s>=0;s-=3){var o=a[s],u=a[s+1],l=a[s+2],c=i(r,o,u);-1===c&&r.push(o,u,l)}}function o(e,t,r){var n=e.__ember_meta__,a=n&&n.listeners&&n.listeners[t],s=[];if(a){for(var o=a.length-3;o>=0;o-=3){var u=a[o],l=a[o+1],c=a[o+2],h=i(r,u,l);-1===h&&(r.push(u,l,c),s.push(u,l,c))}return s}}function u(e,t,r,n,s){n||"function"!=typeof r||(n=r,r=null);var o=a(e,t),u=i(o,r,n),l=0;s&&(l|=E),-1===u&&(o.push(r,n,l),"function"==typeof e.didAddListener&&e.didAddListener(t,r,n))}function l(e,t,r,n){function s(r,n){var s=a(e,t),o=i(s,r,n);-1!==o&&(s.splice(o,3),"function"==typeof e.didRemoveListener&&e.didRemoveListener(t,r,n))}if(n||"function"!=typeof r||(n=r,r=null),n)s(r,n);else{var o=e.__ember_meta__,u=o&&o.listeners&&o.listeners[t];if(!u)return;for(var l=u.length-3;l>=0;l-=3)s(u[l],u[l+1])}}function c(e,t,r,n,s){function o(){return s.call(r)}function u(){-1!==c&&(l[c+2]&=~P)}n||"function"!=typeof r||(n=r,r=null);var l=a(e,t),c=i(l,r,n);return-1!==c&&(l[c+2]|=P),g(o,u)}function h(e,t,r,n,s){function o(){return s.call(r)}function u(){for(var e=0,t=m.length;t>e;e++){var r=m[e];f[e][r+2]&=~P}}n||"function"!=typeof r||(n=r,r=null);var l,c,h,p,m=[],f=[];for(h=0,p=t.length;p>h;h++){l=t[h],c=a(e,l);var d=i(c,r,n);-1!==d&&(c[d+2]|=P,m.push(d),f.push(c))}return g(o,u)}function p(e){var t=e.__ember_meta__.listeners,r=[];if(t)for(var n in t)t[n]&&r.push(n);return r}function m(e,t,r,n){if(e!==b&&"function"==typeof e.sendEvent&&e.sendEvent(t,r),!n){var i=e.__ember_meta__;n=i&&i.listeners&&i.listeners[t]}if(n){for(var a=n.length-3;a>=0;a-=3){var s=n[a],o=n[a+1],u=n[a+2];o&&(u&P||(u&E&&l(e,t,s,o),s||(s=e),"string"==typeof o?r?w(s,o,r):s[o]():r?_(s,o,r):o.call(s)))}return!0}}function f(e,t){var r=e.__ember_meta__,n=r&&r.listeners&&r.listeners[t];return!(!n||!n.length)}function d(e,t){var r=[],n=e.__ember_meta__,i=n&&n.listeners&&n.listeners[t];if(!i)return r;for(var a=0,s=i.length;s>a;a+=3){var o=i[a],u=i[a+1];r.push([o,u])}return r}function v(){var e=C.call(arguments,-1)[0],t=C.call(arguments,0,-1);return e.__ember_listens__=t,e}var b=e["default"],y=t.meta,g=t.tryFinally,_=t.apply,w=t.applyStr,x=r.create,C=[].slice,O=y,E=1,P=2;n.listenersUnion=s,n.listenersDiff=o,n.addListener=u,n.suspendListener=c,n.suspendListeners=h,n.watchedEvents=p,n.sendEvent=m,n.hasListeners=f,n.listenersFor=d,n.on=v,n.removeListener=l}),e("ember-metal/expand_properties",["ember-metal/core","ember-metal/error","ember-metal/enumerable_utils","exports"],function(e,t,r,n){"use strict";function i(e,t){if("string"===s.typeOf(e)){var r=e.split(l),n=[r];u(r,function(e,t){e.indexOf(",")>=0&&(n=a(n,e.split(","),t))}),u(n,function(e){t(e.join(""))})}else t(e)}function a(e,t,r){var n=[];return u(e,function(e){u(t,function(t){var i=e.slice(0);i[r]=t,n.push(i)})}),n}var s=e["default"],o=t["default"],u=r.forEach,l=/\{|\}/;n["default"]=function(e,t){if(e.indexOf(" ")>-1)throw new o("Brace expanded properties cannot contain spaces, e.g. `user.{firstName, lastName}` should be `user.{firstName,lastName}`");return i(e,t)}}),e("ember-metal/get_properties",["ember-metal/property_get","ember-metal/utils","exports"],function(e,t,r){"use strict";var n=e.get,i=t.typeOf;r["default"]=function(e){var t={},r=arguments,a=1;2===arguments.length&&"array"===i(arguments[1])&&(a=0,r=arguments[1]);for(var s=r.length;s>a;a++)t[r[a]]=n(e,r[a]);return t}}),e("ember-metal/instrumentation",["ember-metal/core","ember-metal/utils","exports"],function(e,t,r){"use strict";function n(e,t,r,n){if(0===c.length)return r.call(n);var a=t||{},s=i(e,function(){return a});if(s){var o=function(){return r.call(n)},u=function(e){a.exception=e};return l(o,u,s)}return r.call(n)}function i(e,t){var r=h[e];if(r||(r=p(e)),0!==r.length){var n,i=t(),a=u.STRUCTURED_PROFILE;a&&(n=e+": "+i.object,console.time(n));var s,o,l=r.length,c=new Array(l),f=m();for(s=0;l>s;s++)o=r[s],c[s]=o.before(e,f,i);return function(){var t,s,o,u=m();for(t=0,s=r.length;s>t;t++)o=r[t],o.after(e,u,i,c[t]);a&&console.timeEnd(n)}}}function a(e,t){for(var r,n=e.split("."),i=[],a=0,s=n.length;s>a;a++)r=n[a],i.push("*"===r?"[^\\.]*":r);i=i.join("\\."),i+="(\\..*)?";var o={pattern:e,regex:new RegExp("^"+i+"$"),object:t};return c.push(o),h={},o}function s(e){for(var t,r=0,n=c.length;n>r;r++)c[r]===e&&(t=r);c.splice(t,1),h={}}function o(){c.length=0,h={}}var u=e["default"],l=t.tryCatchFinally,c=[];r.subscribers=c;var h={},p=function(e){for(var t,r=[],n=0,i=c.length;i>n;n++)t=c[n],t.regex.test(e)&&r.push(t.object);return h[e]=r,r},m=function(){var e="undefined"!=typeof window?window.performance||{}:{},t=e.now||e.mozNow||e.webkitNow||e.msNow||e.oNow;return t?t.bind(e):function(){return+new Date}}();r.instrument=n,r._instrumentStart=i,r.subscribe=a,r.unsubscribe=s,r.reset=o}),e("ember-metal/is_blank",["ember-metal/core","ember-metal/is_empty","exports"],function(e,t,r){"use strict";var n=(e["default"],t["default"]);r["default"]=function(e){return n(e)||"string"==typeof e&&null===e.match(/\S/)}}),e("ember-metal/is_empty",["ember-metal/core","ember-metal/property_get","ember-metal/is_none","exports"],function(e,t,r,n){"use strict";function i(e){var t=o(e);if(t)return t;if("number"==typeof e.size)return!e.size;var r=typeof e;if("object"===r){var n=s(e,"size");if("number"==typeof n)return!n}if("number"==typeof e.length&&"function"!==r)return!e.length;if("object"===r){var i=s(e,"length");if("number"==typeof i)return!i}return!1}var a=e["default"],s=t.get,o=r["default"],u=a.deprecateFunc("Ember.empty is deprecated. Please use Ember.isEmpty instead.",i);n.empty=u,n["default"]=i,n.isEmpty=i,n.empty=u}),e("ember-metal/is_none",["ember-metal/core","exports"],function(e,t){"use strict";function r(e){return null===e||void 0===e}var n=e["default"],i=n.deprecateFunc("Ember.none is deprecated. Please use Ember.isNone instead.",r);t.none=i,t["default"]=r,t.isNone=r}),e("ember-metal/is_present",["ember-metal/is_blank","exports"],function(e,t){"use strict";var r,n=e["default"];r=function(e){return!n(e)},t["default"]=r}),e("ember-metal/keys",["ember-metal/platform","exports"],function(e,t){"use strict";var r=e.canDefineNonEnumerableProperties,n=Object.keys;n&&r||(n=function(){var e=Object.prototype.hasOwnProperty,t=!{toString:null}.propertyIsEnumerable("toString"),r=["toString","toLocaleString","valueOf","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","constructor"],n=r.length;return function(i){if("object"!=typeof i&&("function"!=typeof i||null===i))throw new TypeError("Object.keys called on non-object");var a,s,o=[];for(a in i)"_super"!==a&&0!==a.lastIndexOf("__",0)&&e.call(i,a)&&o.push(a);if(t)for(s=0;n>s;s++)e.call(i,r[s])&&o.push(r[s]);return o}}()),t["default"]=n}),e("ember-metal/libraries",["ember-metal/enumerable_utils","exports"],function(e,t){"use strict";var r=e.forEach,n=e.indexOf,i=function(){var e=[],t=0,i=function(t){for(var r=0;r-1&&i.splice(a,1),this.size=i.length,!0}return!1},isEmpty:function(){return 0===this.size},has:function(e){if(0===this.size)return!1;var t=m(e),r=this.presenceSet;return r[t]===!0},forEach:function(e){if("function"!=typeof e&&s(e),0!==this.size){var t,r=this.list,n=arguments.length;if(2===n)for(t=0;ts;s++)n=i[s],e[n]=t[n];return e}}),e("ember-metal/mixin",["ember-metal/core","ember-metal/merge","ember-metal/array","ember-metal/platform","ember-metal/utils","ember-metal/expand_properties","ember-metal/properties","ember-metal/computed","ember-metal/binding","ember-metal/observer","ember-metal/events","exports"],function(e,t,r,n,i,a,s,o,u,l,c,h){function p(){var e,t=this.__nextSuper;if(t){for(var r=new Array(arguments.length),n=0,i=r.length;i>n;n++)r[n]=arguments[n];this.__nextSuper=null,e=Z(this,t,r),this.__nextSuper=t}return e}function m(e){var t=dt(e,!0),r=t.mixins;return r?t.hasOwnProperty("mixins")||(r=t.mixins=ft(r)):r=t.mixins={},r}function f(e,t){return t&&t.length>0&&(e.mixins=ct.call(t,function(e){if(e instanceof I)return e;var t=new I;return t.properties=e,t})),e}function d(e){return"function"==typeof e&&e.isMethod!==!1&&e!==Boolean&&e!==Object&&e!==Number&&e!==Array&&e!==Date&&e!==String}function v(e,t){var r;return t instanceof I?(r=Q(t),e[r]?vt:(e[r]=t,t.properties)):t}function b(e,t,r,n){var i;return i=r[e]||n[e],t[e]&&(i=i?i.concat(t[e]):t[e]),i}function y(e,t,r,n,i){var a;return void 0===n[t]&&(a=i[t]),a=a||e.descs[t],void 0!==a&&a instanceof rt?(r=ft(r),r.func=Y(r.func,a.func),r):r}function g(e,t,r,n,i){var a;return void 0===i[t]&&(a=n[t]),a=a||e[t],void 0===a||"function"!=typeof a?r:Y(r,a)}function _(e,t,r,n){var i=n[t]||e[t];return i?"function"==typeof i.concat?i.concat(r):J(i).concat(r):J(r)}function w(e,t,r,n){var i=n[t]||e[t];if(!i)return r;var a=B({},i),s=!1;for(var o in r)if(r.hasOwnProperty(o)){var u=r[o];d(u)?(s=!0,a[o]=g(e,o,u,i,{})):a[o]=u}return s&&(a._super=p),a}function x(e,t,r,n,i,a,s,o){if(r instanceof et){if(r===q&&i[t])return vt;r.func&&(r=y(n,t,r,a,i)),i[t]=r,a[t]=void 0}else s&&ht.call(s,t)>=0||"concatenatedProperties"===t||"mergedProperties"===t?r=_(e,t,r,a):o&&ht.call(o,t)>=0?r=w(e,t,r,a):d(r)&&(r=g(e,t,r,a,i)),i[t]=void 0,a[t]=r}function C(e,t,r,n,i,a){function s(e){delete r[e],delete n[e]}for(var o,u,l,c,h,p,m=0,f=e.length;f>m;m++)if(o=e[m],u=v(t,o),u!==vt)if(u){p=dt(i),i.willMergeMixin&&i.willMergeMixin(u),c=b("concatenatedProperties",u,n,i),h=b("mergedProperties",u,n,i);for(l in u)u.hasOwnProperty(l)&&(a.push(l),x(i,l,u[l],p,r,n,c,h));u.hasOwnProperty("toString")&&(i.toString=u.toString)}else o.mixins&&(C(o.mixins,t,r,n,i,a),o._without&&pt.call(o._without,s))}function O(e,t,r,n){if(bt.test(t)){var i=n.bindings;i?n.hasOwnProperty("bindings")||(i=n.bindings=ft(n.bindings)):i=n.bindings={},i[t]=r}}function E(e,t){var r,n,i,a=t.bindings;if(a){for(r in a)n=a[r],n&&(i=r.slice(0,-7),n instanceof nt?(n=n.copy(),n.to(i)):n=new nt(i,n),n.connect(e),e[r]=n);t.bindings={}}}function P(e,t){return E(e,t||dt(e)),e}function A(e,t,r,n,i){var a,s=t.methodName;return n[s]||i[s]?(a=i[s],t=n[s]):r.descs[s]?(t=r.descs[s],a=void 0):(t=void 0,a=e[s]),{desc:t,value:a}}function T(e,t,r,n,i){var a=r[n];if(a)for(var s=0,o=a.length;o>s;s++)i(e,a[s],null,t)}function N(e,t,r){var n=e[t];"function"==typeof n&&(T(e,t,n,"__ember_observesBefore__",ot),T(e,t,n,"__ember_observes__",at),T(e,t,n,"__ember_listens__",lt)),"function"==typeof r&&(T(e,t,r,"__ember_observesBefore__",st),T(e,t,r,"__ember_observes__",it),T(e,t,r,"__ember_listens__",ut))}function S(e,t,r){var n,i,a,s={},o={},u=dt(e),l=[];e._super=p,C(t,m(e),s,o,e,l);for(var c=0,h=l.length;h>c;c++)if(n=l[c],"constructor"!==n&&o.hasOwnProperty(n)&&(a=s[n],i=o[n],a!==q)){for(;a&&a instanceof M;){var f=A(e,a,u,s,o);a=f.desc,i=f.value}(void 0!==a||void 0!==i)&&(N(e,n,i),O(e,n,i,u),tt(e,n,a,i,u))}return r||P(e,u),e}function V(e){var t=mt.call(arguments,1);return S(e,t,!1),e}function I(){return f(this,arguments)}function k(e,t,r){var n=Q(e);if(r[n])return!1;if(r[n]=!0,e===t)return!0;for(var i=e.mixins,a=i?i.length:0;--a>=0;)if(k(i[a],t,r))return!0;return!1}function D(e,t,r){if(!r[Q(t)])if(r[Q(t)]=!0,t.properties){var n=t.properties;for(var i in n)n.hasOwnProperty(i)&&(e[i]=!0)}else t.mixins&&pt.call(t.mixins,function(t){D(e,t,r)})}function j(){return q}function M(e){this.methodName=e}function R(e){return new M(e)}function L(){var e,t=mt.call(arguments,-1)[0],r=function(t){e.push(t)},n=mt.call(arguments,0,-1);"function"!=typeof t&&(t=arguments[0],n=mt.call(arguments,1)),e=[];for(var i=0;ie;e++){arguments[e]}return L.apply(this,arguments)}function z(){var e,t=mt.call(arguments,-1)[0],r=function(t){e.push(t)},n=mt.call(arguments,0,-1);"function"!=typeof t&&(t=arguments[0],n=mt.call(arguments,1)),e=[];for(var i=0;ir;r++)e=arguments[r],e instanceof I?i.push(e):(t=I.create(),t.properties=e,i.push(t));return this},yt.apply=function(e){return S(e,[this],!1)},yt.applyPartial=function(e){return S(e,[this],!0)},yt.detect=function(e){if(!e)return!1;if(e instanceof I)return k(e,this,{});var t=e.__ember_meta__,r=t&&t.mixins;return r?!!r[Q(this)]:!1},yt.without=function(){var e=new I(this);return e._without=mt.call(arguments),e},yt.keys=function(){var e={},t={},r=[];D(e,this,t);for(var n in e)e.hasOwnProperty(n)&&r.push(n);return r},I.mixins=function(e){var t=e.__ember_meta__,r=t&&t.mixins,n=[];if(!r)return n;for(var i in r){var a=r[i];a.properties||n.push(a)}return n},q=new et,q.toString=function(){return"(Required Property)"},h.required=j,M.prototype=new et,h.aliasMethod=R,h.observer=L,h.immediateObserver=H,h.beforeObserver=z,h.IS_BINDING=bt,h.Mixin=I}),e("ember-metal/observer",["ember-metal/watching","ember-metal/array","ember-metal/events","exports"],function(e,t,r,n){"use strict";function i(e){return e+O}function a(e){return e+E}function s(e,t,r,n){return _(e,i(t),r,n),v(e,t),this}function o(e,t){return g(e,i(t))}function u(e,t,r,n){return b(e,t),w(e,i(t),r,n),this}function l(e,t,r,n){return _(e,a(t),r,n),v(e,t),this}function c(e,t,r,n,i){return C(e,a(t),r,n,i)}function h(e,t,r,n,a){return C(e,i(t),r,n,a)}function p(e,t,r,n,i){var s=y.call(t,a);return x(e,s,r,n,i)}function m(e,t,r,n,a){var s=y.call(t,i);return x(e,s,r,n,a)}function f(e,t){return g(e,a(t))}function d(e,t,r,n){return b(e,t),w(e,a(t),r,n),this}var v=e.watch,b=e.unwatch,y=t.map,g=r.listenersFor,_=r.addListener,w=r.removeListener,x=r.suspendListeners,C=r.suspendListener,O=":change",E=":before";n.addObserver=s,n.observersFor=o,n.removeObserver=u,n.addBeforeObserver=l,n._suspendBeforeObserver=c,n._suspendObserver=h,n._suspendBeforeObservers=p,n._suspendObservers=m,n.beforeObserversFor=f,n.removeBeforeObserver=d}),e("ember-metal/observer_set",["ember-metal/utils","ember-metal/events","exports"],function(e,t,r){"use strict";function n(){this.clear()}var i=e.guidFor,a=t.sendEvent;r["default"]=n,n.prototype.add=function(e,t,r){var n,a=this.observerSet,s=this.observers,o=i(e),u=a[o];return u||(a[o]=u={}),n=u[t],void 0===n&&(n=s.push({sender:e,keyName:t,eventName:r,listeners:[]})-1,u[t]=n),s[n].listeners},n.prototype.flush=function(){var e,t,r,n,i=this.observers;for(this.clear(),e=0,t=i.length;t>e;++e)r=i[e],n=r.sender,n.isDestroying||n.isDestroyed||a(n,r.eventName,[n,r.keyName],r.listeners)},n.prototype.clear=function(){this.observerSet={},this.observers=[]}}),e("ember-metal/path_cache",["ember-metal/cache","exports"],function(e,t){"use strict";function r(e){return c.get(e)}function n(e){return h.get(e)}function i(e){return p.get(e)}function a(e){return m.get(e)}var s=e["default"],o=/^([A-Z$]|([0-9][A-Z$]))/,u=/^([A-Z$]|([0-9][A-Z$])).*[\.]/,l="this.",c=new s(1e3,function(e){return o.test(e)}),h=new s(1e3,function(e){return u.test(e)}),p=new s(1e3,function(e){return-1!==e.indexOf(l)}),m=new s(1e3,function(e){return-1!==e.indexOf(".")}),f={isGlobalCache:c,isGlobalPathCache:h,hasThisCache:p,isPathCache:m};t.caches=f,t.isGlobal=r,t.isGlobalPath=n,t.hasThis=i,t.isPath=a}),e("ember-metal/platform",["ember-metal/platform/define_property","ember-metal/platform/define_properties","ember-metal/platform/create","exports"],function(e,t,r,n){"use strict";var i=e.hasES5CompliantDefineProperty,a=e.defineProperty,s=t["default"],o=r["default"],u=i,l=i;n.create=o,n.defineProperty=a,n.defineProperties=s,n.hasPropertyAccessors=u,n.canDefineNonEnumerableProperties=l}),e("ember-metal/platform/create",["exports"],function(e){var t;if(!Object.create||Object.create(null).hasOwnProperty){var r,n=!({__proto__:null}instanceof Object);r=n||"undefined"==typeof document?function(){return{__proto__:null}}:function(){function e(){}var t=document.createElement("iframe"),n=document.body||document.documentElement;t.style.display="none",n.appendChild(t),t.src="javascript:";var i=t.contentWindow.Object.prototype;return n.removeChild(t),t=null,delete i.constructor,delete i.hasOwnProperty,delete i.propertyIsEnumerable,delete i.isPrototypeOf,delete i.toLocaleString,delete i.toString,delete i.valueOf,e.prototype=i,r=function(){return new e},new e},t=Object.create=function(e,t){function n(){}var i;if(null===e)i=r();else{if("object"!=typeof e&&"function"!=typeof e)throw new TypeError("Object prototype may only be an Object or null");n.prototype=e,i=new n}return void 0!==t&&Object.defineProperties(i,t),i}}else t=Object.create;e["default"]=t}),e("ember-metal/platform/define_properties",["ember-metal/platform/define_property","exports"],function(e,t){"use strict";var r=e.defineProperty,n=Object.defineProperties;n||(n=function(e,t){for(var n in t)t.hasOwnProperty(n)&&"__proto__"!==n&&r(e,n,t[n]);return e},Object.defineProperties=n),t["default"]=n}),e("ember-metal/platform/define_property",["exports"],function(e){"use strict";var t=function(e){if(e)try{var t=5,r={};if(e(r,"a",{configurable:!0,enumerable:!0,get:function(){return t},set:function(e){t=e}}),5!==r.a)return;if(r.a=10,10!==t)return;e(r,"a",{configurable:!0,enumerable:!1,writable:!0,value:!0});for(var n in r)if("a"===n)return;if(r.a!==!0)return;return e}catch(i){return}}(Object.defineProperty),r=!!t;if(r&&"undefined"!=typeof document){var n=function(){try{return t(document.createElement("div"),"definePropertyOnDOM",{}),!0}catch(e){}return!1}();n||(t=function(e,t,r){var n;return n="object"==typeof Node?e instanceof Node:"object"==typeof e&&"number"==typeof e.nodeType&&"string"==typeof e.nodeName,n?e[t]=r.value:Object.defineProperty(e,t,r)})}r||(t=function(e,t,r){r.get||(e[t]=r.value)}),e.hasES5CompliantDefineProperty=r,e.defineProperty=t}),e("ember-metal/properties",["ember-metal/core","ember-metal/utils","ember-metal/platform","ember-metal/property_events","exports"],function(e,t,r,n,i){"use strict";function a(){}function s(){return function(){}}function o(e){return function(){var t=this.__ember_meta__;return t&&t.values[e]}}function u(e,t,r,n,i){var s,o,u,p;i||(i=l(e)),s=i.descs,o=i.descs[t];var m=i.watching[t];return u=void 0!==m&&m>0,o instanceof a&&o.teardown(e,t),r instanceof a?(p=r,s[t]=r,e[t]=void 0,r.setup&&r.setup(e,t)):(s[t]=void 0,null==r?(p=n,e[t]=n):(p=r,c(e,t,r))),u&&h(e,t,i),e.didDefineProperty&&e.didDefineProperty(e,t,p),this}var l=(e["default"],t.meta),c=r.defineProperty,h=(r.hasPropertyAccessors,n.overrideChains);i.Descriptor=a,i.MANDATORY_SETTER_FUNCTION=s,i.DEFAULT_GETTER_FUNCTION=o,i.defineProperty=u}),e("ember-metal/property_events",["ember-metal/utils","ember-metal/events","ember-metal/observer_set","exports"],function(e,t,r,n){"use strict";function i(e,t){var r=e.__ember_meta__,n=r&&r.watching[t]>0||"length"===t,i=r&&r.proto,a=r&&r.descs[t];n&&i!==e&&(a&&a.willChange&&a.willChange(e,t),s(e,t,r),c(e,t,r),v(e,t)) -}function a(e,t){var r=e.__ember_meta__,n=r&&r.watching[t]>0||"length"===t,i=r&&r.proto,a=r&&r.descs[t];i!==e&&(a&&a.didChange&&a.didChange(e,t),(n||"length"===t)&&(r&&r.deps&&r.deps[t]&&o(e,t,r),h(e,t,r,!1),b(e,t)))}function s(e,t,r){if(!e.isDestroying){var n;if(r&&r.deps&&(n=r.deps[t])){var a=y,s=!a;s&&(a=y={}),l(i,e,n,t,a,r),s&&(y=null)}}}function o(e,t,r){if(!e.isDestroying){var n;if(r&&r.deps&&(n=r.deps[t])){var i=g,s=!i;s&&(i=g={}),l(a,e,n,t,i,r),s&&(g=null)}}}function u(e){var t=[];for(var r in e)t.push(r);return t}function l(e,t,r,n,i,a){var s,o,l,c,h=_(t),p=i[h];if(p||(p=i[h]={}),!p[n]&&(p[n]=!0,r)){s=u(r);var m=a.descs;for(l=0;ln;n++)s[n].willChange(o);for(n=0,a=o.length;a>n;n+=2)i(o[n],o[n+1])}}function h(e,t,r,n){if(r&&r.hasOwnProperty("chainWatchers")&&r.chainWatchers[t]){var i,s,o=r.chainWatchers[t],u=n?null:[];for(i=0,s=o.length;s>i;i++)o[i].didChange(u);if(!n)for(i=0,s=u.length;s>i;i+=2)a(u[i],u[i+1])}}function p(e,t,r){h(e,t,r,!0)}function m(){T++}function f(){T--,0>=T&&(P.clear(),A.flush())}function d(e,t){m(),w(e,f,t)}function v(e,t){if(!e.isDestroying){var r,n,i=t+":before";T?(r=P.add(e,t,i),n=O(e,i,r),x(e,i,[e,t],n)):x(e,i,[e,t])}}function b(e,t){if(!e.isDestroying){var r,n=t+":change";T?(r=A.add(e,t,n),C(e,n,r)):x(e,n,[e,t])}}var y,g,_=e.guidFor,w=e.tryFinally,x=t.sendEvent,C=t.listenersUnion,O=t.listenersDiff,E=r["default"],P=new E,A=new E,T=0;n.propertyWillChange=i,n.propertyDidChange=a,n.overrideChains=p,n.beginPropertyChanges=m,n.endPropertyChanges=f,n.changeProperties=d}),e("ember-metal/property_get",["ember-metal/core","ember-metal/error","ember-metal/path_cache","ember-metal/platform","exports"],function(e,t,r,n,i){"use strict";function a(e,t){var r,n=p(t),i=!n&&c(t);if((!e||i)&&(e=u.lookup),n&&(t=t.slice(5)),e===u.lookup&&(r=t.match(m)[0],e=f(e,r),t=t.slice(r.length+1)),!t||0===t.length)throw new l("Path cannot be empty");return[e,t]}function s(e,t){var r,n,i,s,o;if(null===e&&!h(t))return f(u.lookup,t);for(r=p(t),(!e||r)&&(i=a(e,t),e=i[0],t=i[1],i.length=0),n=t.split("."),o=n.length,s=0;null!=e&&o>s;s++)if(e=f(e,n[s],!0),e&&e.isDestroyed)return void 0;return e}function o(e,t,r){var n=f(e,t);return void 0===n?r:n}var u=e["default"],l=t["default"],c=r.isGlobalPath,h=r.isPath,p=r.hasThis,m=(n.hasPropertyAccessors,/^([^\.]+)/),f=function(e,t){if(""===t)return e;if(t||"string"!=typeof e||(t=e,e=null),null===e){var r=s(e,t);return r}var n,i=e.__ember_meta__,a=i&&i.descs[t];return void 0===a&&h(t)?s(e,t):a?a.get(e,t):(n=e[t],void 0!==n||"object"!=typeof e||t in e||"function"!=typeof e.unknownProperty?n:e.unknownProperty(t))};u.config.overrideAccessors&&(u.get=f,u.config.overrideAccessors(),f=u.get),i.getWithDefault=o,i["default"]=f,i.get=f,i.normalizeTuple=a,i._getPath=s}),e("ember-metal/property_set",["ember-metal/core","ember-metal/property_get","ember-metal/property_events","ember-metal/properties","ember-metal/error","ember-metal/path_cache","ember-metal/platform","exports"],function(e,t,r,n,i,a,s,o){"use strict";function u(e,t,r,n){var i;if(i=t.slice(t.lastIndexOf(".")+1),t=t===i?i:t.slice(0,t.length-(i.length+1)),"this"!==t&&(e=h(e,t)),!i||0===i.length)throw new f("Property set failed: You passed an empty path");if(!e){if(n)return;throw new f('Property set failed: object in path "'+t+'" could not be found or was destroyed.')}return v(e,i,r)}function l(e,t,r){return v(e,t,r,!0)}var c=e["default"],h=t._getPath,p=r.propertyWillChange,m=r.propertyDidChange,f=(n.defineProperty,i["default"]),d=a.isPath,v=(s.hasPropertyAccessors,function(e,t,r,n){if("string"==typeof e&&(r=t,t=e,e=null),!e)return u(e,t,r,n);var i,a,s=e.__ember_meta__,o=s&&s.descs[t];if(void 0===o&&d(t))return u(e,t,r,n);if(void 0!==o)o.set(e,t,r);else{if("object"==typeof e&&null!==e&&void 0!==r&&e[t]===r)return r;i="object"==typeof e&&!(t in e),i&&"function"==typeof e.setUnknownProperty?e.setUnknownProperty(t,r):s&&s.watching[t]>0?(a=e[t],r!==a&&(p(e,t),e[t]=r,m(e,t))):e[t]=r}return r});c.config.overrideAccessors&&(c.set=v,c.config.overrideAccessors(),v=c.set),o.trySet=l,o.set=v}),e("ember-metal/run_loop",["ember-metal/core","ember-metal/utils","ember-metal/array","ember-metal/property_events","backburner","exports"],function(e,t,r,n,i,a){"use strict";function s(e){u.currentRunLoop=e}function o(e,t){u.currentRunLoop=t}function u(){return b.run.apply(b,arguments)}function l(){!u.currentRunLoop}{var c=e["default"],h=t.apply,p=t.GUID_KEY,m=r.indexOf,f=n.beginPropertyChanges,d=n.endPropertyChanges,v=i["default"],b=new v(["sync","actions","destroy"],{GUID_KEY:p,sync:{before:f,after:d},defaultQueue:"actions",onBegin:s,onEnd:o,onErrorTarget:c,onErrorMethod:"onerror"}),y=[].slice;[].concat}a["default"]=u,u.join=function(){if(!u.currentRunLoop)return c.run.apply(c,arguments);var e=y.call(arguments);e.unshift("actions"),u.schedule.apply(u,e)},u.bind=function(){var e=y.call(arguments);return function(){return u.join.apply(u,e.concat(y.call(arguments)))}},u.backburner=b,u.currentRunLoop=null,u.queues=b.queueNames,u.begin=function(){b.begin()},u.end=function(){b.end()},u.schedule=function(){l(),b.schedule.apply(b,arguments)},u.hasScheduledTimers=function(){return b.hasTimers()},u.cancelTimers=function(){b.cancelTimers()},u.sync=function(){b.currentInstance&&b.currentInstance.queues.sync.flush()},u.later=function(){return b.later.apply(b,arguments)},u.once=function(){l();var e=y.call(arguments);return e.unshift("actions"),h(b,b.scheduleOnce,e)},u.scheduleOnce=function(){return l(),b.scheduleOnce.apply(b,arguments)},u.next=function(){var e=y.call(arguments);return e.push(1),h(b,b.later,e)},u.cancel=function(e){return b.cancel(e)},u.debounce=function(){return b.debounce.apply(b,arguments)},u.throttle=function(){return b.throttle.apply(b,arguments)},u._addQueue=function(e,t){-1===m.call(u.queues,e)&&u.queues.splice(m.call(u.queues,t)+1,0,e)}}),e("ember-metal/set_properties",["ember-metal/property_events","ember-metal/property_set","ember-metal/keys","exports"],function(e,t,r,n){"use strict";var i=e.changeProperties,a=t.set,s=r["default"];n["default"]=function(e,t){return t&&"object"==typeof t?(i(function(){for(var r,n=s(t),i=0,o=n.length;o>i;i++)r=n[i],a(e,r,t[r])}),e):e}}),e("ember-metal/utils",["ember-metal/core","ember-metal/platform","ember-metal/array","exports"],function(e,t,r,n){function i(){return++A}function a(e){var t={};t[e]=1;for(var r in t)if(r===e)return r;return e}function s(e,t){t||(t=T);var r=t+i();return e&&(null===e[I]?e[I]=r:(k.value=r,C(e,I,k))),r}function o(e){if(void 0===e)return"(undefined)";if(null===e)return"(null)";var t,r=typeof e;switch(r){case"number":return t=S[e],t||(t=S[e]="nu"+e),t;case"string":return t=V[e],t||(t=V[e]="st"+i()),t;case"boolean":return e?"(true)":"(false)";default:return e[I]?e[I]:e===Object?"(Object)":e===Array?"(Array)":(t=T+i(),null===e[I]?e[I]=t:(k.value=t,C(e,I,k)),t)}}function u(e){this.descs={},this.watching={},this.cache={},this.cacheMeta={},this.source=e}function l(e,t){var r=e.__ember_meta__;return t===!1?r||j:(r?r.source!==e&&(O&&C(e,"__ember_meta__",D),r=N(r),r.descs=N(r.descs),r.watching=N(r.watching),r.cache={},r.cacheMeta={},r.source=e,e.__ember_meta__=r):(O&&C(e,"__ember_meta__",D),r=new u(e),e.__ember_meta__=r,r.descs.constructor=null),r)}function c(e,t){var r=l(e,!1);return r[t]}function h(e,t,r){var n=l(e,!0);return n[t]=r,r}function p(e,t,r){for(var n,i,a=l(e,r),s=0,o=t.length;o>s;s++){if(n=t[s],i=a[n]){if(i.__ember_source__!==e){if(!r)return void 0;i=a[n]=N(i),i.__ember_source__=e}}else{if(!r)return void 0;i=a[n]={__ember_source__:e}}a=i}return i}function m(e,t){function r(){for(var r,n=this&&this.__nextSuper,i=new Array(arguments.length),a=0,s=i.length;s>a;a++)i[a]=arguments[a];return this&&(this.__nextSuper=t),r=_(this,e,i),this&&(this.__nextSuper=n),r}return r.wrappedFunction=e,r.wrappedFunction.__ember_arity__=e.length,r.__ember_observes__=e.__ember_observes__,r.__ember_observesBefore__=e.__ember_observesBefore__,r.__ember_listens__=e.__ember_listens__,r}function f(e){var t,r;return"undefined"==typeof M&&(t="ember-runtime/mixins/array",x.__loader.registry[t]&&(M=x.__loader.require(t)["default"])),!e||e.setInterval?!1:Array.isArray&&Array.isArray(e)?!0:M&&M.detect(e)?!0:(r=y(e),"array"===r?!0:void 0!==e.length&&"object"===r?!0:!1)}function d(e){return null===e||void 0===e?[]:f(e)?e:[e]}function v(e,t){return!(!e||"function"!=typeof e[t])}function b(e,t,r){return v(e,t)?r?w(e,t,r):w(e,t):void 0}function y(e){var t,r;return"undefined"==typeof F&&(r="ember-runtime/system/object",x.__loader.registry[r]&&(F=x.__loader.require(r)["default"])),t=null===e||void 0===e?String(e):z[B.call(e)]||"object","function"===t?F&&F.detect(e)&&(t="class"):"object"===t&&(e instanceof Error?t="error":F&&e instanceof F?t="instance":e instanceof Date&&(t="date")),t}function g(e){var t=y(e);if("array"===t)return"["+e+"]";if("object"!==t)return e+"";var r,n=[];for(var i in e)if(e.hasOwnProperty(i)){if(r=e[i],"toString"===r)continue;"function"===y(r)&&(r="function() { ... }"),n.push(r&&"function"!=typeof r.toString?i+": "+B.call(r):i+": "+r)}return"{"+n.join(", ")+"}"}function _(e,t,r){var n=r&&r.length;if(!r||!n)return t.call(e);switch(n){case 1:return t.call(e,r[0]);case 2:return t.call(e,r[0],r[1]);case 3:return t.call(e,r[0],r[1],r[2]);case 4:return t.call(e,r[0],r[1],r[2],r[3]);case 5:return t.call(e,r[0],r[1],r[2],r[3],r[4]);default:return t.apply(e,r)}}function w(e,t,r){var n=r&&r.length;if(!r||!n)return e[t]();switch(n){case 1:return e[t](r[0]);case 2:return e[t](r[0],r[1]);case 3:return e[t](r[0],r[1],r[2]);case 4:return e[t](r[0],r[1],r[2],r[3]);case 5:return e[t](r[0],r[1],r[2],r[3],r[4]);default:return e[t].apply(e,r)}}var x=e["default"],C=t.defineProperty,O=t.canDefineNonEnumerableProperties,E=(t.hasPropertyAccessors,t.create),P=r.forEach,A=0;n.uuid=i;var T="ember",N=E,S=[],V={},I=a("__ember"+ +new Date),k={writable:!1,configurable:!1,enumerable:!1,value:null};n.generateGuid=s,n.guidFor=o;var D={writable:!0,configurable:!1,enumerable:!1,value:null};u.prototype={descs:null,deps:null,watching:null,listeners:null,cache:null,cacheMeta:null,source:null,mixins:null,bindings:null,chains:null,chainWatchers:null,values:null,proto:null},O||(u.prototype.__preventPlainObject__=!0,u.prototype.toJSON=function(){});var j=new u(null);n.getMeta=c,n.setMeta=h,n.metaPath=p,n.wrap=m;var M;n.makeArray=d,n.tryInvoke=b;var R,L=function(){var e=0;try{try{}finally{throw e++,new Error("needsFinallyFixTest")}}catch(t){}return 1!==e}();R=L?function(e,t,r){var n,i,a;r=r||this;try{n=e.call(r)}finally{try{i=t.call(r)}catch(s){a=s}}if(a)throw a;return void 0===i?n:i}:function(e,t,r){var n,i;r=r||this;try{n=e.call(r)}finally{i=t.call(r)}return void 0===i?n:i};var H;H=L?function(e,t,r,n){var i,a,s;n=n||this;try{i=e.call(n)}catch(o){i=t.call(n,o)}finally{try{a=r.call(n)}catch(u){s=u}}if(s)throw s;return void 0===a?i:a}:function(e,t,r,n){var i,a;n=n||this;try{i=e.call(n)}catch(s){i=t.call(n,s)}finally{a=r.call(n)}return void 0===a?i:a};var z={},q="Boolean Number String Function Array Date RegExp Object".split(" ");P.call(q,function(e){z["[object "+e+"]"]=e.toLowerCase()});var F,B=Object.prototype.toString;n.inspect=g,n.apply=_,n.applyStr=w,n.GUID_KEY=I,n.META_DESC=D,n.EMPTY_META=j,n.meta=l,n.typeOf=y,n.tryCatchFinally=H,n.isArray=f,n.canInvoke=v,n.tryFinally=R}),e("ember-metal/watch_key",["ember-metal/core","ember-metal/utils","ember-metal/platform","ember-metal/properties","exports"],function(e,t,r,n,i){"use strict";function a(e,t,r){if("length"!==t||"array"!==u(e)){var n=r||l(e),i=n.watching;if(i[t])i[t]=(i[t]||0)+1;else{i[t]=1;var a=n.descs[t];a&&a.willWatch&&a.willWatch(e,t),"function"==typeof e.willWatchProperty&&e.willWatchProperty(t)}}}function s(e,t,r){var n=r||l(e),i=n.watching;if(1===i[t]){i[t]=0;var a=n.descs[t];a&&a.didUnwatch&&a.didUnwatch(e,t),"function"==typeof e.didUnwatchProperty&&e.didUnwatchProperty(t)}else i[t]>1&&i[t]--}var o=(e["default"],t.meta),u=t.typeOf,l=(r.defineProperty,r.hasPropertyAccessors,n.MANDATORY_SETTER_FUNCTION,n.DEFAULT_GETTER_FUNCTION,o);i.watchKey=a,i.unwatchKey=s}),e("ember-metal/watch_path",["ember-metal/utils","ember-metal/chains","exports"],function(e,t,r){"use strict";function n(e,t){var r=t||l(e),n=r.chains;return n?n.value()!==e&&(n=r.chains=n.copy(e)):n=r.chains=new u(null,null,e),n}function i(e,t,r){if("length"!==t||"array"!==o(e)){var i=r||l(e),a=i.watching;a[t]?a[t]=(a[t]||0)+1:(a[t]=1,n(e,i).add(t))}}function a(e,t,r){var i=r||l(e),a=i.watching;1===a[t]?(a[t]=0,n(e,i).remove(t)):a[t]>1&&a[t]--}var s=e.meta,o=e.typeOf,u=t.ChainNode,l=s;r.watchPath=i,r.unwatchPath=a}),e("ember-metal/watching",["ember-metal/utils","ember-metal/chains","ember-metal/watch_key","ember-metal/watch_path","ember-metal/path_cache","exports"],function(e,t,r,n,i,a){"use strict";function s(e,t,r){("length"!==t||"array"!==p(e))&&(_(t)?y(e,t,r):v(e,t,r))}function o(e,t){var r=e.__ember_meta__;return(r&&r.watching[t])>0}function u(e,t,r){("length"!==t||"array"!==p(e))&&(_(t)?g(e,t,r):b(e,t,r))}function l(e){var t=e.__ember_meta__,r=t&&t.chains;h in e&&!e.hasOwnProperty(h)&&m(e),r&&r.value()!==e&&(t.chains=r.copy(e))}function c(e){var t,r,n,i,a=e.__ember_meta__;if(a&&(e.__ember_meta__=null,t=a.chains))for(w.push(t);w.length>0;){if(t=w.pop(),r=t._chains)for(n in r)r.hasOwnProperty(n)&&w.push(r[n]);t._watching&&(i=t._object,i&&f(i,t._key,t))}}var h=(e.meta,e.GUID_KEY),p=e.typeOf,m=e.generateGuid,f=t.removeChainWatcher,d=t.flushPendingChains,v=r.watchKey,b=r.unwatchKey,y=n.watchPath,g=n.unwatchPath,_=i.isPath;a.watch=s,a.isWatching=o,s.flushPending=d,a.unwatch=u,a.rewatch=l;var w=[];a.destroy=c}),e("ember-routing-handlebars",["ember-metal/core","ember-handlebars","ember-routing/system/router","ember-routing-handlebars/helpers/shared","ember-routing-handlebars/helpers/link_to","ember-routing-handlebars/helpers/outlet","ember-routing-handlebars/helpers/render","ember-routing-handlebars/helpers/action","exports"],function(e,t,r,n,i,a,s,o,u){"use strict";var l=e["default"],c=t["default"],h=r["default"],p=n.resolvePaths,m=n.resolveParams,f=i.deprecatedLinkToHelper,d=i.linkToHelper,v=i.LinkView,b=i.queryParamsHelper,y=a.outletHelper,g=a.OutletView,_=s["default"],w=o.ActionHelper,x=o.actionHelper;h.resolveParams=m,h.resolvePaths=p,l.LinkView=v,c.ActionHelper=w,c.OutletView=g,c.registerHelper("render",_),c.registerHelper("action",x),c.registerHelper("outlet",y),c.registerHelper("link-to",d),c.registerHelper("linkTo",f),c.registerHelper("query-params",b),u["default"]=l}),e("ember-routing-handlebars/helpers/action",["ember-metal/core","ember-metal/property_get","ember-metal/array","ember-metal/utils","ember-metal/run_loop","ember-views/system/utils","ember-views/system/action_manager","ember-routing/system/router","ember-handlebars","ember-handlebars/ext","ember-handlebars/helpers/view","ember-routing-handlebars/helpers/shared","exports"],function(e,t,r,n,i,a,s,o,u,l,c,h,p){"use strict";function m(e,t){var r=[];t&&r.push(t);var n=e.options.types.slice(1),i=e.options.data;return r.concat(x(e.context,e.params,{types:n,data:i}))}function f(e){var t=arguments[arguments.length-1],r=O.call(arguments,1,-1),n=t.hash,i=t.data.keywords.controller,a={eventName:n.on||"click",parameters:{context:this,options:t,params:r},view:t.data.view,bubbles:n.bubbles,preventDefault:n.preventDefault,target:{options:t},withKeyCode:n.withKeyCode,boundProperty:"ID"===t.types[0]};n.target?(a.target.root=this,a.target.target=n.target):i&&(a.target.root=i);var s=E.registerAction(e,a,n.allowedKeys);return new C('data-ember-action="'+s+'"')}var d=(e["default"],t.get,r.forEach),v=n.uuid,b=i["default"],y=a.isSimpleClick,g=s["default"],_=(o["default"],u["default"]),w=l.handlebarsGet,x=(c.viewHelper,h.resolveParams),C=(h.resolvePath,_.SafeString),O=Array.prototype.slice,E={};E.registeredActions=g.registeredActions,p.ActionHelper=E;var P=["alt","shift","meta","ctrl"],A=/^click|mouse|touch/,T=function(e,t){if("undefined"==typeof t){if(A.test(e.type))return y(e);t=""}if(t.indexOf("any")>=0)return!0;var r=!0;return d.call(P,function(n){e[n+"Key"]&&-1===t.indexOf(n)&&(r=!1)}),r};E.registerAction=function(e,t,r){var n=v();return g.registeredActions[n]={eventName:t.eventName,handler:function(n){if(!T(n,r))return!0;t.preventDefault!==!1&&n.preventDefault(),t.bubbles===!1&&n.stopPropagation();{var i,a=t.target,s=t.parameters;t.eventName}a=a.target?w(a.root,a.target,a.options):a.root,t.boundProperty&&(i=x(s.context,[e],{types:["ID"],data:s.options.data})[0],("undefined"==typeof i||"function"==typeof i)&&(i=e)),i||(i=e),b(function(){a.send?a.send.apply(a,m(s,i)):a[i].apply(a,m(s))})}},t.view.on("willClearRender",function(){delete g.registeredActions[n]}),n},p.actionHelper=f}),e("ember-routing-handlebars/helpers/link_to",["ember-metal/core","ember-metal/property_get","ember-metal/property_set","ember-metal/merge","ember-metal/run_loop","ember-metal/computed","ember-runtime/system/lazy_load","ember-runtime/system/string","ember-runtime/system/object","ember-metal/keys","ember-views/system/utils","ember-views/views/component","ember-handlebars","ember-handlebars/helpers/view","ember-routing/system/router","ember-routing-handlebars/helpers/shared","exports"],function(e,r,n,i,a,s,o,u,l,c,h,p,m,f,d,v,b){"use strict";function y(e){var t=e.options.types,r=e.options.data;return R(e.context,e.params,{types:t,data:r})}function g(){var e=H.call(arguments,-1)[0],t=H.call(arguments,0,-1),r=e.hash;if(t[t.length-1]instanceof q&&(r.queryParamsObject=t.pop()),r.disabledBinding=r.disabledWhen,!e.fn){var n=t.shift(),i=e.types.shift(),a=this;"ID"===i?(e.linkTextPath=n,e.fn=function(){return D.getEscaped(a,n,e)}):e.fn=function(){return n}}return r.parameters={context:this,options:e,params:t},e.helperName=e.helperName||"link-to",j.call(this,F,e)}function _(e){return q.create({values:e.hash,types:e.hashTypes})}function w(){return g.apply(this,arguments)}function x(e){var t=e.parameters,r=e.queryParamsObject,n={};if(!r)return n;var i=r.values;for(var a in i)if(i.hasOwnProperty(a)){var s=i[a],o=r.types[a];if("ID"===o){var u=C(s,t);s=D.get(u.root,u.path,t.options)}n[a]=s}return n}function C(e,t){return D.normalizePath(t.context,e,t.options.data)}function O(e){for(var t=0,r=e.length;r>t;++t){var n=e[t];if(null===n||"undefined"==typeof n)return!1}return!0}function E(e,t){var r;for(r in e)if(e.hasOwnProperty(r)&&e[r]!==t[r])return!1;for(r in t)if(t.hasOwnProperty(r)&&e[r]!==t[r])return!1;return!0}var P=e["default"],A=r.get,T=(n.set,i["default"]),N=a["default"],S=s.computed,V=(o.onLoad,u.fmt,l["default"]),I=(c["default"],h.isSimpleClick),k=p["default"],D=m["default"],j=f.viewHelper,M=(d["default"],v.resolveParams),R=v.resolvePaths,L=v.routeArgs,H=[].slice;t("ember-handlebars");var z=function(e,t){for(var r=0,n=0,i=t.length;i>n&&(r+=t[n].names.length,t[n].handler!==e);n++);return r},q=V.extend({values:null}),F=P.LinkView=k.extend({tagName:"a",currentWhen:null,"current-when":null,title:null,rel:null,activeClass:"active",loadingClass:"loading",disabledClass:"disabled",_isDisabled:!1,replace:!1,attributeBindings:["href","title","rel","tabindex"],classNameBindings:["active","loading","disabled"],eventName:"click",init:function(){this._super.apply(this,arguments);var e=A(this,"eventName");this.on(e,this,this._invoke)},_paramsChanged:function(){this.notifyPropertyChange("resolvedParams")},_setupPathObservers:function(){var e,t,r,n=this.parameters,i=n.options.linkTextPath,a=y(n),s=a.length;for(i&&(r=C(i,n),this.registerObserver(r.root,r.path,this,this.rerender)),t=0;s>t;t++)e=a[t],null!==e&&(r=C(e,n),this.registerObserver(r.root,r.path,this,this._paramsChanged));var o=this.queryParamsObject;if(o){var u=o.values;for(var l in u)u.hasOwnProperty(l)&&"ID"===o.types[l]&&(r=C(u[l],n),this.registerObserver(r.root,r.path,this,this._paramsChanged))}},afterRender:function(){this._super.apply(this,arguments),this._setupPathObservers()},disabled:S(function(e,t){return void 0!==t&&this.set("_isDisabled",t),t?A(this,"disabledClass"):!1}),active:S("loadedParams",function(){function e(e){var i=t.router.recognizer.handlersFor(e),s=i[i.length-1].handler,o=z(e,i);n.length>o&&(e=s);var u=L(e,n,null),l=t.isActive.apply(t,u);if(!l)return!1;var c=P.isEmpty(P.keys(r.queryParams));if(!a&&!c&&l){var h={};T(h,r.queryParams),t._prepareQueryParams(r.targetRouteName,r.models,h),l=E(h,t.router.state.queryParams)}return l}if(A(this,"loading"))return!1;var t=A(this,"router"),r=A(this,"loadedParams"),n=r.models,i=this["current-when"]||this.currentWhen,a=Boolean(i);i=i||r.targetRouteName,i=i.split(" ");for(var s=0,o=i.length;o>s;s++)if(e(i[s]))return A(this,"activeClass")}),loading:S("loadedParams",function(){return A(this,"loadedParams")?void 0:A(this,"loadingClass")}),router:S(function(){var e=A(this,"controller");return e&&e.container?e.container.lookup("router:main"):void 0}),_invoke:function(e){if(!I(e))return!0;if(this.preventDefault!==!1){var t=A(this,"target");t&&"_self"!==t||e.preventDefault()}if(this.bubbles===!1&&e.stopPropagation(),A(this,"_isDisabled"))return!1;if(A(this,"loading"))return P.Logger.warn("This link-to is in an inactive loading state because at least one of its parameters presently has a null/undefined value, or the provided route name is invalid."),!1;var r=A(this,"target");if(r&&"_self"!==r)return!1;var n=A(this,"router"),i=A(this,"loadedParams"),a=n._doTransition(i.targetRouteName,i.models,i.queryParams);A(this,"replace")&&a.method("replace");var s=L(i.targetRouteName,i.models,a.state.queryParams),o=n.router.generate.apply(n.router,s);N.scheduleOnce("routerTransitions",this,this._eagerUpdateUrl,a,o)},_eagerUpdateUrl:function(e,t){if(e.isActive&&e.urlMethod){0===t.indexOf("#")&&(t=t.slice(1));var r=A(this,"router.router");"update"===e.urlMethod?r.updateURL(t):"replace"===e.urlMethod&&r.replaceURL(t),e.method(null)}},resolvedParams:S("router.url",function(){var e,t,r=this.parameters,n=r.options,i=n.types,a=n.data,s=0===r.params.length;if(s){var o=this.container.lookup("controller:application");e=A(o,"currentRouteName"),t=[]}else t=M(r.context,r.params,{types:i,data:a}),e=t.shift();var u=x(this,e);return{targetRouteName:e,models:t,queryParams:u}}),loadedParams:S("resolvedParams",function(){var e=A(this,"router");if(e){var t=A(this,"resolvedParams"),r=t.targetRouteName;if(r&&O(t.models))return t}}),queryParamsObject:null,href:S("loadedParams",function(){if("a"===A(this,"tagName")){var e=A(this,"router"),t=A(this,"loadedParams");if(!t)return A(this,"loadingHref");var r={};T(r,t.queryParams),e._prepareQueryParams(t.targetRouteName,t.models,r);var n=L(t.targetRouteName,t.models,r),i=e.generate.apply(e,n);return i}}),loadingHref:"#"});F.toString=function(){return"LinkView"},F.reopen({attributeBindings:["target"],target:null}),b.queryParamsHelper=_,b.LinkView=F,b.deprecatedLinkToHelper=w,b.linkToHelper=g}),e("ember-routing-handlebars/helpers/outlet",["ember-metal/core","ember-metal/property_get","ember-metal/property_set","ember-runtime/system/lazy_load","ember-views/views/container_view","ember-handlebars/views/metamorph_view","ember-handlebars/helpers/view","exports"],function(e,t,r,n,i,a,s,o){"use strict";function u(e,t){var r,n,i,a,s;for(e&&e.data&&e.data.isRenderData&&(t=e,e="main"),n=t.data.view.container,r=t.data.view;!r.get("template.isTop");)r=r.get("_parentView");return i=t.hash.view,i&&(s="view:"+i),a=i?n.lookupFactory(s):t.hash.viewClass||p,t.data.view.set("outletSource",r),t.hash.currentViewBinding="_view.outletSource._outlets."+e,t.helperName=t.helperName||"outlet",h.call(this,a,t)}var l=(e["default"],t.get,r.set,n.onLoad,i["default"]),c=a._Metamorph,h=s.viewHelper,p=l.extend(c);o.OutletView=p,o.outletHelper=u}),e("ember-routing-handlebars/helpers/render",["ember-metal/core","ember-metal/error","ember-metal/property_get","ember-metal/property_set","ember-runtime/system/string","ember-routing/system/generate_controller","ember-handlebars/ext","ember-handlebars/helpers/view","exports"],function(e,t,r,n,i,a,s,o,u){"use strict";var l=(e["default"],t["default"]),c=(r.get,n.set,i.camelize),h=a.generateControllerFactory,p=a["default"],m=s.handlebarsGet,f=o.ViewHelper;u["default"]=function(e,t,r){var n,i,a,s,o,u=arguments.length;if(n=(r||t).data.keywords.controller.container,i=n.lookup("router:main"),2===u)r=t,t=void 0;else{if(3!==u)throw new l("You must pass a templateName to render");o=m(r.contexts[1],t,r)}e=e.replace(/\//g,"."),s=n.lookup("view:"+e)||n.lookup("view:default");var d=r.hash.controller||e,v="controller:"+d;r.hash.controller;var b=r.data.keywords.controller;if(u>2){var y=n.lookupFactory(v)||h(n,d,o);a=y.create({model:o,parentController:b,target:b}),s.one("willDestroyElement",function(){a.destroy()})}else a=n.lookup(v)||p(n,d),a.setProperties({target:b,parentController:b});var g=r.contexts[1];g&&s.registerObserver(g,t,function(){a.set("model",m(g,t,r))}),r.hash.viewName=c(e);var _="template:"+e;r.hash.template=n.lookup(_),r.hash.controller=a,i&&!o&&i._connectActiveView(e,s),r.helperName=r.helperName||'render "'+e+'"',f.instanceHelper(this,s,r)}}),e("ember-routing-handlebars/helpers/shared",["ember-metal/property_get","ember-metal/array","ember-runtime/mixins/controller","ember-handlebars/ext","ember-metal/utils","exports"],function(e,t,r,n,i,a){"use strict";function s(e,t,r){var n=[];return"string"===v(e)&&n.push(""+e),n.push.apply(n,t),n.push({queryParams:r}),n}function o(e){var t=e.activeTransition?e.activeTransition.state.handlerInfos:e.state.handlerInfos;return t[t.length-1].name}function u(e,t,r){return p.call(c(e,t,r),function(n,i){return null===n?t[i]:d(e,n,r)})}function l(e,t){if(!t._namesStashed){for(var r=t[t.length-1].name,n=e.router.recognizer.handlersFor(r),i=null,a=0,s=t.length;s>a;++a){var o=t[a],u=n[a].names;u.length&&(i=o),o._names=u;var l=o.handler;l._stashNames(o,i)}t._namesStashed=!0}}function c(e,t,r){function n(e,t){return"controller"===t?t:m.detect(e)?n(h(e,"model"),t?t+".model":"model"):t}var i=f(e,t,r),a=r.types;return p.call(i,function(e,r){return"ID"===a[r]?n(e,t[r]):null})}var h=e.get,p=t.map,m=r["default"],f=n.resolveParams,d=n.handlebarsGet,v=i.typeOf,h=e.get;a.routeArgs=s,a.getActiveTargetName=o,a.resolveParams=u,a.stashParamNames=l,a.resolvePaths=c}),e("ember-routing",["ember-handlebars","ember-metal/core","ember-routing/ext/run_loop","ember-routing/ext/controller","ember-routing/ext/view","ember-routing/location/api","ember-routing/location/none_location","ember-routing/location/hash_location","ember-routing/location/history_location","ember-routing/location/auto_location","ember-routing/system/generate_controller","ember-routing/system/controller_for","ember-routing/system/dsl","ember-routing/system/router","ember-routing/system/route","exports"],function(e,t,r,n,i,a,s,o,u,l,c,h,p,m,f,d){"use strict";var v=(e["default"],t["default"]),b=a["default"],y=s["default"],g=o["default"],_=u["default"],w=l["default"],x=c.generateControllerFactory,C=c["default"],O=h["default"],E=p["default"],P=m["default"],A=f["default"];v.Location=b,v.AutoLocation=w,v.HashLocation=g,v.HistoryLocation=_,v.NoneLocation=y,v.controllerFor=O,v.generateControllerFactory=x,v.generateController=C,v.RouterDSL=E,v.Router=P,v.Route=A,d["default"]=v}),e("ember-routing/ext/controller",["ember-metal/core","ember-metal/property_get","ember-metal/property_set","ember-metal/computed","ember-metal/utils","ember-metal/merge","ember-metal/enumerable_utils","ember-runtime/mixins/controller","exports"],function(e,t,r,n,i,a,s,o,u){"use strict";function l(e,t){var r,n=e;"string"===f(n)&&(r={},r[n]={as:null},n=r);for(var i in n){if(!n.hasOwnProperty(i))return;var a=n[i];"string"===f(a)&&(a={as:a}),r=t[i]||{as:null,scope:"model"},v(r,a),t[i]=r}}function c(e){var t=h(e,"_normalizedQueryParams");for(var r in t)t.hasOwnProperty(r)&&e.addObserver(r+".[]",e,e._qpChanged)}var h=(e["default"],t.get),p=r.set,m=n.computed,f=i.typeOf,d=i.meta,v=a["default"],b=(s.map,o["default"]);b.reopen({concatenatedProperties:["queryParams","_pCacheMeta"],init:function(){this._super.apply(this,arguments),c(this)},queryParams:null,_qpDelegate:null,_normalizedQueryParams:m(function(){var e=d(this);if(e.proto!==this)return h(e.proto,"_normalizedQueryParams");var t=h(this,"queryParams");if(t._qpMap)return t._qpMap;for(var r=t._qpMap={},n=0,i=t.length;i>n;++n)l(t[n],r);return r}),_cacheMeta:m(function(){var e=d(this);if(e.proto!==this)return h(e.proto,"_cacheMeta");var t={},r=h(this,"_normalizedQueryParams");for(var n in r)if(r.hasOwnProperty(n)){var i,a=r[n],s=a.scope;"controller"===s&&(i=[]),t[n]={parts:i,values:null,scope:s,prefix:"",def:h(this,n)}}return t}),_updateCacheParams:function(e){var t=h(this,"_cacheMeta");for(var r in t)if(t.hasOwnProperty(r)){var n=t[r];n.values=e;var i=this._calculateCacheKey(n.prefix,n.parts,n.values),a=this._bucketCache;if(a){var s=a.lookup(i,r,n.def);p(this,r,s)}}},_qpChanged:function(e,t){var r=t.substr(0,t.length-3),n=h(e,"_cacheMeta"),i=n[r],a=e._calculateCacheKey(i.prefix||"",i.parts,i.values),s=h(e,r),o=this._bucketCache;o&&e._bucketCache.stash(a,r,s);var u=e._qpDelegate;u&&u(e,r)},_calculateCacheKey:function(e,t,r){for(var n=t||[],i="",a=0,s=n.length;s>a;++a){var o=n[a],u=h(r,o);i+="::"+o+":"+u}return e+i.replace(y,"-")},transitionToRoute:function(){var e=h(this,"target"),t=e.transitionToRoute||e.transitionTo;return t.apply(e,arguments)},transitionTo:function(){return this.transitionToRoute.apply(this,arguments)},replaceRoute:function(){var e=h(this,"target"),t=e.replaceRoute||e.replaceWith;return t.apply(e,arguments)},replaceWith:function(){return this.replaceRoute.apply(this,arguments)}});var y=/\./g;u["default"]=b}),e("ember-routing/ext/run_loop",["ember-metal/run_loop"],function(e){"use strict";{var t=e["default"];t.queues}t._addQueue("routerTransitions","actions")}),e("ember-routing/ext/view",["ember-metal/property_get","ember-metal/property_set","ember-metal/run_loop","ember-views/views/view","exports"],function(e,t,r,n,i){"use strict";var a=e.get,s=t.set,o=r["default"],u=n["default"];u.reopen({init:function(){s(this,"_outlets",{}),this._super()},connectOutlet:function(e,t){if(this._pendingDisconnections&&delete this._pendingDisconnections[e],this._hasEquivalentView(e,t))return void t.destroy();var r=a(this,"_outlets"),n=a(this,"container"),i=n&&n.lookup("router:main"),o=a(t,"renderedName");s(r,e,t),i&&o&&i._connectActiveView(o,t)},_hasEquivalentView:function(e,t){var r=a(this,"_outlets."+e);return r&&r.constructor===t.constructor&&r.get("template")===t.get("template")&&r.get("context")===t.get("context")},disconnectOutlet:function(e){this._pendingDisconnections||(this._pendingDisconnections={}),this._pendingDisconnections[e]=!0,o.once(this,"_finishDisconnections")},_finishDisconnections:function(){if(!this.isDestroyed){var e=a(this,"_outlets"),t=this._pendingDisconnections;this._pendingDisconnections=null;for(var r in t)s(e,r,null)}}}),i["default"]=u}),e("ember-routing/location/api",["ember-metal/core","ember-metal/property_get","ember-metal/property_set","exports"],function(e,t,r,n){"use strict";e["default"],t.get,r.set;n["default"]={create:function(e){var t=e&&e.implementation,r=this.implementations[t];return r.create.apply(r,arguments)},registerImplementation:function(e,t){this.implementations[e]=t},implementations:{},_location:window.location,_getHash:function(){var e=(this._location||this.location).href,t=e.indexOf("#");return-1===t?"":e.substr(t)}}}),e("ember-routing/location/auto_location",["ember-metal/core","ember-metal/property_get","ember-metal/property_set","ember-routing/location/api","ember-routing/location/history_location","ember-routing/location/hash_location","ember-routing/location/none_location","exports"],function(e,t,r,n,i,a,s,o){"use strict";var u=(e["default"],t.get,r.set),l=n["default"],c=i["default"],h=a["default"],p=s["default"];o["default"]={cancelRouterSetup:!1,rootURL:"/",_window:window,_location:window.location,_history:window.history,_HistoryLocation:c,_HashLocation:h,_NoneLocation:p,_getOrigin:function(){var e=this._location,t=e.origin; -return t||(t=e.protocol+"//"+e.hostname,e.port&&(t+=":"+e.port)),t},_getSupportsHistory:function(){var e=this._window.navigator.userAgent;return-1!==e.indexOf("Android 2")&&-1!==e.indexOf("Mobile Safari")&&-1===e.indexOf("Chrome")?!1:!!(this._history&&"pushState"in this._history)},_getSupportsHashChange:function(){var e=this._window,t=e.document.documentMode;return"onhashchange"in e&&(void 0===t||t>7)},_replacePath:function(e){this._location.replace(this._getOrigin()+e)},_getRootURL:function(){return this.rootURL},_getPath:function(){var e=this._location.pathname;return"/"!==e.charAt(0)&&(e="/"+e),e},_getHash:l._getHash,_getQuery:function(){return this._location.search},_getFullPath:function(){return this._getPath()+this._getQuery()+this._getHash()},_getHistoryPath:function(){{var e,t,r=this._getRootURL(),n=this._getPath(),i=this._getHash(),a=this._getQuery();n.indexOf(r)}return"#/"===i.substr(0,2)?(t=i.substr(1).split("#"),e=t.shift(),"/"===n.slice(-1)&&(e=e.substr(1)),n+=e,n+=a,t.length&&(n+="#"+t.join("#"))):(n+=a,n+=i),n},_getHashPath:function(){var e=this._getRootURL(),t=e,r=this._getHistoryPath(),n=r.substr(e.length);return""!==n&&("/"!==n.charAt(0)&&(n="/"+n),t+="#"+n),t},create:function(e){e&&e.rootURL&&(this.rootURL=e.rootURL);var t,r,n=!1,i=this._NoneLocation,a=this._getFullPath();this._getSupportsHistory()?(t=this._getHistoryPath(),a===t?i=this._HistoryLocation:"/#"===a.substr(0,2)?(this._history.replaceState({path:t},null,t),i=this._HistoryLocation):(n=!0,this._replacePath(t))):this._getSupportsHashChange()&&(r=this._getHashPath(),a===r||"/"===a&&"/#/"===r?i=this._HashLocation:(n=!0,this._replacePath(r)));var s=i.create.apply(i,arguments);return n&&u(s,"cancelRouterSetup",!0),s}}}),e("ember-routing/location/hash_location",["ember-metal/core","ember-metal/property_get","ember-metal/property_set","ember-metal/run_loop","ember-metal/utils","ember-runtime/system/object","ember-routing/location/api","exports"],function(e,t,r,n,i,a,s,o){"use strict";var u=e["default"],l=t.get,c=r.set,h=n["default"],p=i.guidFor,m=a["default"],f=s["default"];o["default"]=m.extend({implementation:"hash",init:function(){c(this,"location",l(this,"_location")||window.location)},getHash:f._getHash,getURL:function(){var e=this.getHash().substr(1);return e},setURL:function(e){l(this,"location").hash=e,c(this,"lastSetURL",e)},replaceURL:function(e){l(this,"location").replace("#"+e),c(this,"lastSetURL",e)},onUpdateURL:function(e){var t=this,r=p(this);u.$(window).on("hashchange.ember-location-"+r,function(){h(function(){var r=t.getURL();l(t,"lastSetURL")!==r&&(c(t,"lastSetURL",null),e(r))})})},formatURL:function(e){return"#"+e},willDestroy:function(){var e=p(this);u.$(window).off("hashchange.ember-location-"+e)}})}),e("ember-routing/location/history_location",["ember-metal/core","ember-metal/property_get","ember-metal/property_set","ember-metal/utils","ember-runtime/system/object","ember-views/system/jquery","exports"],function(e,t,r,n,i,a,s){"use strict";var o=(e["default"],t.get),u=r.set,l=n.guidFor,c=i["default"],h=a["default"],p=!1,m=window.history&&"state"in window.history;s["default"]=c.extend({implementation:"history",init:function(){u(this,"location",o(this,"location")||window.location),u(this,"baseURL",h("base").attr("href")||"")},initState:function(){u(this,"history",o(this,"history")||window.history),this.replaceState(this.formatURL(this.getURL()))},rootURL:"/",getURL:function(){var e=o(this,"rootURL"),t=o(this,"location"),r=t.pathname,n=o(this,"baseURL");e=e.replace(/\/$/,""),n=n.replace(/\/$/,"");var i=r.replace(n,"").replace(e,""),a=t.search||"";return i+=a},setURL:function(e){var t=this.getState();e=this.formatURL(e),t&&t.path===e||this.pushState(e)},replaceURL:function(e){var t=this.getState();e=this.formatURL(e),t&&t.path===e||this.replaceState(e)},getState:function(){return m?o(this,"history").state:this._historyState},pushState:function(e){var t={path:e};o(this,"history").pushState(t,null,e),m||(this._historyState=t),this._previousURL=this.getURL()},replaceState:function(e){var t={path:e};o(this,"history").replaceState(t,null,e),m||(this._historyState=t),this._previousURL=this.getURL()},onUpdateURL:function(e){var t=l(this),r=this;h(window).on("popstate.ember-location-"+t,function(){(p||(p=!0,r.getURL()!==r._previousURL))&&e(r.getURL())})},formatURL:function(e){var t=o(this,"rootURL"),r=o(this,"baseURL");return""!==e?(t=t.replace(/\/$/,""),r=r.replace(/\/$/,"")):r.match(/^\//)&&t.match(/^\//)&&(r=r.replace(/\/$/,"")),r+t+e},willDestroy:function(){var e=l(this);h(window).off("popstate.ember-location-"+e)}})}),e("ember-routing/location/none_location",["ember-metal/property_get","ember-metal/property_set","ember-runtime/system/object","exports"],function(e,t,r,n){"use strict";var i=e.get,a=t.set,s=r["default"];n["default"]=s.extend({implementation:"none",path:"",getURL:function(){return i(this,"path")},setURL:function(e){a(this,"path",e)},onUpdateURL:function(e){this.updateCallback=e},handleURL:function(e){a(this,"path",e),this.updateCallback(e)},formatURL:function(e){return e}})}),e("ember-routing/system/cache",["ember-runtime/system/object","exports"],function(e,t){"use strict";var r=e["default"];t["default"]=r.extend({init:function(){this.cache={}},has:function(e){return e in this.cache},stash:function(e,t,r){var n=this.cache[e];n||(n=this.cache[e]={}),n[t]=r},lookup:function(e,t,r){var n=this.cache;if(!(e in n))return r;var i=n[e];return t in i?i[t]:r},cache:null})}),e("ember-routing/system/controller_for",["exports"],function(e){"use strict";e["default"]=function(e,t,r){return e.lookup("controller:"+t,r)}}),e("ember-routing/system/dsl",["ember-metal/core","exports"],function(e,t){"use strict";function r(e){this.parent=e,this.matches=[]}function n(e){return e.parent&&"application"!==e.parent}function i(e,t,r){r=r||{},"string"!=typeof r.path&&(r.path="/"+t),n(e)&&r.resetNamespace!==!0&&(t=e.parent+"."+t),e.push(r.path,t,null)}e["default"];t["default"]=r,r.prototype={route:function(e,t,a){2===arguments.length&&"function"==typeof t&&(a=t,t={}),1===arguments.length&&(t={});t.resetNamespace===!0?"resource":"route";if("string"!=typeof t.path&&(t.path="/"+e),n(this)&&t.resetNamespace!==!0&&(e=this.parent+"."+e),a){var s=new r(e);i(s,"loading"),i(s,"error",{path:"/_unused_dummy_error_path_route_"+e+"/:error"}),a&&a.call(s),this.push(t.path,e,s.generate())}else this.push(t.path,e,null)},push:function(e,t,r){var n=t.split(".");(""===e||"/"===e||"index"===n[n.length-1])&&(this.explicitIndex=!0),this.matches.push([e,t,r])},resource:function(e,t,r){2===arguments.length&&"function"==typeof t&&(r=t,t={}),1===arguments.length&&(t={}),t.resetNamespace=!0,this.route(e,t,r)},generate:function(){var e=this.matches;return this.explicitIndex||i(this,"index",{path:"/"}),function(t){for(var r=0,n=e.length;n>r;r++){var i=e[r];t(i[0]).to(i[1],i[2])}}}},r.map=function(e){var t=new r;return e.call(t),t}}),e("ember-routing/system/generate_controller",["ember-metal/core","ember-metal/property_get","ember-metal/utils","exports"],function(e,t,r,n){"use strict";function i(e,t,r){var n,i,a,o;return o=r&&s(r)?"array":r?"object":"basic",a="controller:"+o,n=e.lookupFactory(a).extend({isGenerated:!0,toString:function(){return"(generated "+t+" controller)"}}),i="controller:"+t,e.register(i,n),n}var a=(e["default"],t.get),s=r.isArray;n.generateControllerFactory=i,n["default"]=function(e,t,r){i(e,t,r);var n="controller:"+t,s=e.lookup(n);return a(s,"namespace.LOG_ACTIVE_GENERATION"),s}}),e("ember-routing/system/route",["ember-metal/core","ember-metal/error","ember-metal/property_get","ember-metal/property_set","ember-metal/get_properties","ember-metal/enumerable_utils","ember-metal/is_none","ember-metal/computed","ember-metal/merge","ember-metal/utils","ember-metal/run_loop","ember-metal/keys","ember-runtime/copy","ember-runtime/system/string","ember-runtime/system/object","ember-runtime/mixins/action_handler","ember-routing/system/generate_controller","ember-routing-handlebars/helpers/shared","exports"],function(e,t,r,n,i,a,s,o,u,l,c,h,p,m,f,d,v,b,y){"use strict";function g(e){var t=_(e,e.router.router.state.handlerInfos,-1);return t&&t.handler}function _(e,t,r){if(t)for(var n,i=r||0,a=0,s=t.length;s>a;a++)if(n=t[a].handler,n===e)return t[a+i]}function w(e){var t,r=g(e);if(r)return(t=r.lastRenderedTemplate)?t:w(r)}function x(e,t,r,n){n=n||{},n.into=n.into?n.into.replace(/\//g,"."):w(e),n.outlet=n.outlet||"main",n.name=t,n.template=r,n.LOG_VIEW_LOOKUPS=I(e.router,"namespace.LOG_VIEW_LOOKUPS");var i=n.controller,a=n.model;if(i=n.controller?n.controller:n.namePassed?e.container.lookup("controller:"+t)||e.controllerName||e.routeName:e.controllerName||e.container.lookup("controller:"+t),"string"==typeof i){var s=i;if(i=e.container.lookup("controller:"+s),!i)throw new V("You passed `controller: '"+s+"'` into the `render` method, but no such controller could be found.")}return a&&i.set("model",a),n.controller=i,n}function C(e,t,r){if(e)r.LOG_VIEW_LOOKUPS;else{var n=r.into?"view:default":"view:toplevel";e=t.lookup(n),r.LOG_VIEW_LOOKUPS}return I(e,"templateName")||(k(e,"template",r.template),k(e,"_debugTemplateName",r.name)),k(e,"renderedName",r.name),k(e,"controller",r.controller),e}function O(e,t,r){if(r.into){var n=e.router._lookupActiveView(r.into),i=P(n,r.outlet);e.teardownOutletViews||(e.teardownOutletViews=[]),M(e.teardownOutletViews,0,0,[i]),n.connectOutlet(r.outlet,t)}else{var a=I(e,"router.namespace.rootElement");e.teardownTopLevelView&&e.teardownTopLevelView(),e.router._connectActiveView(r.name,t),e.teardownTopLevelView=E(t),t.appendTo(a)}}function E(e){return function(){e.destroy()}}function P(e,t){return function(){e.disconnectOutlet(t)}}function A(e,t){if(t.fullQueryParams)return t.fullQueryParams;t.fullQueryParams={},L(t.fullQueryParams,t.queryParams);var r=t.handlerInfos[t.handlerInfos.length-1].name;return e._deserializeQueryParams(r,t.fullQueryParams),t.fullQueryParams}function T(e,t){t.queryParamsFor=t.queryParamsFor||{};var r=e.routeName;if(t.queryParamsFor[r])return t.queryParamsFor[r];for(var n=A(e.router,t),i=t.queryParamsFor[r]={},a=I(e,"_qp"),s=a.qps,o=0,u=s.length;u>o;++o){var l=s[o],c=l.prop in n;i[l.prop]=c?n[l.prop]:N(l.def)}return i}function N(e){return H(e)?S.A(e.slice()):e}var S=e["default"],V=t["default"],I=r.get,k=n.set,D=i["default"],j=a.forEach,M=a.replace,R=(s.isNone,o.computed),L=u["default"],H=l.isArray,z=l.typeOf,q=c["default"],F=h["default"],B=p["default"],U=(m.classify,m.fmt,f["default"]),K=d["default"],W=v["default"],G=b.stashParamNames,Q=U.extend(K,{queryParams:{},_qp:R(function(){var e=this.controllerName||this.routeName,t=this.container.lookupFactory("controller:"+e);if(!t)return $;var r=t.proto(),n=I(r,"_normalizedQueryParams"),i=I(r,"_cacheMeta"),a=[],s={},o=this;for(var u in n)if(n.hasOwnProperty(u)){var l=n[u],c=l.as||this.serializeQueryParamKey(u),h=I(r,u);H(h)&&(h=S.A(h.slice()));var p=z(h),m=this.serializeQueryParam(h,c,p),f=e+":"+u,d={def:h,sdef:m,type:p,urlKey:c,prop:u,fprop:f,ctrl:e,cProto:r,svalue:m,cacheType:l.scope,route:this,cacheMeta:i[u]};s[u]=s[c]=s[f]=d,a.push(d)}return{qps:a,map:s,states:{active:function(e,t){return o._activeQPChanged(e,s[t])},allowOverrides:function(e,t){return o._updatingQPChanged(e,s[t])},changingKeys:function(e,t){return o._updateSerializedQPValue(e,s[t])}}}}),_names:null,_stashNames:function(e,t){var r=e;if(!this._names){var n=this._names=r._names;n.length||(r=t,n=r&&r._names||[]);for(var i=I(this,"_qp.qps"),a=i.length,s=new Array(n.length),o=0,u=n.length;u>o;++o)s[o]=r.name+"."+n[o];for(var l=0;a>l;++l){var c=i[l],h=c.cacheMeta;"model"===h.scope&&(h.parts=s),h.prefix=c.ctrl}}},_updateSerializedQPValue:function(e,t){var r=I(e,t.prop);t.svalue=this.serializeQueryParam(r,t.urlKey,t.type)},_activeQPChanged:function(e,t){var r=I(e,t.prop);this.router._queuedQPChanges[t.fprop]=r,q.once(this,this._fireQueryParamTransition)},_updatingQPChanged:function(e,t){var r=this.router;r._qpUpdates||(r._qpUpdates={}),r._qpUpdates[t.urlKey]=!0},mergedProperties:["events","queryParams"],paramsFor:function(e){var t=this.container.lookup("route:"+e);if(!t)return{};var r=this.router.router.activeTransition,n=r?r.state:this.router.router.state,i={};return L(i,n.params[e]),L(i,T(t,n)),i},serializeQueryParamKey:function(e){return e},serializeQueryParam:function(e,t,r){return"array"===r?JSON.stringify(e):""+e},deserializeQueryParam:function(e,t,r){return"boolean"===r?"true"===e?!0:!1:"number"===r?Number(e).valueOf():"array"===r?S.A(JSON.parse(e)):e},_fireQueryParamTransition:function(){this.transitionTo({queryParams:this.router._queuedQPChanges}),this.router._queuedQPChanges={}},resetController:S.K,exit:function(){this.deactivate(),this.teardownViews()},_reset:function(e,t){var r=this.controller;r._qpDelegate=I(this,"_qp.states.inactive"),this.resetController(r,e,t)},enter:function(){this.activate()},viewName:null,templateName:null,controllerName:null,_actions:{queryParamsDidChange:function(e,t,r){for(var n=F(e).concat(F(r)),i=0,a=n.length;a>i;++i){var s=n[i],o=I(this.queryParams,s)||{};I(o,"refreshModel")&&this.refresh()}return!0},finalizeQueryParamChange:function(e,t,r){if("application"!==this.routeName)return!0;if(r){var n,i=r.state.handlerInfos,a=this.router,s=a._queryParamsFor(i[i.length-1].name),o=a._qpUpdates;G(a,i);for(var u=0,l=s.qps.length;l>u;++u){var c,h,p=s.qps[u],m=p.route,f=m.controller,d=p.urlKey in e&&p.urlKey;o&&p.urlKey in o?(c=I(f,p.prop),h=m.serializeQueryParam(c,p.urlKey,p.type)):d?(h=e[d],c=m.deserializeQueryParam(h,p.urlKey,p.type)):(h=p.sdef,c=N(p.def)),f._qpDelegate=I(this,"_qp.states.inactive");var v=h!==p.svalue;if(v){var b=I(m,"queryParams."+p.urlKey)||{};if(r.queryParamsOnly&&n!==!1){var y=I(b,"replace");y?n=!0:y===!1&&(n=!1)}k(f,p.prop,c)}p.svalue=h;var g=p.sdef===h;g||t.push({value:h,visible:!0,key:d||p.urlKey})}n&&r.method("replace"),j(s.qps,function(e){var t=I(e.route,"_qp"),r=e.route.controller;r._qpDelegate=I(t,"states.active")}),a._qpUpdates=null}}},events:null,deactivate:S.K,activate:S.K,transitionTo:function(){var e=this.router;return e.transitionTo.apply(e,arguments)},intermediateTransitionTo:function(){var e=this.router;e.intermediateTransitionTo.apply(e,arguments)},refresh:function(){return this.router.router.refresh(this)},replaceWith:function(){var e=this.router;return e.replaceWith.apply(e,arguments)},send:function(){return this.router.send.apply(this.router,arguments)},setup:function(e,t){var r=this.controllerName||this.routeName,n=this.controllerFor(r,!0);if(n||(n=this.generateController(r,e)),this.controller=n,this.setupControllers)this.setupControllers(n,e);else{var i=I(this,"_qp.states");if(t&&(G(this.router,t.state.handlerInfos),n._qpDelegate=i.changingKeys,n._updateCacheParams(t.params)),n._qpDelegate=i.allowOverrides,t){var a=T(this,t.state);n.setProperties(a)}this.setupController(n,e,t)}this.renderTemplates?this.renderTemplates(e):this.renderTemplate(n,e)},beforeModel:S.K,afterModel:S.K,redirect:S.K,contextDidChange:function(){this.currentModel=this.context},model:function(e,t){var r,n,i,a,s=I(this,"_qp.map");for(var o in e)"queryParams"===o||s&&o in s||((r=o.match(/^(.*)_id$/))&&(n=r[1],a=e[o]),i=!0);if(!n&&i)return B(e);if(!n){if(t.resolveIndex<1)return;var u=t.state.handlerInfos[t.resolveIndex-1].context;return u}return this.findModel(n,a)},deserialize:function(e,t){return this.model(this.paramsFor(this.routeName),t)},findModel:function(){var e=I(this,"store");return e.find.apply(e,arguments)},store:R(function(){{var e=this.container;this.routeName,I(this,"router.namespace")}return{find:function(t,r){var n=e.lookupFactory("model:"+t);if(n)return n.find(r)}}}),serialize:function(e,t){if(!(t.length<1)&&e){var r=t[0],n={};return/_id$/.test(r)&&1===t.length?n[r]=I(e,"id"):n=D(e,t),n}},setupController:function(e,t){e&&void 0!==t&&k(e,"model",t)},controllerFor:function(e){var t,r=this.container,n=r.lookup("route:"+e);return n&&n.controllerName&&(e=n.controllerName),t=r.lookup("controller:"+e)},generateController:function(e,t){var r=this.container;return t=t||this.modelFor(e),W(r,e,t)},modelFor:function(e){var t=this.container.lookup("route:"+e),r=this.router?this.router.router.activeTransition:null;if(r){var n=t&&t.routeName||e;if(r.resolvedModels.hasOwnProperty(n))return r.resolvedModels[n]}return t&&t.currentModel},renderTemplate:function(){this.render()},render:function(e,t){var r="string"==typeof e&&!!e;"object"!=typeof e||t||(t=e,e=this.routeName),t=t||{},t.namePassed=r;var n;e?(e=e.replace(/\//g,"."),n=e):(e=this.routeName,n=this.templateName||e);var i=t.view||r&&e||this.viewName||e,a=this.container,s=a.lookup("view:"+i),o=s?s.get("template"):null;return o||(o=a.lookup("template:"+n)),s||o?(t=x(this,e,o,t),s=C(s,a,t),"main"===t.outlet&&(this.lastRenderedTemplate=e),void O(this,s,t)):void I(this.router,"namespace.LOG_VIEW_LOOKUPS")},disconnectOutlet:function(e){if(!e||"string"==typeof e){var t=e;e={},e.outlet=t}e.parentView=e.parentView?e.parentView.replace(/\//g,"."):w(this),e.outlet=e.outlet||"main";var r=this.router._lookupActiveView(e.parentView);r&&r.disconnectOutlet(e.outlet)},willDestroy:function(){this.teardownViews()},teardownViews:function(){this.teardownTopLevelView&&this.teardownTopLevelView();var e=this.teardownOutletViews||[];j(e,function(e){e()}),delete this.teardownTopLevelView,delete this.teardownOutletViews,delete this.lastRenderedTemplate}}),$={qps:[],map:{},states:{}};y["default"]=Q}),e("ember-routing/system/router",["ember-metal/core","ember-metal/error","ember-metal/property_get","ember-metal/property_set","ember-metal/properties","ember-metal/computed","ember-metal/merge","ember-metal/run_loop","ember-metal/enumerable_utils","ember-runtime/system/string","ember-runtime/system/object","ember-runtime/mixins/evented","ember-routing/system/dsl","ember-views/views/view","ember-routing/location/api","ember-handlebars/views/metamorph_view","ember-routing-handlebars/helpers/shared","ember-metal/platform","exports"],function(e,r,n,i,a,s,o,u,l,c,h,p,m,f,d,v,b,y,g){"use strict";function _(e,t,r){for(var n,i,a=t.state.handlerInfos,s=!1,o=a.length-1;o>=0;--o)if(n=a[o],i=n.handler,s){if(r(i,a[o+1].handler)!==!0)return!1}else e===i&&(s=!0);return!0}function w(e,t){var r=[];t&&r.push(t),e&&(e.message&&r.push(e.message),e.stack&&r.push(e.stack),"string"==typeof e&&r.push(e)),S.Logger.error.apply(this,r)}function x(e,t,r){var n,i=e.router,a=(t.routeName.split(".").pop(),"application"===e.routeName?"":e.routeName+".");return n=a+r,C(i,n)?n:void 0}function C(e,t){var r=e.container;return e.hasRoute(t)&&(r.has("template:"+t)||r.has("route:"+t))}function O(e,t,r){var n=r.shift();if(!e){if(t)return;throw new V("Can't trigger action '"+n+"' because your app hasn't finished transitioning into its first route. To trigger an action on destination routes during a transition, you can call `.send()` on the `Transition` object passed to the `model/beforeModel/afterModel` hooks.")}for(var i,a,s=!1,o=e.length-1;o>=0;o--)if(i=e[o],a=i.handler,a._actions&&a._actions[n]){if(a._actions[n].apply(a,r)!==!0)return;s=!0}if(Y[n])return void Y[n].apply(null,r);if(!s&&!t)throw new V("Nothing handled the action '"+n+"'. If you did handle the action, this error can be caused by returning true from an action handler in a controller, causing the action to bubble.")}function E(e,t,r){for(var n=e.router,i=n.applyIntent(t,r),a=i.handlerInfos,s=i.params,o=0,u=a.length;u>o;++o){var l=a[o];l.isResolved||(l=l.becomeResolved(null,l.context)),s[l.name]=l.params}return i}function P(e){var t=e.container.lookup("controller:application");if(t){var r=e.router.currentHandlerInfos,n=$._routePath(r);"currentPath"in t||D(t,"currentPath"),k(t,"currentPath",n),"currentRouteName"in t||D(t,"currentRouteName"),k(t,"currentRouteName",r[r.length-1].name)}}function A(e){e.then(null,function(e){return e&&e.name?("UnrecognizedURLError"===e.name,e):void 0},"Ember: Process errors from Router")}function T(e){return"string"==typeof e&&(""===e||"/"===e.charAt(0))}function N(e,t,r,n){{var i=e._queryParamsFor(t);i.qps}for(var a in r)if(r.hasOwnProperty(a)){var s=r[a],o=i.map[a];o&&n(a,s,o)}}var S=e["default"],V=r["default"],I=n.get,k=i.set,D=a.defineProperty,j=s.computed,M=o["default"],R=u["default"],L=(l.forEach,c.fmt,h["default"]),H=p["default"],z=m["default"],q=f["default"],F=d["default"],B=v["default"],U=b.routeArgs,K=b.getActiveTargetName,W=b.stashParamNames,G=(y.create,t("router")["default"]),Q=(t("router/transition").Transition,[].slice),$=L.extend(H,{location:"hash",rootURL:"/",init:function(){this.router=this.constructor.router||this.constructor.map(S.K),this._activeViews={},this._setupLocation(),this._qpCache={},this._queuedQPChanges={},I(this,"namespace.LOG_TRANSITIONS_INTERNAL")&&(this.router.log=S.Logger.debug)},url:j(function(){return I(this,"location").getURL()}),startRouting:function(){this.router=this.router||this.constructor.map(S.K);var e=this.router,t=I(this,"location"),r=this.container,n=this,i=I(this,"initialURL");I(t,"cancelRouterSetup")||(this._setupRouter(e,t),r.register("view:default",B),r.register("view:toplevel",q.extend()),t.onUpdateURL(function(e){n.handleURL(e)}),"undefined"==typeof i&&(i=t.getURL()),this.handleURL(i))},didTransition:function(e){P(this),this._cancelLoadingEvent(),this.notifyPropertyChange("url"),R.once(this,this.trigger,"didTransition"),I(this,"namespace").LOG_TRANSITIONS&&S.Logger.log("Transitioned into '"+$._routePath(e)+"'")},handleURL:function(e){return this._doURLTransition("handleURL",e)},_doURLTransition:function(e,t){var r=this.router[e](t||"/");return A(r),r},transitionTo:function(){var e,t=Q.call(arguments);if(T(t[0]))return this._doURLTransition("transitionTo",t[0]);var r=t[t.length-1];e=r&&r.hasOwnProperty("queryParams")?t.pop().queryParams:{};var n=t.shift();return this._doTransition(n,t,e)},intermediateTransitionTo:function(){this.router.intermediateTransitionTo.apply(this.router,arguments),P(this);var e=this.router.currentHandlerInfos;I(this,"namespace").LOG_TRANSITIONS&&S.Logger.log("Intermediate-transitioned into '"+$._routePath(e)+"'")},replaceWith:function(){return this.transitionTo.apply(this,arguments).method("replace")},generate:function(){var e=this.router.generate.apply(this.router,arguments);return this.location.formatURL(e)},isActive:function(){var e=this.router;return e.isActive.apply(e,arguments)},isActiveIntent:function(){var e=this.router;return e.isActive.apply(e,arguments)},send:function(){this.router.trigger.apply(this.router,arguments)},hasRoute:function(e){return this.router.hasRoute(e)},reset:function(){this.router.reset()},_lookupActiveView:function(e){var t=this._activeViews[e];return t&&t[0]},_connectActiveView:function(e,t){function r(){delete this._activeViews[e]}var n=this._activeViews[e];n&&n[0].off("willDestroyElement",this,n[1]),this._activeViews[e]=[t,r],t.one("willDestroyElement",this,r)},_setupLocation:function(){var e=I(this,"location"),t=I(this,"rootURL");if(t&&this.container&&!this.container.has("-location-setting:root-url")&&this.container.register("-location-setting:root-url",t,{instantiate:!1}),"string"==typeof e&&this.container){var r=this.container.lookup("location:"+e);if("undefined"!=typeof r)e=k(this,"location",r);else{var n={implementation:e};e=k(this,"location",F.create(n))}}null!==e&&"object"==typeof e&&(t&&"string"==typeof t&&(e.rootURL=t),"function"==typeof e.initState&&e.initState())},_getHandlerFunction:function(){var e={},t=this.container,r=t.lookupFactory("route:basic"),n=this;return function(i){var a="route:"+i,s=t.lookup(a);return e[i]?s:(e[i]=!0,s||(t.register(a,r.extend()),s=t.lookup(a),I(n,"namespace.LOG_ACTIVE_GENERATION")),s.routeName=i,s)}},_setupRouter:function(e,t){var r,n=this;e.getHandler=this._getHandlerFunction();var i=function(){t.setURL(r)};if(e.updateURL=function(e){r=e,R.once(i)},t.replaceURL){var a=function(){t.replaceURL(r)};e.replaceURL=function(e){r=e,R.once(a)}}e.didTransition=function(e){n.didTransition(e)}},_serializeQueryParams:function(e,t){var r={};N(this,e,t,function(e,n,i){var a=i.urlKey;r[a]||(r[a]=[]),r[a].push({qp:i,value:n}),delete t[e]});for(var n in r){var i=r[n];if(i.length>1){i[0].qp,i[1].qp}var a=i[0].qp;t[a.urlKey]=a.route.serializeQueryParam(i[0].value,a.urlKey,a.type)}},_deserializeQueryParams:function(e,t){N(this,e,t,function(e,r,n){delete t[e],t[n.prop]=n.route.deserializeQueryParam(r,n.urlKey,n.type)})},_pruneDefaultQueryParamValues:function(e,t){var r=this._queryParamsFor(e);for(var n in t){var i=r.map[n];i&&i.sdef===t[n]&&delete t[n]}},_doTransition:function(e,t,r){var n=e||K(this.router),i={};M(i,r),this._prepareQueryParams(n,t,i);var a=U(n,t,i),s=this.router.transitionTo.apply(this.router,a);return A(s),s},_prepareQueryParams:function(e,t,r){this._hydrateUnsuppliedQueryParams(e,t,r),this._serializeQueryParams(e,r),this._pruneDefaultQueryParamValues(e,r)},_queryParamsFor:function(e){if(this._qpCache[e])return this._qpCache[e];for(var t={},r=[],n=(this._qpCache[e]={map:t,qps:r},this.router),i=n.recognizer.handlersFor(e),a=0,s=i.length;s>a;++a){var o=i[a],u=n.getHandler(o.handler),l=I(u,"_qp");l&&(M(t,l.map),r.push.apply(r,l.qps))}return{qps:r,map:t}},_hydrateUnsuppliedQueryParams:function(e,t,r){var n=E(this,e,t),i=n.handlerInfos,a=this._bucketCache;W(this,i);for(var s=0,o=i.length;o>s;++s)for(var u=i[s].handler,l=I(u,"_qp"),c=0,h=l.qps.length;h>c;++c){var p=l.qps[c],m=p.prop in r&&p.prop||p.fprop in r&&p.fprop;if(m)m!==p.fprop&&(r[p.fprop]=r[m],delete r[m]);else{var f=p.cProto,d=I(f,"_cacheMeta"),v=f._calculateCacheKey(p.ctrl,d[p.prop].parts,n.params);r[p.fprop]=a.lookup(v,p.prop,p.def)}}},_scheduleLoadingEvent:function(e,t){this._cancelLoadingEvent(),this._loadingStateTimer=R.scheduleOnce("routerTransitions",this,"_fireLoadingEvent",e,t)},_fireLoadingEvent:function(e,t){this.router.activeTransition&&e.trigger(!0,"loading",e,t)},_cancelLoadingEvent:function(){this._loadingStateTimer&&R.cancel(this._loadingStateTimer),this._loadingStateTimer=null}}),Y={willResolveModel:function(e,t){t.router._scheduleLoadingEvent(e,t)},error:function(e,t,r){var n=r.router,i=_(r,t,function(t,r){var i=x(t,r,"error");return i?void n.intermediateTransitionTo(i,e):!0});return i&&C(r.router,"application_error")?void n.intermediateTransitionTo("application_error",e):void w(e,"Error while processing route: "+t.targetName)},loading:function(e,t){var r=t.router,n=_(t,e,function(t,n){var i=x(t,n,"loading");return i?void r.intermediateTransitionTo(i):e.pivotHandler!==t?!0:void 0});return n&&C(t.router,"application_loading")?void r.intermediateTransitionTo("application_loading"):void 0}};$.reopenClass({router:null,map:function(e){var t=this.router;t||(t=new G,t._triggerWillChangeContext=S.K,t._triggerWillLeave=S.K,t.callbacks=[],t.triggerEvent=O,this.reopenClass({router:t}));var r=z.map(function(){this.resource("application",{path:"/"},function(){for(var r=0;rr;++r)if(e[r]!==t[r])return!1;return!0}for(var r,n,i,a=[],s=1,o=e.length;o>s;s++){for(r=e[s].name,n=r.split("."),i=Q.call(a);i.length&&!t(i,n);)i.shift();a.push.apply(a,n.slice(i.length))}return a.join(".")}}),g["default"]=$}),e("ember-runtime",["ember-metal","ember-runtime/core","ember-runtime/compare","ember-runtime/copy","ember-runtime/system/namespace","ember-runtime/system/object","ember-runtime/system/tracked_array","ember-runtime/system/subarray","ember-runtime/system/container","ember-runtime/system/application","ember-runtime/system/array_proxy","ember-runtime/system/object_proxy","ember-runtime/system/core_object","ember-runtime/system/each_proxy","ember-runtime/system/native_array","ember-runtime/system/set","ember-runtime/system/string","ember-runtime/system/deferred","ember-runtime/system/lazy_load","ember-runtime/mixins/array","ember-runtime/mixins/comparable","ember-runtime/mixins/copyable","ember-runtime/mixins/enumerable","ember-runtime/mixins/freezable","ember-runtime/mixins/-proxy","ember-runtime/mixins/observable","ember-runtime/mixins/action_handler","ember-runtime/mixins/deferred","ember-runtime/mixins/mutable_enumerable","ember-runtime/mixins/mutable_array","ember-runtime/mixins/target_action_support","ember-runtime/mixins/evented","ember-runtime/mixins/promise_proxy","ember-runtime/mixins/sortable","ember-runtime/computed/array_computed","ember-runtime/computed/reduce_computed","ember-runtime/computed/reduce_computed_macros","ember-runtime/controllers/array_controller","ember-runtime/controllers/object_controller","ember-runtime/controllers/controller","ember-runtime/mixins/controller","ember-runtime/ext/rsvp","ember-runtime/ext/string","ember-runtime/ext/function","exports"],function(e,t,r,n,i,a,s,o,u,l,c,h,p,m,f,d,v,b,y,g,_,w,x,C,O,E,P,A,T,N,S,V,I,k,D,j,M,R,L,H,z,q,F,B,U){"use strict";var K=e["default"],W=t.isEqual,G=r["default"],Q=n["default"],$=i["default"],Y=a["default"],J=s["default"],Z=o["default"],X=u["default"],et=(l["default"],c["default"]),tt=h["default"],rt=p["default"],nt=m.EachArray,it=m.EachProxy,at=f["default"],st=d["default"],ot=v["default"],ut=b["default"],lt=y.onLoad,ct=y.runLoadHooks,ht=g["default"],pt=_["default"],mt=w["default"],ft=x["default"],dt=C.Freezable,vt=C.FROZEN_ERROR,bt=O["default"],yt=E["default"],gt=P["default"],_t=A["default"],wt=T["default"],xt=N["default"],Ct=S["default"],Ot=V["default"],Et=I["default"],Pt=k["default"],At=D.arrayComputed,Tt=D.ArrayComputedProperty,Nt=j.reduceComputed,St=j.ReduceComputedProperty,Vt=M.sum,It=M.min,kt=M.max,Dt=M.map,jt=M.sort,Mt=M.setDiff,Rt=M.mapBy,Lt=M.mapProperty,Ht=M.filter,zt=M.filterBy,qt=M.filterProperty,Ft=M.uniq,Bt=M.union,Ut=M.intersect,Kt=R["default"],Wt=L["default"],Gt=H["default"],Qt=z["default"],$t=q["default"];K.compare=G,K.copy=Q,K.isEqual=W,K.Array=ht,K.Comparable=pt,K.Copyable=mt,K.SortableMixin=Pt,K.Freezable=dt,K.FROZEN_ERROR=vt,K.DeferredMixin=_t,K.MutableEnumerable=wt,K.MutableArray=xt,K.TargetActionSupport=Ct,K.Evented=Ot,K.PromiseProxyMixin=Et,K.Observable=yt,K.arrayComputed=At,K.ArrayComputedProperty=Tt,K.reduceComputed=Nt,K.ReduceComputedProperty=St;var Yt=K.computed;Yt.sum=Vt,Yt.min=It,Yt.max=kt,Yt.map=Dt,Yt.sort=jt,Yt.setDiff=Mt,Yt.mapBy=Rt,Yt.mapProperty=Lt,Yt.filter=Ht,Yt.filterBy=zt,Yt.filterProperty=qt,Yt.uniq=Ft,Yt.union=Bt,Yt.intersect=Ut,K.String=ot,K.Object=Y,K.TrackedArray=J,K.SubArray=Z,K.Container=X,K.Namespace=$,K.Enumerable=ft,K.ArrayProxy=et,K.ObjectProxy=tt,K.ActionHandler=gt,K.CoreObject=rt,K.EachArray=nt,K.EachProxy=it,K.NativeArray=at,K.Set=st,K.Deferred=ut,K.onLoad=lt,K.runLoadHooks=ct,K.ArrayController=Kt,K.ObjectController=Wt,K.Controller=Gt,K.ControllerMixin=Qt,K._ProxyMixin=bt,K.RSVP=$t,U["default"]=K}),e("ember-runtime/compare",["ember-metal/utils","ember-runtime/mixins/comparable","exports"],function(e,t,r){"use strict";function n(e,t){var r=e-t;return(r>0)-(0>r)}var i=e.typeOf,a=t["default"],s={undefined:0,"null":1,"boolean":2,number:3,string:4,array:5,object:6,instance:7,"function":8,"class":9,date:10};r["default"]=function o(e,t){if(e===t)return 0;var r=i(e),u=i(t);if(a){if("instance"===r&&a.detect(e.constructor))return e.constructor.compare(e,t);if("instance"===u&&a.detect(t.constructor))return 1-t.constructor.compare(t,e)}var l=n(s[r],s[u]);if(0!==l)return l;switch(r){case"boolean":case"number":return n(e,t);case"string":return n(e.localeCompare(t),0);case"array":for(var c=e.length,h=t.length,p=Math.min(c,h),m=0;p>m;m++){var f=o(e[m],t[m]);if(0!==f)return f}return n(c,h);case"instance":return a&&a.detect(e)?e.compare(e,t):0;case"date":return n(e.getTime(),t.getTime());default:return 0}}}),e("ember-runtime/computed/array_computed",["ember-metal/core","ember-runtime/computed/reduce_computed","ember-metal/enumerable_utils","ember-metal/platform","ember-metal/observer","ember-metal/error","exports"],function(e,t,r,n,i,a,s){"use strict";function o(){var e=this;return c.apply(this,arguments),this.func=function(t){return function(r){return e._hasInstanceMeta(this,r)||h(e._dependentKeys,function(t){m(this,t,function(){e.recomputeOnce.call(this,r) -})},this),t.apply(this,arguments)}}(this.func),this}function u(e){var t;if(arguments.length>1&&(t=d.call(arguments,0,-1),e=d.call(arguments,-1)[0]),"object"!=typeof e)throw new f("Array Computed Property declared without an options hash");var r=new o(e);return t&&r.property.apply(r,t),r}var l=e["default"],c=(t.reduceComputed,t.ReduceComputedProperty),h=r.forEach,p=n.create,m=i.addObserver,f=a["default"],d=[].slice;o.prototype=p(c.prototype),o.prototype.initialValue=function(){return l.A()},o.prototype.resetValue=function(e){return e.clear(),e},o.prototype.didChange=function(){},s.arrayComputed=u,s.ArrayComputedProperty=o}),e("ember-runtime/computed/reduce_computed",["ember-metal/core","ember-metal/property_get","ember-metal/property_set","ember-metal/utils","ember-metal/error","ember-metal/property_events","ember-metal/expand_properties","ember-metal/observer","ember-metal/computed","ember-metal/platform","ember-metal/enumerable_utils","ember-runtime/system/tracked_array","ember-runtime/mixins/array","ember-metal/run_loop","exports"],function(e,t,r,n,i,a,s,o,u,l,c,h,p,m,f){"use strict";function d(e,t){return"@this"===t?e:T(e,t)}function v(e,t,r){this.callbacks=e,this.cp=t,this.instanceMeta=r,this.dependentKeysByGuid={},this.trackedArraysByGuid={},this.suspended=!1,this.changedItems={},this.changedItemCount=0}function b(e,t,r){this.dependentArray=e,this.index=t,this.item=e.objectAt(t),this.trackedArray=r,this.beforeObserver=null,this.observer=null,this.destroyed=!1}function y(e,t,r){return 0>e?Math.max(0,t+e):t>e?e:Math.min(t-r,e)}function g(e,t,r){return Math.min(r,t-e)}function _(e,t,r,n,i,a,s){this.arrayChanged=e,this.index=r,this.item=t,this.propertyName=n,this.property=i,this.changedCount=a,s&&(this.previousValues=s)}function w(e,t,r,n,i){F(e,function(a,s){i.setValue(t.addedItem.call(this,i.getValue(),a,new _(e,a,s,n,r,e.length),i.sugarMeta))},this),t.flushedChanges.call(this,i.getValue(),i.sugarMeta)}function x(e,t){var r=(e._callbacks(),e._hasInstanceMeta(this,t)),n=e._instanceMeta(this,t);r&&n.setValue(e.resetValue(n.getValue())),e.options.initialize&&e.options.initialize.call(this,n.getValue(),{property:e,propertyName:t},n.sugarMeta)}function C(e,t){if(Z.test(t))return!1;var r=d(e,t);return U.detect(r)}function O(e,t,r){this.context=e,this.propertyName=t,this.cache=S(e).cache,this.dependentArrays={},this.sugarMeta={},this.initialValue=r}function E(e){var t=this;this.options=e,this._dependentKeys=null,this._itemPropertyKeys={},this._previousItemPropertyKeys={},this.readOnly(),this.cacheable(),this.recomputeOnce=function(e){K.once(this,r,e)};var r=function(e){var r=(t._dependentKeys,t._instanceMeta(this,e)),n=t._callbacks();x.call(this,t,e),r.dependentArraysObserver.suspendArrayObservers(function(){F(t._dependentKeys,function(e){if(C(this,e)){var n=d(this,e),i=r.dependentArrays[e];n===i?t._previousItemPropertyKeys[e]&&(delete t._previousItemPropertyKeys[e],r.dependentArraysObserver.setupPropertyObservers(e,t._itemPropertyKeys[e])):(r.dependentArrays[e]=n,i&&r.dependentArraysObserver.teardownObservers(i,e),n&&r.dependentArraysObserver.setupObservers(n,e))}},this)},this),F(t._dependentKeys,function(i){if(C(this,i)){var a=d(this,i);a&&w.call(this,a,n,t,e,r)}},this)};this.func=function(e){return r.call(this,e),t._instanceMeta(this,e).getValue()}}function P(e){return e}function A(e){var t;if(arguments.length>1&&(t=$.call(arguments,0,-1),e=$.call(arguments,-1)[0]),"object"!=typeof e)throw new V("Reduce Computed Property declared without an options hash");if(!("initialValue"in e))throw new V("Reduce Computed Property declared without an initial value");var r=new E(e);return t&&r.property.apply(r,t),r}var T=(e["default"],t.get),N=(r.set,n.guidFor),S=n.meta,V=i["default"],I=a.propertyWillChange,k=a.propertyDidChange,D=s["default"],j=o.addObserver,M=(o.observersFor,o.removeObserver),R=o.addBeforeObserver,L=o.removeBeforeObserver,H=u.ComputedProperty,z=u.cacheFor,q=l.create,F=c.forEach,B=h["default"],U=p["default"],K=m["default"],W=(n.isArray,z.set),G=z.get,Q=z.remove,$=[].slice,Y=/^(.*)\.@each\.(.*)/,J=/(.*\.@each){2,}/,Z=/\.\[\]$/;v.prototype={setValue:function(e){this.instanceMeta.setValue(e,!0)},getValue:function(){return this.instanceMeta.getValue()},setupObservers:function(e,t){this.dependentKeysByGuid[N(e)]=t,e.addArrayObserver(this,{willChange:"dependentArrayWillChange",didChange:"dependentArrayDidChange"}),this.cp._itemPropertyKeys[t]&&this.setupPropertyObservers(t,this.cp._itemPropertyKeys[t])},teardownObservers:function(e,t){var r=this.cp._itemPropertyKeys[t]||[];delete this.dependentKeysByGuid[N(e)],this.teardownPropertyObservers(t,r),e.removeArrayObserver(this,{willChange:"dependentArrayWillChange",didChange:"dependentArrayDidChange"})},suspendArrayObservers:function(e,t){var r=this.suspended;this.suspended=!0,e.call(t),this.suspended=r},setupPropertyObservers:function(e,t){var r=d(this.instanceMeta.context,e),n=d(r,"length"),i=new Array(n);this.resetTransformations(e,i),F(r,function(n,a){var s=this.createPropertyObserverContext(r,a,this.trackedArraysByGuid[e]);i[a]=s,F(t,function(e){R(n,e,this,s.beforeObserver),j(n,e,this,s.observer)},this)},this)},teardownPropertyObservers:function(e,t){var r,n,i,a=this,s=this.trackedArraysByGuid[e];s&&s.apply(function(e,s,o){o!==B.DELETE&&F(e,function(e){e.destroyed=!0,r=e.beforeObserver,n=e.observer,i=e.item,F(t,function(e){L(i,e,a,r),M(i,e,a,n)})})})},createPropertyObserverContext:function(e,t,r){var n=new b(e,t,r);return this.createPropertyObserver(n),n},createPropertyObserver:function(e){var t=this;e.beforeObserver=function(r,n){return t.itemPropertyWillChange(r,n,e.dependentArray,e)},e.observer=function(r,n){return t.itemPropertyDidChange(r,n,e.dependentArray,e)}},resetTransformations:function(e,t){this.trackedArraysByGuid[e]=new B(t)},trackAdd:function(e,t,r){var n=this.trackedArraysByGuid[e];n&&n.addItems(t,r)},trackRemove:function(e,t,r){var n=this.trackedArraysByGuid[e];return n?n.removeItems(t,r):[]},updateIndexes:function(e,t){var r=d(t,"length");e.apply(function(e,t,n,i){n!==B.DELETE&&(0!==i||n!==B.RETAIN||e.length!==r||0!==t)&&F(e,function(e,r){e.index=r+t})})},dependentArrayWillChange:function(e,t,r){function n(e){u[o].destroyed=!0,L(a,e,this,u[o].beforeObserver),M(a,e,this,u[o].observer)}if(!this.suspended){var i,a,s,o,u,l=this.callbacks.removedItem,c=N(e),h=this.dependentKeysByGuid[c],p=this.cp._itemPropertyKeys[h]||[],m=d(e,"length"),f=y(t,m,0),v=g(f,m,r);for(u=this.trackRemove(h,f,v),o=v-1;o>=0&&(s=f+o,!(s>=m));--o)a=e.objectAt(s),F(p,n,this),i=new _(e,a,s,this.instanceMeta.propertyName,this.cp,v),this.setValue(l.call(this.instanceMeta.context,this.getValue(),a,i,this.instanceMeta.sugarMeta));this.callbacks.flushedChanges.call(this.instanceMeta.context,this.getValue(),this.instanceMeta.sugarMeta)}},dependentArrayDidChange:function(e,t,r,n){if(!this.suspended){var i,a,s=this.callbacks.addedItem,o=N(e),u=this.dependentKeysByGuid[o],l=new Array(n),c=this.cp._itemPropertyKeys[u],h=d(e,"length"),p=y(t,h,n),m=p+n;F(e.slice(p,m),function(t,r){c&&(a=this.createPropertyObserverContext(e,p+r,this.trackedArraysByGuid[u]),l[r]=a,F(c,function(e){R(t,e,this,a.beforeObserver),j(t,e,this,a.observer)},this)),i=new _(e,t,p+r,this.instanceMeta.propertyName,this.cp,n),this.setValue(s.call(this.instanceMeta.context,this.getValue(),t,i,this.instanceMeta.sugarMeta))},this),this.callbacks.flushedChanges.call(this.instanceMeta.context,this.getValue(),this.instanceMeta.sugarMeta),this.trackAdd(u,p,l)}},itemPropertyWillChange:function(e,t,r,n){var i=N(e);this.changedItems[i]||(this.changedItems[i]={array:r,observerContext:n,obj:e,previousValues:{}}),++this.changedItemCount,this.changedItems[i].previousValues[t]=d(e,t)},itemPropertyDidChange:function(){0===--this.changedItemCount&&this.flushChanges()},flushChanges:function(){var e,t,r,n=this.changedItems;for(e in n)t=n[e],t.observerContext.destroyed||(this.updateIndexes(t.observerContext.trackedArray,t.observerContext.dependentArray),r=new _(t.array,t.obj,t.observerContext.index,this.instanceMeta.propertyName,this.cp,n.length,t.previousValues),this.setValue(this.callbacks.removedItem.call(this.instanceMeta.context,this.getValue(),t.obj,r,this.instanceMeta.sugarMeta)),this.setValue(this.callbacks.addedItem.call(this.instanceMeta.context,this.getValue(),t.obj,r,this.instanceMeta.sugarMeta)));this.changedItems={},this.callbacks.flushedChanges.call(this.instanceMeta.context,this.getValue(),this.instanceMeta.sugarMeta)}},O.prototype={getValue:function(){var e=G(this.cache,this.propertyName);return void 0!==e?e:this.initialValue},setValue:function(e,t){e!==G(this.cache,this.propertyName)&&(t&&I(this.context,this.propertyName),void 0===e?Q(this.cache,this.propertyName):W(this.cache,this.propertyName,e),t&&k(this.context,this.propertyName))}},f.ReduceComputedProperty=E,E.prototype=q(H.prototype),E.prototype._callbacks=function(){if(!this.callbacks){var e=this.options;this.callbacks={removedItem:e.removedItem||P,addedItem:e.addedItem||P,flushedChanges:e.flushedChanges||P}}return this.callbacks},E.prototype._hasInstanceMeta=function(e,t){return!!S(e).cacheMeta[t]},E.prototype._instanceMeta=function(e,t){var r=S(e).cacheMeta,n=r[t];return n||(n=r[t]=new O(e,t,this.initialValue()),n.dependentArraysObserver=new v(this._callbacks(),this,n,e,t,n.sugarMeta)),n},E.prototype.initialValue=function(){return"function"==typeof this.options.initialValue?this.options.initialValue():this.options.initialValue},E.prototype.resetValue=function(){return this.initialValue()},E.prototype.itemPropertyKey=function(e,t){this._itemPropertyKeys[e]=this._itemPropertyKeys[e]||[],this._itemPropertyKeys[e].push(t)},E.prototype.clearItemPropertyKeys=function(e){this._itemPropertyKeys[e]&&(this._previousItemPropertyKeys[e]=this._itemPropertyKeys[e],this._itemPropertyKeys[e]=[])},E.prototype.property=function(){var e,t,r=this,n=$.call(arguments),i={};F(n,function(n){if(J.test(n))throw new V("Nested @each properties not supported: "+n);if(e=Y.exec(n)){t=e[1];var a=e[2],s=function(e){r.itemPropertyKey(t,e)};D(a,s),i[N(t)]=t}else i[N(n)]=n});var a=[];for(var s in i)a.push(i[s]);return H.prototype.property.apply(this,a)},f.reduceComputed=A}),e("ember-runtime/computed/reduce_computed_macros",["ember-metal/core","ember-metal/property_get","ember-metal/property_set","ember-metal/utils","ember-metal/error","ember-metal/enumerable_utils","ember-metal/run_loop","ember-metal/observer","ember-runtime/computed/array_computed","ember-runtime/computed/reduce_computed","ember-runtime/system/subarray","ember-metal/keys","ember-runtime/compare","exports"],function(e,t,r,n,i,a,s,o,u,l,c,h,p,m){"use strict";function f(e){return M(e,{initialValue:0,addedItem:function(e,t){return e+t},removedItem:function(e,t){return e-t}})}function d(e){return M(e,{initialValue:-1/0,addedItem:function(e,t){return Math.max(e,t)},removedItem:function(e,t){return e>t?e:void 0}})}function v(e){return M(e,{initialValue:1/0,addedItem:function(e,t){return Math.min(e,t)},removedItem:function(e,t){return t>e?e:void 0}})}function b(e,t){var r={addedItem:function(e,r,n){var i=t.call(this,r,n.index);return e.insertAt(n.index,i),e},removedItem:function(e,t,r){return e.removeAt(r.index,1),e}};return j(e,r)}function y(e,t){var r=function(e){return N(e,t)};return b(e+".@each."+t,r)}function g(e,t){var r={initialize:function(e,t,r){r.filteredArrayIndexes=new R},addedItem:function(e,r,n,i){var a=!!t.call(this,r,n.index),s=i.filteredArrayIndexes.addItem(n.index,a);return a&&e.insertAt(s,r),e},removedItem:function(e,t,r,n){var i=n.filteredArrayIndexes.removeItem(r.index);return i>-1&&e.removeAt(i),e}};return j(e,r)}function _(e,t,r){var n;return n=2===arguments.length?function(e){return N(e,t)}:function(e){return N(e,t)===r},g(e+".@each."+t,n)}function w(){var e=z.call(arguments);return e.push({initialize:function(e,t,r){r.itemCounts={}},addedItem:function(e,t,r,n){var i=S(t);return n.itemCounts[i]?++n.itemCounts[i]:(n.itemCounts[i]=1,e.pushObject(t)),e},removedItem:function(e,t,r,n){var i=S(t),a=n.itemCounts;return 0===--a[i]&&e.removeObject(t),e}}),j.apply(null,e)}function x(){var e=z.call(arguments);return e.push({initialize:function(e,t,r){r.itemCounts={}},addedItem:function(e,t,r,n){var i=S(t),a=S(r.arrayChanged),s=r.property._dependentKeys.length,o=n.itemCounts;return o[i]||(o[i]={}),void 0===o[i][a]&&(o[i][a]=0),1===++o[i][a]&&s===L(o[i]).length&&e.addObject(t),e},removedItem:function(e,t,r,n){var i,a=S(t),s=S(r.arrayChanged),o=(r.property._dependentKeys.length,n.itemCounts);return void 0===o[a][s]&&(o[a][s]=0),0===--o[a][s]&&(delete o[a][s],i=L(o[a]).length,0===i&&delete o[a],e.removeObject(t)),e}}),j.apply(null,e)}function C(e,t){if(2!==arguments.length)throw new V("setDiff requires exactly two dependent arrays.");return j(e,t,{addedItem:function(r,n,i){var a=N(this,e),s=N(this,t);return i.arrayChanged===a?s.contains(n)||r.addObject(n):r.removeObject(n),r},removedItem:function(r,n,i){var a=N(this,e),s=N(this,t);return i.arrayChanged===s?a.contains(n)&&r.addObject(n):r.removeObject(n),r}})}function O(e,t,r,n){var i,a,s,o,u;return arguments.length<4&&(n=N(e,"length")),arguments.length<3&&(r=0),r===n?r:(i=r+Math.floor((n-r)/2),a=e.objectAt(i),o=S(a),u=S(t),o===u?i:(s=this.order(a,t),0===s&&(s=u>o?-1:1),0>s?this.binarySearch(e,t,i+1,n):s>0?this.binarySearch(e,t,r,i):i))}function E(e,t){return"function"==typeof t?P(e,t):A(e,t)}function P(e,t){return j(e,{initialize:function(e,r,n){n.order=t,n.binarySearch=O,n.waitingInsertions=[],n.insertWaiting=function(){var t,r,i=n.waitingInsertions;n.waitingInsertions=[];for(var a=0;a=0&&r>e&&(t=this.lookupItemController(i))?this.controllerAt(e,i,t):i},arrangedContentDidChange:function(){this._super(),this._resetSubControllers()},arrayContentDidChange:function(e,t,r){var n=this._subControllers;if(n.length){var i=n.slice(e,e+t);p(i,function(e){e&&e.destroy()}),m(n,e,t,new Array(r))}this._super(e,t,r)},init:function(){this._super(),this._subControllers=[]},model:b(function(){return c.A()}),_isVirtual:!1,controllerAt:function(e,t,r){var n,i,a,s=h(this,"container"),o=this._subControllers;if(o.length>e&&(i=o[e]))return i;if(a=this._isVirtual?h(this,"parentController"):this,n="controller:"+r,!s.has(n))throw new y('Could not resolve itemController: "'+r+'"');return i=s.lookupFactory(n).create({target:a,parentController:a,model:t}),o[e]=i,i},_subControllers:null,_resetSubControllers:function(){var e,t=this._subControllers;if(t.length){for(var r=0,n=t.length;n>r;r++)e=t[r],e&&e.destroy();t.length=0}},willDestroy:function(){this._resetSubControllers(),this._super()}})}),e("ember-runtime/controllers/controller",["ember-runtime/system/object","ember-runtime/mixins/controller","exports"],function(e,t,r){"use strict";var n=e["default"],i=t["default"];r["default"]=n.extend(i)}),e("ember-runtime/controllers/object_controller",["ember-runtime/mixins/controller","ember-runtime/system/object_proxy","exports"],function(e,t,r){"use strict";var n=e["default"],i=t["default"];r["default"]=i.extend(n)}),e("ember-runtime/copy",["ember-metal/enumerable_utils","ember-metal/utils","ember-runtime/system/object","ember-runtime/mixins/copyable","exports"],function(e,t,r,n,i){"use strict";function a(e,t,r,n){var i,l,c;if("object"!=typeof e||null===e)return e;if(t&&(l=s(r,e))>=0)return n[l];if("array"===o(e)){if(i=e.slice(),t)for(l=i.length;--l>=0;)i[l]=a(i[l],t,r,n)}else if(u&&u.detect(e))i=e.copy(t,r,n);else if(e instanceof Date)i=new Date(e.getTime());else{i={};for(c in e)Object.prototype.hasOwnProperty.call(e,c)&&"__"!==c.substring(0,2)&&(i[c]=t?a(e[c],t,r,n):e[c])}return t&&(r.push(e),n.push(i)),i}var s=e.indexOf,o=t.typeOf,u=(r["default"],n["default"]);i["default"]=function(e,t){return"object"!=typeof e||null===e?e:u&&u.detect(e)?e.copy(t):a(e,t,t?[]:null,t?[]:null)}}),e("ember-runtime/core",["exports"],function(e){"use strict";var t=function(e,t){return e&&"function"==typeof e.isEqual?e.isEqual(t):e instanceof Date&&t instanceof Date?e.getTime()===t.getTime():e===t};e.isEqual=t}),e("ember-runtime/ext/function",["ember-metal/core","ember-metal/expand_properties","ember-metal/computed","ember-metal/mixin"],function(e,t,r,n){"use strict";var i=e["default"],a=t["default"],s=r.computed,o=n.observer,u=Array.prototype.slice,l=Function.prototype;(i.EXTEND_PROTOTYPES===!0||i.EXTEND_PROTOTYPES.Function)&&(l.property=function(){var e=s(this);return e.property.apply(e,arguments)},l.observes=function(){for(var e=arguments.length,t=new Array(e),r=0;e>r;r++)t[r]=arguments[r];return o.apply(this,t.concat(this))},l.observesImmediately=function(){for(var e=0,t=arguments.length;t>e;e++){arguments[e]}return this.observes.apply(this,arguments)},l.observesBefore=function(){for(var e=[],t=function(t){e.push(t)},r=0,n=arguments.length;n>r;++r)a(arguments[r],t);return this.__ember_observesBefore__=e,this},l.on=function(){var e=u.call(arguments);return this.__ember_listens__=e,this})}),e("ember-runtime/ext/rsvp",["ember-metal/core","ember-metal/logger","ember-metal/run_loop","exports"],function(e,r,n,i){"use strict";var a,s=e["default"],o=r["default"],u=n["default"],l=t("rsvp"),c="ember-testing/test",h=function(){s.Test&&s.Test.adapter&&s.Test.adapter.asyncStart()},p=function(){s.Test&&s.Test.adapter&&s.Test.adapter.asyncEnd()};l.configure("async",function(e,t){var r=!u.currentRunLoop;s.testing&&r&&h(),u.backburner.schedule("actions",function(){s.testing&&r&&p(),e(t)})}),l.Promise.prototype.fail=function(e,t){return this["catch"](e,t)},l.onerrorDefault=function(e){if(e instanceof Error)if(s.testing){if(!a&&s.__loader.registry[c]&&(a=t(c)["default"]),!a||!a.adapter)throw e;a.adapter.exception(e)}else s.onerror?s.onerror(e):o.error(e.stack)},l.on("error",l.onerrorDefault),i["default"]=l}),e("ember-runtime/ext/string",["ember-metal/core","ember-runtime/system/string"],function(e,t){"use strict";var r=e["default"],n=t.fmt,i=t.w,a=t.loc,s=t.camelize,o=t.decamelize,u=t.dasherize,l=t.underscore,c=t.capitalize,h=t.classify,p=String.prototype;(r.EXTEND_PROTOTYPES===!0||r.EXTEND_PROTOTYPES.String)&&(p.fmt=function(){return n(this,arguments)},p.w=function(){return i(this)},p.loc=function(){return a(this,arguments)},p.camelize=function(){return s(this)},p.decamelize=function(){return o(this)},p.dasherize=function(){return u(this)},p.underscore=function(){return l(this)},p.classify=function(){return h(this)},p.capitalize=function(){return c(this)})}),e("ember-runtime/mixins/-proxy",["ember-metal/core","ember-metal/property_get","ember-metal/property_set","ember-metal/utils","ember-metal/observer","ember-metal/property_events","ember-metal/computed","ember-metal/properties","ember-metal/mixin","ember-runtime/system/string","ember-runtime/system/object","exports"],function(e,t,r,n,i,a,s,o,u,l,c,h){"use strict";function p(e,t){var r=t.slice(8);r in this||w(this,r)}function m(e,t){var r=t.slice(8);r in this||x(this,r)}{var f=(e["default"],t.get),d=r.set,v=n.meta,b=i.addObserver,y=i.removeObserver,g=i.addBeforeObserver,_=i.removeBeforeObserver,w=a.propertyWillChange,x=a.propertyDidChange,C=s.computed,O=o.defineProperty,E=u.Mixin,P=u.observer;l.fmt,c["default"]}h["default"]=E.create({content:null,_contentDidChange:P("content",function(){}),isTruthy:C.bool("content"),_debugContainerKey:null,willWatchProperty:function(e){var t="content."+e;g(this,t,null,p),b(this,t,null,m)},didUnwatchProperty:function(e){var t="content."+e;_(this,t,null,p),y(this,t,null,m)},unknownProperty:function(e){var t=f(this,"content");return t?f(t,e):void 0},setUnknownProperty:function(e,t){var r=v(this);if(r.proto===this)return O(this,e,null,t),t;var n=f(this,"content");return d(n,e,t)}})}),e("ember-runtime/mixins/action_handler",["ember-metal/merge","ember-metal/mixin","ember-metal/property_get","ember-metal/utils","exports"],function(e,t,r,n,i){"use strict";var a=e["default"],s=t.Mixin,o=r.get,u=n.typeOf,l=s.create({mergedProperties:["_actions"],willMergeMixin:function(e){var t;e._actions||("object"===u(e.actions)?t="actions":"object"===u(e.events)&&(t="events"),t&&(e._actions=a(e._actions||{},e[t])),delete e[t])},send:function(e){var t,r=[].slice.call(arguments,1);this._actions&&this._actions[e]&&this._actions[e].apply(this,r)!==!0||(t=o(this,"target"))&&t.send.apply(t,arguments)}});i["default"]=l}),e("ember-runtime/mixins/array",["ember-metal/core","ember-metal/property_get","ember-metal/computed","ember-metal/is_none","ember-runtime/mixins/enumerable","ember-metal/enumerable_utils","ember-metal/mixin","ember-metal/property_events","ember-metal/events","ember-metal/watching","exports"],function(e,r,n,i,a,s,o,u,l,c,h){"use strict";function p(e,t,r,n,i){var a=r&&r.willChange||"arrayWillChange",s=r&&r.didChange||"arrayDidChange",o=f(e,"hasArrayObservers");return o===i&&x(e,"hasArrayObservers"),n(e,"@array:before",t,a),n(e,"@array:change",t,s),o===i&&C(e,"hasArrayObservers"),e}var m=e["default"],f=r.get,d=n.computed,v=n.cacheFor,b=i.isNone,y=(i.none,a["default"]),g=s.map,_=o.Mixin,w=o.required,x=u.propertyWillChange,C=u.propertyDidChange,O=l.addListener,E=l.removeListener,P=l.sendEvent,A=l.hasListeners,T=c.isWatching;h["default"]=_.create(y,{length:w(),objectAt:function(e){return 0>e||e>=f(this,"length")?void 0:f(this,e)},objectsAt:function(e){var t=this;return g(e,function(e){return t.objectAt(e)})},nextObject:function(e){return this.objectAt(e)},"[]":d(function(e,t){return void 0!==t&&this.replace(0,f(this,"length"),t),this}),firstObject:d(function(){return this.objectAt(0)}),lastObject:d(function(){return this.objectAt(f(this,"length")-1)}),contains:function(e){return this.indexOf(e)>=0},slice:function(e,t){var r=m.A(),n=f(this,"length");for(b(e)&&(e=0),(b(t)||t>n)&&(t=n),0>e&&(e=n+e),0>t&&(t=n+t);t>e;)r[r.length]=this.objectAt(e++);return r},indexOf:function(e,t){var r,n=f(this,"length");for(void 0===t&&(t=0),0>t&&(t+=n),r=t;n>r;r++)if(this.objectAt(r)===e)return r;return-1},lastIndexOf:function(e,t){var r,n=f(this,"length");for((void 0===t||t>=n)&&(t=n-1),0>t&&(t+=n),r=t;r>=0;r--)if(this.objectAt(r)===e)return r;return-1},addArrayObserver:function(e,t){return p(this,e,t,O,!1)},removeArrayObserver:function(e,t){return p(this,e,t,E,!0)},hasArrayObservers:d(function(){return A(this,"@array:change")||A(this,"@array:before")}),arrayContentWillChange:function(e,t,r){var n,i;if(void 0===e?(e=0,t=r=-1):(void 0===t&&(t=-1),void 0===r&&(r=-1)),T(this,"@each")&&f(this,"@each"),P(this,"@array:before",[this,e,t,r]),e>=0&&t>=0&&f(this,"hasEnumerableObservers")){n=[],i=e+t;for(var a=e;i>a;a++)n.push(this.objectAt(a))}else n=t;return this.enumerableContentWillChange(n,r),this},arrayContentDidChange:function(e,t,r){var n,i;if(void 0===e?(e=0,t=r=-1):(void 0===t&&(t=-1),void 0===r&&(r=-1)),e>=0&&r>=0&&f(this,"hasEnumerableObservers")){n=[],i=e+r;for(var a=e;i>a;a++)n.push(this.objectAt(a))}else n=r;this.enumerableContentDidChange(t,n),P(this,"@array:change",[this,e,t,r]);var s=f(this,"length"),o=v(this,"firstObject"),u=v(this,"lastObject");return this.objectAt(0)!==o&&(x(this,"firstObject"),C(this,"firstObject")),this.objectAt(s-1)!==u&&(x(this,"lastObject"),C(this,"lastObject")),this},"@each":d(function(){if(!this.__each){var e=t("ember-runtime/system/each_proxy").EachProxy;this.__each=new e(this)}return this.__each})})}),e("ember-runtime/mixins/comparable",["ember-metal/mixin","exports"],function(e,t){"use strict";var r=e.Mixin,n=e.required;t["default"]=r.create({compare:n(Function)})}),e("ember-runtime/mixins/controller",["ember-metal/core","ember-metal/property_get","ember-runtime/system/object","ember-metal/mixin","ember-metal/computed","ember-runtime/mixins/action_handler","ember-runtime/mixins/controller_content_model_alias_deprecation","exports"],function(e,t,r,n,i,a,s,o){"use strict";var u=(e["default"],t.get,r["default"],n.Mixin),l=i.computed,c=a["default"],h=s["default"];o["default"]=u.create(c,h,{isController:!0,target:null,container:null,parentController:null,store:null,model:null,content:l.alias("model")})}),e("ember-runtime/mixins/controller_content_model_alias_deprecation",["ember-metal/core","ember-metal/property_get","ember-metal/mixin","exports"],function(e,t,r,n){"use strict";var i=(e["default"],t.get,r.Mixin);n["default"]=i.create({willMergeMixin:function(e){this._super.apply(this,arguments);var t=!!e.model;e.content&&!t&&(e.model=e.content,delete e.content)}})}),e("ember-runtime/mixins/copyable",["ember-metal/property_get","ember-metal/property_set","ember-metal/mixin","ember-runtime/mixins/freezable","ember-runtime/system/string","ember-metal/error","exports"],function(e,t,r,n,i,a,s){"use strict";var o=e.get,u=(t.set,r.required),l=n.Freezable,c=r.Mixin,h=i.fmt,p=a["default"];s["default"]=c.create({copy:u(Function),frozenCopy:function(){if(l&&l.detect(this))return o(this,"isFrozen")?this:this.copy().freeze();throw new p(h("%@ does not support freezing",[this]))}})}),e("ember-runtime/mixins/deferred",["ember-metal/core","ember-metal/property_get","ember-metal/mixin","ember-metal/computed","ember-runtime/ext/rsvp","exports"],function(e,t,r,n,i,a){"use strict";var s=(e["default"],t.get),o=r.Mixin,u=n.computed,l=i["default"];a["default"]=o.create({then:function(e,t,r){function n(t){return e(t===a?o:t)}var i,a,o;return o=this,i=s(this,"_deferred"),a=i.promise,a.then(e&&n,t,r)},resolve:function(e){var t,r;t=s(this,"_deferred"),r=t.promise,t.resolve(e===this?r:e)},reject:function(e){s(this,"_deferred").reject(e)},_deferred:u(function(){return l.defer("Ember: DeferredMixin - "+this)})})}),e("ember-runtime/mixins/enumerable",["ember-metal/core","ember-metal/property_get","ember-metal/property_set","ember-metal/utils","ember-metal/mixin","ember-metal/enumerable_utils","ember-metal/computed","ember-metal/property_events","ember-metal/events","ember-runtime/compare","exports"],function(e,t,r,n,i,a,s,o,u,l,c){"use strict";function h(){return 0===V.length?{}:V.pop()}function p(e){return V.push(e),null}function m(e,t){function r(r){var i=d(r,e);return n?t===i:!!i}var n=2===arguments.length;return r}var f=e["default"],d=t.get,v=r.set,b=n.apply,y=i.Mixin,g=i.required,_=i.aliasMethod,w=a.indexOf,x=s.computed,C=o.propertyWillChange,O=o.propertyDidChange,E=u.addListener,P=u.removeListener,A=u.sendEvent,T=u.hasListeners,N=l["default"],S=Array.prototype.slice,V=[];c["default"]=y.create({nextObject:g(Function),firstObject:x("[]",function(){if(0===d(this,"length"))return void 0;var e,t=h();return e=this.nextObject(0,null,t),p(t),e}),lastObject:x("[]",function(){var e=d(this,"length");if(0===e)return void 0;var t,r=h(),n=0,i=null;do i=t,t=this.nextObject(n++,i,r);while(void 0!==t);return p(r),i}),contains:function(e){return void 0!==this.find(function(t){return t===e})},forEach:function(e,t){if("function"!=typeof e)throw new TypeError;var r=d(this,"length"),n=null,i=h();void 0===t&&(t=null);for(var a=0;r>a;a++){var s=this.nextObject(a,n,i);e.call(t,s,a,this),n=s}return n=null,i=p(i),this},getEach:function(e){return this.mapBy(e)},setEach:function(e,t){return this.forEach(function(r){v(r,e,t)})},map:function(e,t){var r=f.A();return this.forEach(function(n,i,a){r[i]=e.call(t,n,i,a)}),r},mapBy:function(e){return this.map(function(t){return d(t,e)})},mapProperty:_("mapBy"),filter:function(e,t){var r=f.A();return this.forEach(function(n,i,a){e.call(t,n,i,a)&&r.push(n)}),r},reject:function(e,t){return this.filter(function(){return!b(t,e,arguments)})},filterBy:function(){return this.filter(b(this,m,arguments))},filterProperty:_("filterBy"),rejectBy:function(e,t){var r=function(r){return d(r,e)===t},n=function(t){return!!d(t,e)},i=2===arguments.length?r:n;return this.reject(i)},rejectProperty:_("rejectBy"),find:function(e,t){var r=d(this,"length");void 0===t&&(t=null);for(var n,i,a=null,s=!1,o=h(),u=0;r>u&&!s;u++)n=this.nextObject(u,a,o),(s=e.call(t,n,u,this))&&(i=n),a=n;return n=a=null,o=p(o),i},findBy:function(){return this.find(b(this,m,arguments))},findProperty:_("findBy"),every:function(e,t){return!this.find(function(r,n,i){return!e.call(t,r,n,i)})},everyBy:_("isEvery"),everyProperty:_("isEvery"),isEvery:function(){return this.every(b(this,m,arguments))},any:function(e,t){var r,n,i=d(this,"length"),a=h(),s=!1,o=null;for(void 0===t&&(t=null),n=0;i>n&&!s;n++)r=this.nextObject(n,o,a),s=e.call(t,r,n,this),o=r;return r=o=null,a=p(a),s},some:_("any"),isAny:function(){return this.any(b(this,m,arguments))},anyBy:_("isAny"),someProperty:_("isAny"),reduce:function(e,t,r){if("function"!=typeof e)throw new TypeError;var n=t;return this.forEach(function(t,i){n=e(n,t,i,this,r)},this),n},invoke:function(e){var t,r=f.A();return arguments.length>1&&(t=S.call(arguments,1)),this.forEach(function(n,i){var a=n&&n[e];"function"==typeof a&&(r[i]=t?b(n,a,t):n[e]())},this),r},toArray:function(){var e=f.A();return this.forEach(function(t,r){e[r]=t}),e},compact:function(){return this.filter(function(e){return null!=e})},without:function(e){if(!this.contains(e))return this;var t=f.A();return this.forEach(function(r){r!==e&&(t[t.length]=r)}),t},uniq:function(){var e=f.A();return this.forEach(function(t){w(e,t)<0&&e.push(t)}),e},"[]":x(function(){return this}),addEnumerableObserver:function(e,t){var r=t&&t.willChange||"enumerableWillChange",n=t&&t.didChange||"enumerableDidChange",i=d(this,"hasEnumerableObservers");return i||C(this,"hasEnumerableObservers"),E(this,"@enumerable:before",e,r),E(this,"@enumerable:change",e,n),i||O(this,"hasEnumerableObservers"),this},removeEnumerableObserver:function(e,t){var r=t&&t.willChange||"enumerableWillChange",n=t&&t.didChange||"enumerableDidChange",i=d(this,"hasEnumerableObservers"); -return i&&C(this,"hasEnumerableObservers"),P(this,"@enumerable:before",e,r),P(this,"@enumerable:change",e,n),i&&O(this,"hasEnumerableObservers"),this},hasEnumerableObservers:x(function(){return T(this,"@enumerable:change")||T(this,"@enumerable:before")}),enumerableContentWillChange:function(e,t){var r,n,i;return r="number"==typeof e?e:e?d(e,"length"):e=-1,n="number"==typeof t?t:t?d(t,"length"):t=-1,i=0>n||0>r||n-r!==0,-1===e&&(e=null),-1===t&&(t=null),C(this,"[]"),i&&C(this,"length"),A(this,"@enumerable:before",[this,e,t]),this},enumerableContentDidChange:function(e,t){var r,n,i;return r="number"==typeof e?e:e?d(e,"length"):e=-1,n="number"==typeof t?t:t?d(t,"length"):t=-1,i=0>n||0>r||n-r!==0,-1===e&&(e=null),-1===t&&(t=null),A(this,"@enumerable:change",[this,e,t]),i&&O(this,"length"),O(this,"[]"),this},sortBy:function(){var e=arguments;return this.toArray().sort(function(t,r){for(var n=0;nn;n++)r[n-1]=arguments[n];o(this,e,r)},off:function(e,t,r){return a(this,e,t,r),this},has:function(e){return s(this,e)}})}),e("ember-runtime/mixins/freezable",["ember-metal/mixin","ember-metal/property_get","ember-metal/property_set","exports"],function(e,t,r,n){"use strict";var i=e.Mixin,a=t.get,s=r.set,o=i.create({isFrozen:!1,freeze:function(){return a(this,"isFrozen")?this:(s(this,"isFrozen",!0),this)}});n.Freezable=o;var u="Frozen object cannot be modified.";n.FROZEN_ERROR=u}),e("ember-runtime/mixins/mutable_array",["ember-metal/property_get","ember-metal/property_set","ember-metal/utils","ember-metal/error","ember-metal/mixin","ember-runtime/mixins/array","ember-runtime/mixins/mutable_enumerable","ember-runtime/mixins/enumerable","exports"],function(e,t,r,n,i,a,s,o,u){"use strict";var l="Index out of range",c=[],h=e.get,p=(t.set,r.isArray),m=n["default"],f=i.Mixin,d=i.required,v=a["default"],b=s["default"],y=o["default"];u["default"]=f.create(v,b,{replace:d(),clear:function(){var e=h(this,"length");return 0===e?this:(this.replace(0,e,c),this)},insertAt:function(e,t){if(e>h(this,"length"))throw new m(l);return this.replace(e,0,[t]),this},removeAt:function(e,t){if("number"==typeof e){if(0>e||e>=h(this,"length"))throw new m(l);void 0===t&&(t=1),this.replace(e,t,c)}return this},pushObject:function(e){return this.insertAt(h(this,"length"),e),e},pushObjects:function(e){if(!y.detect(e)&&!p(e))throw new TypeError("Must pass Ember.Enumerable to Ember.MutableArray#pushObjects");return this.replace(h(this,"length"),0,e),this},popObject:function(){var e=h(this,"length");if(0===e)return null;var t=this.objectAt(e-1);return this.removeAt(e-1,1),t},shiftObject:function(){if(0===h(this,"length"))return null;var e=this.objectAt(0);return this.removeAt(0),e},unshiftObject:function(e){return this.insertAt(0,e),e},unshiftObjects:function(e){return this.replace(0,0,e),this},reverseObjects:function(){var e=h(this,"length");if(0===e)return this;var t=this.toArray().reverse();return this.replace(0,e,t),this},setObjects:function(e){if(0===e.length)return this.clear();var t=h(this,"length");return this.replace(0,t,e),this},removeObject:function(e){for(var t=h(this,"length")||0;--t>=0;){var r=this.objectAt(t);r===e&&this.removeAt(t)}return this},addObject:function(e){return this.contains(e)||this.pushObject(e),this}})}),e("ember-runtime/mixins/mutable_enumerable",["ember-metal/enumerable_utils","ember-runtime/mixins/enumerable","ember-metal/mixin","ember-metal/property_events","exports"],function(e,t,r,n,i){"use strict";var a=e.forEach,s=t["default"],o=r.Mixin,u=r.required,l=n.beginPropertyChanges,c=n.endPropertyChanges;i["default"]=o.create(s,{addObject:u(Function),addObjects:function(e){return l(this),a(e,function(e){this.addObject(e)},this),c(this),this},removeObject:u(Function),removeObjects:function(e){l(this);for(var t=e.length-1;t>=0;t--)this.removeObject(e[t]);return c(this),this}})}),e("ember-runtime/mixins/observable",["ember-metal/core","ember-metal/property_get","ember-metal/property_set","ember-metal/utils","ember-metal/get_properties","ember-metal/set_properties","ember-metal/mixin","ember-metal/events","ember-metal/property_events","ember-metal/observer","ember-metal/computed","ember-metal/is_none","exports"],function(e,t,r,n,i,a,s,o,u,l,c,h,p){"use strict";var m=(e["default"],t.get),f=t.getWithDefault,d=r.set,v=n.apply,b=i["default"],y=a["default"],g=s.Mixin,_=o.hasListeners,w=u.beginPropertyChanges,x=u.propertyWillChange,C=u.propertyDidChange,O=u.endPropertyChanges,E=l.addObserver,P=l.addBeforeObserver,A=l.removeObserver,T=l.observersFor,N=c.cacheFor,S=h.isNone,V=Array.prototype.slice;p["default"]=g.create({get:function(e){return m(this,e)},getProperties:function(){return v(null,b,[this].concat(V.call(arguments)))},set:function(e,t){return d(this,e,t),this},setProperties:function(e){return y(this,e)},beginPropertyChanges:function(){return w(),this},endPropertyChanges:function(){return O(),this},propertyWillChange:function(e){return x(this,e),this},propertyDidChange:function(e){return C(this,e),this},notifyPropertyChange:function(e){return this.propertyWillChange(e),this.propertyDidChange(e),this},addBeforeObserver:function(e,t,r){P(this,e,t,r)},addObserver:function(e,t,r){E(this,e,t,r)},removeObserver:function(e,t,r){A(this,e,t,r)},hasObserverFor:function(e){return _(this,e+":change")},getWithDefault:function(e,t){return f(this,e,t)},incrementProperty:function(e,t){return S(t)&&(t=1),d(this,e,(parseFloat(m(this,e))||0)+t),m(this,e)},decrementProperty:function(e,t){return S(t)&&(t=1),d(this,e,(m(this,e)||0)-t),m(this,e)},toggleProperty:function(e){return d(this,e,!m(this,e)),m(this,e)},cacheFor:function(e){return N(this,e)},observersForKey:function(e){return T(this,e)}})}),e("ember-runtime/mixins/promise_proxy",["ember-metal/property_get","ember-metal/set_properties","ember-metal/computed","ember-metal/mixin","ember-metal/error","exports"],function(e,t,r,n,i,a){"use strict";function s(e,t){return l(e,{isFulfilled:!1,isRejected:!1}),t.then(function(t){return l(e,{content:t,isFulfilled:!0}),t},function(t){throw l(e,{reason:t,isRejected:!0}),t},"Ember: PromiseProxy")}function o(e){return function(){var t=u(this,"promise");return t[e].apply(t,arguments)}}var u=e.get,l=t["default"],c=r.computed,h=n.Mixin,p=i["default"],m=c.not,f=c.or;a["default"]=h.create({reason:null,isPending:m("isSettled").readOnly(),isSettled:f("isRejected","isFulfilled").readOnly(),isRejected:!1,isFulfilled:!1,promise:c(function(e,t){if(2===arguments.length)return s(this,t);throw new p("PromiseProxy's promise must be set")}),then:o("then"),"catch":o("catch"),"finally":o("finally")})}),e("ember-runtime/mixins/sortable",["ember-metal/core","ember-metal/property_get","ember-metal/property_set","ember-metal/enumerable_utils","ember-metal/mixin","ember-runtime/mixins/mutable_enumerable","ember-runtime/compare","ember-metal/observer","ember-metal/computed","exports"],function(e,t,r,n,i,a,s,o,u,l){"use strict";var c=e["default"],h=t.get,p=(r.set,n.forEach),m=i.Mixin,f=a["default"],d=s["default"],v=o.addObserver,b=o.removeObserver,y=u.computed,g=i.beforeObserver,_=i.observer;l["default"]=m.create(f,{sortProperties:null,sortAscending:!0,sortFunction:d,orderBy:function(e,t){var r=0,n=h(this,"sortProperties"),i=h(this,"sortAscending"),a=h(this,"sortFunction");return p(n,function(n){0===r&&(r=a.call(this,h(e,n),h(t,n)),0===r||i||(r=-1*r))},this),r},destroy:function(){var e=h(this,"content"),t=h(this,"sortProperties");return e&&t&&p(e,function(e){p(t,function(t){b(e,t,this,"contentItemSortPropertyDidChange")},this)},this),this._super()},isSorted:y.notEmpty("sortProperties"),arrangedContent:y("content","sortProperties.@each",function(){var e=h(this,"content"),t=h(this,"isSorted"),r=h(this,"sortProperties"),n=this;return e&&t?(e=e.slice(),e.sort(function(e,t){return n.orderBy(e,t)}),p(e,function(e){p(r,function(t){v(e,t,this,"contentItemSortPropertyDidChange")},this)},this),c.A(e)):e}),_contentWillChange:g("content",function(){var e=h(this,"content"),t=h(this,"sortProperties");e&&t&&p(e,function(e){p(t,function(t){b(e,t,this,"contentItemSortPropertyDidChange")},this)},this),this._super()}),sortPropertiesWillChange:g("sortProperties",function(){this._lastSortAscending=void 0}),sortPropertiesDidChange:_("sortProperties",function(){this._lastSortAscending=void 0}),sortAscendingWillChange:g("sortAscending",function(){this._lastSortAscending=h(this,"sortAscending")}),sortAscendingDidChange:_("sortAscending",function(){if(void 0!==this._lastSortAscending&&h(this,"sortAscending")!==this._lastSortAscending){var e=h(this,"arrangedContent");e.reverseObjects()}}),contentArrayWillChange:function(e,t,r,n){var i=h(this,"isSorted");if(i){var a=h(this,"arrangedContent"),s=e.slice(t,t+r),o=h(this,"sortProperties");p(s,function(e){a.removeObject(e),p(o,function(t){b(e,t,this,"contentItemSortPropertyDidChange")},this)},this)}return this._super(e,t,r,n)},contentArrayDidChange:function(e,t,r,n){var i=h(this,"isSorted"),a=h(this,"sortProperties");if(i){var s=e.slice(t,t+n);p(s,function(e){this.insertItemSorted(e),p(a,function(t){v(e,t,this,"contentItemSortPropertyDidChange")},this)},this)}return this._super(e,t,r,n)},insertItemSorted:function(e){var t=h(this,"arrangedContent"),r=h(t,"length"),n=this._binarySearch(e,0,r);t.insertAt(n,e)},contentItemSortPropertyDidChange:function(e){var t=h(this,"arrangedContent"),r=t.indexOf(e),n=t.objectAt(r-1),i=t.objectAt(r+1),a=n&&this.orderBy(e,n),s=i&&this.orderBy(e,i);(0>a||s>0)&&(t.removeObject(e),this.insertItemSorted(e))},_binarySearch:function(e,t,r){var n,i,a,s;return t===r?t:(s=h(this,"arrangedContent"),n=t+Math.floor((r-t)/2),i=s.objectAt(n),a=this.orderBy(i,e),0>a?this._binarySearch(e,n+1,r):a>0?this._binarySearch(e,t,n):n)}})}),e("ember-runtime/mixins/target_action_support",["ember-metal/core","ember-metal/property_get","ember-metal/property_set","ember-metal/utils","ember-metal/mixin","ember-metal/computed","exports"],function(e,t,r,n,i,a,s){"use strict";var o=e["default"],u=t.get,l=(r.set,n.typeOf),c=i.Mixin,h=a.computed,p=c.create({target:null,action:null,actionContext:null,targetObject:h(function(){var e=u(this,"target");if("string"===l(e)){var t=u(this,e);return void 0===t&&(t=u(o.lookup,e)),t}return e}).property("target"),actionContextObject:h(function(){var e=u(this,"actionContext");if("string"===l(e)){var t=u(this,e);return void 0===t&&(t=u(o.lookup,e)),t}return e}).property("actionContext"),triggerAction:function(e){function t(e,t){var r=[];return t&&r.push(t),r.concat(e)}e=e||{};var r=e.action||u(this,"action"),n=e.target||u(this,"targetObject"),i=e.actionContext;if("undefined"==typeof i&&(i=u(this,"actionContextObject")||this),n&&r){var a;return a=n.send?n.send.apply(n,t(i,r)):n[r].apply(n,t(i)),a!==!1&&(a=!0),a}return!1}});s["default"]=p}),e("ember-runtime/system/application",["ember-runtime/system/namespace","exports"],function(e,t){"use strict";var r=e["default"];t["default"]=r.extend()}),e("ember-runtime/system/array_proxy",["ember-metal/core","ember-metal/property_get","ember-metal/property_set","ember-metal/utils","ember-metal/computed","ember-metal/mixin","ember-metal/property_events","ember-metal/error","ember-runtime/system/object","ember-runtime/mixins/mutable_array","ember-runtime/mixins/enumerable","ember-runtime/system/string","exports"],function(e,t,r,n,i,a,s,o,u,l,c,h,p){"use strict";var m=e["default"],f=t.get,d=(r.set,n.isArray),v=n.apply,b=i.computed,y=a.beforeObserver,g=a.observer,_=s.beginPropertyChanges,w=s.endPropertyChanges,x=o["default"],C=u["default"],O=l["default"],E=c["default"],P=(h.fmt,"Index out of range"),A=[],T=b.alias,N=m.K,S=C.extend(O,{content:null,arrangedContent:T("content"),objectAtContent:function(e){return f(this,"arrangedContent").objectAt(e)},replaceContent:function(e,t,r){f(this,"content").replace(e,t,r)},_contentWillChange:y("content",function(){this._teardownContent()}),_teardownContent:function(){var e=f(this,"content");e&&e.removeArrayObserver(this,{willChange:"contentArrayWillChange",didChange:"contentArrayDidChange"})},contentArrayWillChange:N,contentArrayDidChange:N,_contentDidChange:g("content",function(){f(this,"content");this._setupContent()}),_setupContent:function(){var e=f(this,"content");e&&e.addArrayObserver(this,{willChange:"contentArrayWillChange",didChange:"contentArrayDidChange"})},_arrangedContentWillChange:y("arrangedContent",function(){var e=f(this,"arrangedContent"),t=e?f(e,"length"):0;this.arrangedContentArrayWillChange(this,0,t,void 0),this.arrangedContentWillChange(this),this._teardownArrangedContent(e)}),_arrangedContentDidChange:g("arrangedContent",function(){var e=f(this,"arrangedContent"),t=e?f(e,"length"):0;this._setupArrangedContent(),this.arrangedContentDidChange(this),this.arrangedContentArrayDidChange(this,0,void 0,t)}),_setupArrangedContent:function(){var e=f(this,"arrangedContent");e&&e.addArrayObserver(this,{willChange:"arrangedContentArrayWillChange",didChange:"arrangedContentArrayDidChange"})},_teardownArrangedContent:function(){var e=f(this,"arrangedContent");e&&e.removeArrayObserver(this,{willChange:"arrangedContentArrayWillChange",didChange:"arrangedContentArrayDidChange"})},arrangedContentWillChange:N,arrangedContentDidChange:N,objectAt:function(e){return f(this,"content")&&this.objectAtContent(e)},length:b(function(){var e=f(this,"arrangedContent");return e?f(e,"length"):0}),_replace:function(e,t,r){var n=f(this,"content");return n&&this.replaceContent(e,t,r),this},replace:function(){if(f(this,"arrangedContent")!==f(this,"content"))throw new x("Using replace on an arranged ArrayProxy is not allowed.");v(this,this._replace,arguments)},_insertAt:function(e,t){if(e>f(this,"content.length"))throw new x(P);return this._replace(e,0,[t]),this},insertAt:function(e,t){if(f(this,"arrangedContent")===f(this,"content"))return this._insertAt(e,t);throw new x("Using insertAt on an arranged ArrayProxy is not allowed.")},removeAt:function(e,t){if("number"==typeof e){var r,n=f(this,"content"),i=f(this,"arrangedContent"),a=[];if(0>e||e>=f(this,"length"))throw new x(P);for(void 0===t&&(t=1),r=e;e+t>r;r++)a.push(n.indexOf(i.objectAt(r)));for(a.sort(function(e,t){return t-e}),_(),r=0;rl;l++){var h=o[l];if("object"!=typeof h&&void 0!==h)throw new M("Ember.Object.create only accepts objects.");if(h)for(var p=L(h),m=0,f=p.length;f>m;m++){var d=p[m];if(h.hasOwnProperty(d)){var v=h[d];if(I.test(d)){var b=i.bindings;b?i.hasOwnProperty("bindings")||(b=i.bindings=O(i.bindings)):b=i.bindings={},b[d]=v}var y=i.descs[d];if(u&&j(u,d)>=0){var g=this[d];v=g?"function"==typeof g.concat?g.concat(v):T(g).concat(v):T(v)}y?y.set(this,d,v):"function"!=typeof this.setUnknownProperty||d in this?this[d]=v:this.setUnknownProperty(d,v)}}}}W(this,i);for(var _=arguments.length,w=new Array(_),x=0;_>x;x++)w[x]=arguments[x];C(this,this.init,w),i.proto=a,S(this),V(this,"init")};return n.toString=k.prototype.toString,n.willReopen=function(){r&&(n.PrototypeMixin=k.create(n.PrototypeMixin)),r=!1},n._initMixins=function(t){e=t},n._initProperties=function(e){t=e},n.proto=function(){var e=n.superclass;return e&&e.proto(),r||(r=!0,n.PrototypeMixin.applyPartial(n.prototype),N(n.prototype)),this.prototype},n}function g(e){return function(){return e}}var _=e["default"],w=t.get,x=(r.set,n.guidFor),C=n.apply,O=i.create,E=n.generateGuid,P=n.GUID_KEY,A=n.meta,T=n.makeArray,N=a.rewatch,S=s.finishChains,V=o.sendEvent,I=u.IS_BINDING,k=u.Mixin,D=u.required,j=l.indexOf,M=c["default"],R=i.defineProperty,L=h["default"],H=(p["default"],m.defineProperty,f.Binding),z=d.ComputedProperty,q=v["default"],F=a.destroy,B=e.K,U=(i.hasPropertyAccessors,q.schedule),K=k._apply,W=k.finishPartial,G=k.prototype.reopen,Q=!1,$={configurable:!0,writable:!0,enumerable:!1,value:void 0},Y={configurable:!0,writable:!0,enumerable:!1,value:null},J=y();J.toString=function(){return"Ember.CoreObject"},J.PrototypeMixin=k.create({reopen:function(){for(var e=arguments.length,t=new Array(e),r=0;e>r;r++)t[r]=arguments[r];return K(this,t,!0),this},init:function(){},concatenatedProperties:null,isDestroyed:!1,isDestroying:!1,destroy:function(){return this.isDestroying?void 0:(this.isDestroying=!0,U("actions",this,this.willDestroy),U("destroy",this,this._scheduledDestroy),this)},willDestroy:B,_scheduledDestroy:function(){this.isDestroyed||(F(this),this.isDestroyed=!0)},bind:function(e,t){return t instanceof H||(t=H.from(t)),t.to(e).connect(this),t},toString:function(){var e="function"==typeof this.toStringExtension,t=e?":"+this.toStringExtension():"",r="<"+this.constructor.toString()+":"+x(this)+t+">";return this.toString=g(r),r}}),J.PrototypeMixin.ownerConstructor=J,_.config.overridePrototypeMixin&&_.config.overridePrototypeMixin(J.PrototypeMixin),J.__super__=null;var Z=k.create({ClassMixin:D(),PrototypeMixin:D(),isClass:!0,isMethod:!1,extend:function(){var e,t=y();return t.ClassMixin=k.create(this.ClassMixin),t.PrototypeMixin=k.create(this.PrototypeMixin),t.ClassMixin.ownerConstructor=t,t.PrototypeMixin.ownerConstructor=t,G.apply(t.PrototypeMixin,arguments),t.superclass=this,t.__super__=this.prototype,e=t.prototype=O(this.prototype),e.constructor=t,E(e),A(e).proto=e,t.ClassMixin.apply(t),t},createWithMixins:function(){var e=this,t=arguments.length;if(t>0){for(var r=new Array(t),n=0;t>n;n++)r[n]=arguments[n];this._initMixins(r)}return new e},create:function(){var e=this,t=arguments.length;if(t>0){for(var r=new Array(t),n=0;t>n;n++)r[n]=arguments[n];this._initProperties(r)}return new e},reopen:function(){this.willReopen();var e=arguments.length,t=new Array(e);if(e>0)for(var r=0;e>r;r++)t[r]=arguments[r];return C(this.PrototypeMixin,G,t),this},reopenClass:function(){var e=arguments.length,t=new Array(e);if(e>0)for(var r=0;e>r;r++)t[r]=arguments[r];return C(this.ClassMixin,G,t),K(this,arguments,!1),this},detect:function(e){if("function"!=typeof e)return!1;for(;e;){if(e===this)return!0;e=e.superclass}return!1},detectInstance:function(e){return e instanceof this},metaForProperty:function(e){var t=this.proto().__ember_meta__,r=t&&t.descs[e];return r._meta||{}},_computedProperties:_.computed(function(){Q=!0;var e,t=this.proto(),r=A(t).descs,n=[];for(var i in r)e=r[i],e instanceof z&&n.push({name:i,meta:e._meta});return n}).readOnly(),eachComputedProperty:function(e,t){for(var r,n,i={},a=w(this,"_computedProperties"),s=0,o=a.length;o>s;s++)r=a[s],n=r.name,e.call(t||this,r.name,r.meta||i)}});Z.ownerConstructor=J,_.config.overrideClassMixin&&_.config.overrideClassMixin(Z),J.ClassMixin=Z,Z.apply(J),J.reopen({didDefineProperty:function(e,t,r){if(Q!==!1&&r instanceof _.ComputedProperty){var n=_.meta(this.constructor).cache;void 0!==n._computedProperties&&(n._computedProperties=void 0)}}}),b["default"]=J}),e("ember-runtime/system/deferred",["ember-metal/core","ember-runtime/mixins/deferred","ember-metal/property_get","ember-runtime/system/object","exports"],function(e,t,r,n,i){"use strict";var a=(e["default"],t["default"]),s=(r.get,n["default"]),o=s.extend(a,{init:function(){this._super()}});o.reopenClass({promise:function(e,t){var r=o.create();return e.call(t,r),r}}),i["default"]=o}),e("ember-runtime/system/each_proxy",["ember-metal/core","ember-metal/property_get","ember-metal/property_set","ember-metal/utils","ember-metal/enumerable_utils","ember-metal/array","ember-runtime/mixins/array","ember-runtime/system/object","ember-metal/computed","ember-metal/observer","ember-metal/events","ember-metal/properties","ember-metal/property_events","exports"],function(e,t,r,n,i,a,s,o,u,l,c,h,p,m){"use strict";function f(e,t,r,n,i){var a,s=r._objects;for(s||(s=r._objects={});--i>=n;){var o=e.objectAt(i);o&&(O(o,t,r,"contentKeyWillChange"),C(o,t,r,"contentKeyDidChange"),a=b(o),s[a]||(s[a]=[]),s[a].push(i))}}function d(e,t,r,n,i){var a=r._objects;a||(a=r._objects={});for(var s,o;--i>=n;){var u=e.objectAt(i);u&&(E(u,t,r,"contentKeyWillChange"),P(u,t,r,"contentKeyDidChange"),o=b(u),s=a[o],s[g.call(s,i)]=null)}}var v=(e["default"],t.get),b=(r.set,n.guidFor),y=i.forEach,g=a.indexOf,_=s["default"],w=o["default"],x=u.computed,C=l.addObserver,O=l.addBeforeObserver,E=l.removeBeforeObserver,P=l.removeObserver,A=(n.typeOf,c.watchedEvents),T=h.defineProperty,N=p.beginPropertyChanges,S=p.propertyDidChange,V=p.propertyWillChange,I=p.endPropertyChanges,k=p.changeProperties,D=w.extend(_,{init:function(e,t,r){this._super(),this._keyName=t,this._owner=r,this._content=e},objectAt:function(e){var t=this._content.objectAt(e);return t&&v(t,this._keyName)},length:x(function(){var e=this._content;return e?v(e,"length"):0})}),j=/^.+:(before|change)$/,M=w.extend({init:function(e){this._super(),this._content=e,e.addArrayObserver(this),y(A(this),function(e){this.didAddListener(e)},this)},unknownProperty:function(e){var t;return t=new D(this._content,e,this),T(this,e,null,t),this.beginObservingContentKey(e),t},arrayWillChange:function(e,t,r){var n,i,a=this._keys;i=r>0?t+r:-1,N(this);for(n in a)a.hasOwnProperty(n)&&(i>0&&d(e,n,this,t,i),V(this,n));V(this._content,"@each"),I(this)},arrayDidChange:function(e,t,r,n){var i,a=this._keys;i=n>0?t+n:-1,k(function(){for(var r in a)a.hasOwnProperty(r)&&(i>0&&f(e,r,this,t,i),S(this,r));S(this._content,"@each")},this)},didAddListener:function(e){j.test(e)&&this.beginObservingContentKey(e.slice(0,-7))},didRemoveListener:function(e){j.test(e)&&this.stopObservingContentKey(e.slice(0,-7))},beginObservingContentKey:function(e){var t=this._keys;if(t||(t=this._keys={}),t[e])t[e]++;else{t[e]=1;var r=this._content,n=v(r,"length");f(r,e,this,0,n)}},stopObservingContentKey:function(e){var t=this._keys;if(t&&t[e]>0&&--t[e]<=0){var r=this._content,n=v(r,"length");d(r,e,this,0,n)}},contentKeyWillChange:function(e,t){V(this,t)},contentKeyDidChange:function(e,t){S(this,t)}});m.EachArray=D,m.EachProxy=M}),e("ember-runtime/system/lazy_load",["ember-metal/core","ember-metal/array","ember-runtime/system/native_array","exports"],function(e,t,r,n){"use strict";function i(e,t){var r;u[e]=u[e]||s.A(),u[e].pushObject(t),(r=l[e])&&t(r)}function a(e,t){if(l[e]=t,"object"==typeof window&&"function"==typeof window.dispatchEvent&&"function"==typeof CustomEvent){var r=new CustomEvent(e,{detail:t,name:e});window.dispatchEvent(r)}u[e]&&o.call(u[e],function(e){e(t)})}var s=e["default"],o=t.forEach,u=s.ENV.EMBER_LOAD_HOOKS||{},l={};n.onLoad=i,n.runLoadHooks=a}),e("ember-runtime/system/namespace",["ember-metal/core","ember-metal/property_get","ember-metal/array","ember-metal/utils","ember-metal/mixin","ember-runtime/system/object","exports"],function(e,t,r,n,i,a,s){"use strict";function o(e,t,r){var n=e.length;x[e.join(".")]=t;for(var i in t)if(C.call(t,i)){var a=t[i];if(e[n]=i,a&&a.toString===h)a.toString=m(e.join(".")),a[E]=e.join(".");else if(a&&a.isNamespace){if(r[y(a)])continue;r[y(a)]=!0,o(e,a,r)}}e.length=n}function u(e,t){try{var r=e[t];return r&&r.isNamespace&&r}catch(n){}}function l(){var e,t=f.lookup;if(!w.PROCESSED)for(var r in t)O.test(r)&&(!t.hasOwnProperty||t.hasOwnProperty(r))&&(e=u(t,r),e&&(e[E]=r))}function c(e){var t=e.superclass;return t?t[E]?t[E]:c(t):void 0}function h(){f.BOOTED||this[E]||p();var e;if(this[E])e=this[E];else if(this._toString)e=this._toString;else{var t=c(this);e=t?"(subclass of "+t+")":"(unknown mixin)",this.toString=m(e)}return e}function p(){var e=!w.PROCESSED,t=f.anyUnprocessedMixins;if(e&&(l(),w.PROCESSED=!0),e||t){for(var r,n=w.NAMESPACES,i=0,a=n.length;a>i;i++)r=n[i],o([r.toString()],r,{});f.anyUnprocessedMixins=!1}}function m(e){return function(){return e}}var f=e["default"],d=t.get,v=r.indexOf,b=n.GUID_KEY,y=n.guidFor,g=i.Mixin,_=a["default"],w=_.extend({isNamespace:!0,init:function(){w.NAMESPACES.push(this),w.PROCESSED=!1},toString:function(){var e=d(this,"name")||d(this,"modulePrefix");return e?e:(l(),this[E])},nameClasses:function(){o([this.toString()],this,{})},destroy:function(){var e=w.NAMESPACES,t=this.toString();t&&(f.lookup[t]=void 0,delete w.NAMESPACES_BY_ID[t]),e.splice(v.call(e,this),1),this._super()}});w.reopenClass({NAMESPACES:[f],NAMESPACES_BY_ID:{},PROCESSED:!1,processAll:p,byName:function(e){return f.BOOTED||p(),x[e]}});var x=w.NAMESPACES_BY_ID,C={}.hasOwnProperty,O=/^[A-Z]/,E=f.NAME_KEY=b+"_name";g.prototype.toString=h,s["default"]=w}),e("ember-runtime/system/native_array",["ember-metal/core","ember-metal/property_get","ember-metal/property_set","ember-metal/enumerable_utils","ember-metal/mixin","ember-metal/array","ember-runtime/mixins/array","ember-runtime/mixins/mutable_array","ember-runtime/mixins/observable","ember-runtime/mixins/copyable","ember-runtime/mixins/freezable","ember-runtime/copy","exports"],function(e,t,r,n,i,a,s,o,u,l,c,h,p){"use strict";var m=e["default"],f=t.get,d=(r.set,n._replace),v=n.forEach,b=i.Mixin,y=a.indexOf,g=a.lastIndexOf,_=s["default"],w=o["default"],x=u["default"],C=l["default"],O=c.FROZEN_ERROR,E=h["default"],P=b.create(w,x,C,{get:function(e){return"length"===e?this.length:"number"==typeof e?this[e]:this._super(e)},objectAt:function(e){return this[e]},replace:function(e,t,r){if(this.isFrozen)throw O;var n=r?f(r,"length"):0;return this.arrayContentWillChange(e,t,n),0===n?this.splice(e,t):d(this,e,t,r),this.arrayContentDidChange(e,t,n),this},unknownProperty:function(e,t){var r;return void 0!==t&&void 0===r&&(r=this[e]=t),r},indexOf:y,lastIndexOf:g,copy:function(e){return e?this.map(function(e){return E(e,!0)}):this.slice()}}),A=["length"];v(P.keys(),function(e){Array.prototype[e]&&A.push(e)}),A.length>0&&(P=P.without.apply(P,A));var T=function(e){return void 0===e&&(e=[]),_.detect(e)?e:P.apply(e)};P.activate=function(){P.apply(Array.prototype),T=function(e){return e||[]}},(m.EXTEND_PROTOTYPES===!0||m.EXTEND_PROTOTYPES.Array)&&P.activate(),m.A=T,p.A=T,p.NativeArray=P,p["default"]=P}),e("ember-runtime/system/object",["ember-runtime/system/core_object","ember-runtime/mixins/observable","exports"],function(e,t,r){"use strict";var n=e["default"],i=t["default"],a=n.extend(i);a.toString=function(){return"Ember.Object"},r["default"]=a}),e("ember-runtime/system/object_proxy",["ember-runtime/system/object","ember-runtime/mixins/-proxy","exports"],function(e,t,r){"use strict";var n=e["default"],i=t["default"];r["default"]=n.extend(i)}),e("ember-runtime/system/set",["ember-metal/core","ember-metal/property_get","ember-metal/property_set","ember-metal/utils","ember-metal/is_none","ember-runtime/system/string","ember-runtime/system/core_object","ember-runtime/mixins/mutable_enumerable","ember-runtime/mixins/enumerable","ember-runtime/mixins/copyable","ember-runtime/mixins/freezable","ember-metal/error","ember-metal/property_events","ember-metal/mixin","ember-metal/computed","exports"],function(e,t,r,n,i,a,s,o,u,l,c,h,p,m,f,d){"use strict";var v=(e["default"],t.get),b=r.set,y=n.guidFor,g=i.isNone,_=a.fmt,w=s["default"],x=o["default"],C=u["default"],O=l["default"],E=c.Freezable,P=c.FROZEN_ERROR,A=h["default"],T=p.propertyWillChange,N=p.propertyDidChange,S=m.aliasMethod,V=f.computed;d["default"]=w.extend(x,O,E,{length:0,clear:function(){if(this.isFrozen)throw new A(P);var e=v(this,"length");if(0===e)return this;var t;this.enumerableContentWillChange(e,0),T(this,"firstObject"),T(this,"lastObject");for(var r=0;e>r;r++)t=y(this[r]),delete this[t],delete this[r];return b(this,"length",0),N(this,"firstObject"),N(this,"lastObject"),this.enumerableContentDidChange(e,0),this},isEqual:function(e){if(!C.detect(e))return!1;var t=v(this,"length");if(v(e,"length")!==t)return!1;for(;--t>=0;)if(!e.contains(this[t]))return!1;return!0},add:S("addObject"),remove:S("removeObject"),pop:function(){if(v(this,"isFrozen"))throw new A(P);var e=this.length>0?this[this.length-1]:null;return this.remove(e),e},push:S("addObject"),shift:S("pop"),unshift:S("push"),addEach:S("addObjects"),removeEach:S("removeObjects"),init:function(e){this._super(),e&&this.addObjects(e)},nextObject:function(e){return this[e]},firstObject:V(function(){return this.length>0?this[0]:void 0}),lastObject:V(function(){return this.length>0?this[this.length-1]:void 0}),addObject:function(e){if(v(this,"isFrozen"))throw new A(P);if(g(e))return this;var t,r=y(e),n=this[r],i=v(this,"length");return n>=0&&i>n&&this[n]===e?this:(t=[e],this.enumerableContentWillChange(null,t),T(this,"lastObject"),i=v(this,"length"),this[r]=i,this[i]=e,b(this,"length",i+1),N(this,"lastObject"),this.enumerableContentDidChange(null,t),this)},removeObject:function(e){if(v(this,"isFrozen"))throw new A(P);if(g(e))return this;var t,r,n=y(e),i=this[n],a=v(this,"length"),s=0===i,o=i===a-1;return i>=0&&a>i&&this[i]===e&&(r=[e],this.enumerableContentWillChange(r,null),s&&T(this,"firstObject"),o&&T(this,"lastObject"),a-1>i&&(t=this[a-1],this[i]=t,this[y(t)]=i),delete this[n],delete this[a-1],b(this,"length",a-1),s&&N(this,"firstObject"),o&&N(this,"lastObject"),this.enumerableContentDidChange(r,null)),this},contains:function(e){return this[y(e)]>=0},copy:function(){var e=this.constructor,t=new e,r=v(this,"length");for(b(t,"length",r);--r>=0;)t[r]=this[r],t[y(this[r])]=r;return t},toString:function(){var e,t=this.length,r=[];for(e=0;t>e;e++)r[e]=this[e];return _("Ember.Set<%@>",[r.join(",")])}})}),e("ember-runtime/system/string",["ember-metal/core","ember-metal/utils","ember-metal/cache","exports"],function(e,t,r,n){"use strict";function i(e,t){var r=t;if(!f(r)||arguments.length>2){r=new Array(arguments.length-1);for(var n=1,i=arguments.length;i>n;n++)r[n-1]=arguments[n]}var a=0;return e.replace(/%@([0-9]+)?/g,function(e,t){return t=t?parseInt(t,10)-1:a++,e=r[t],null===e?"(null)":void 0===e?"":d(e)})}function a(e,t){return(!f(t)||arguments.length>2)&&(t=Array.prototype.slice.call(arguments,1)),e=m.STRINGS[e]||e,i(e,t)}function s(e){return e.split(/\s+/)}function o(e){return C.get(e)}function u(e){return y.get(e)}function l(e){return g.get(e)}function c(e){return _.get(e)}function h(e){return w.get(e) -}function p(e){return x.get(e)}var m=e["default"],f=t.isArray,d=t.inspect,v=r["default"],b=/[ _]/g,y=new v(1e3,function(e){return o(e).replace(b,"-")}),g=new v(1e3,function(e){return e.replace(E,function(e,t,r){return r?r.toUpperCase():""}).replace(/^([A-Z])/,function(e){return e.toLowerCase()})}),_=new v(1e3,function(e){for(var t=e.split("."),r=[],n=0,i=t.length;i>n;n++){var a=l(t[n]);r.push(a.charAt(0).toUpperCase()+a.substr(1))}return r.join(".")}),w=new v(1e3,function(e){return e.replace(P,"$1_$2").replace(A,"_").toLowerCase()}),x=new v(1e3,function(e){return e.charAt(0).toUpperCase()+e.substr(1)}),C=new v(1e3,function(e){return e.replace(O,"$1_$2").toLowerCase()}),O=/([a-z\d])([A-Z])/g,E=/(\-|_|\.|\s)+(.)?/g,P=/([a-z\d])([A-Z]+)/g,A=/\-|\s+/g;m.STRINGS={},n["default"]={fmt:i,loc:a,w:s,decamelize:o,dasherize:u,camelize:l,classify:c,underscore:h,capitalize:p},n.fmt=i,n.loc=a,n.w=s,n.decamelize=o,n.dasherize=u,n.camelize=l,n.classify=c,n.underscore=h,n.capitalize=p}),e("ember-runtime/system/subarray",["ember-metal/property_get","ember-metal/error","ember-metal/enumerable_utils","exports"],function(e,t,r,n){"use strict";function i(e,t){this.type=e,this.count=t}function a(e){arguments.length<1&&(e=0),this._operations=e>0?[new i(u,e)]:[]}var s=(e.get,t["default"]),o=r["default"],u="r",l="f";n["default"]=a,a.prototype={addItem:function(e,t){var r=-1,n=t?u:l,a=this;return this._findOperation(e,function(s,o,l,c,h){var p,m;n===s.type?++s.count:e===l?a._operations.splice(o,0,new i(n,1)):(p=new i(n,1),m=new i(s.type,c-e+1),s.count=e-l,a._operations.splice(o+1,0,p,m)),t&&(r=s.type===u?h+(e-l):h),a._composeAt(o)},function(e){a._operations.push(new i(n,1)),t&&(r=e),a._composeAt(a._operations.length-1)}),r},removeItem:function(e){var t=-1,r=this;return this._findOperation(e,function(n,i,a,s,o){n.type===u&&(t=o+(e-a)),n.count>1?--n.count:(r._operations.splice(i,1),r._composeAt(i))},function(){throw new s("Can't remove an item that has never been added.")}),t},_findOperation:function(e,t,r){var n,i,a,s,o,l=0;for(n=s=0,i=this._operations.length;i>n;s=o+1,++n){if(a=this._operations[n],o=s+a.count-1,e>=s&&o>=e)return void t(a,n,s,o,l);a.type===u&&(l+=a.count)}r(l)},_composeAt:function(e){var t,r=this._operations[e];r&&(e>0&&(t=this._operations[e-1],t.type===r.type&&(r.count+=t.count,this._operations.splice(e-1,1),--e)),er)){var n,a,o=this._findArrayOperation(e),u=o.operation,c=o.index,h=o.rangeStart;a=new i(l,r,t),u?o.split?(this._split(c,e-h,a),n=c+1):(this._operations.splice(c,0,a),n=c):(this._operations.push(a),n=c),this._composeInsert(n)}},removeItems:function(e,t){if(!(1>t)){var r,n,a=this._findArrayOperation(e),s=(a.operation,a.index),o=a.rangeStart;return r=new i(c,t),a.split?(this._split(s,e-o,r),n=s+1):(this._operations.splice(s,0,r),n=s),this._composeDelete(n)}},apply:function(e){var t=[],r=0;o(this._operations,function(n,i){e(n.items,r,n.type,i),n.type!==c&&(r+=n.count,t=t.concat(n.items))}),this._operations=[new i(u,t.length,t)]},_findArrayOperation:function(e){var t,r,n,i,s,o=!1;for(t=n=0,s=this._operations.length;s>t;++t)if(r=this._operations[t],r.type!==c){if(i=n+r.count-1,e===n)break;if(e>n&&i>=e){o=!0;break}n=i+1}return new a(r,t,o,n)},_split:function(e,t,r){var n=this._operations[e],a=n.items.slice(t),s=new i(n.type,a.length,a);n.count=t,n.items=n.items.slice(0,t),this._operations.splice(e+1,0,r,s)},_composeInsert:function(e){var t=this._operations[e],r=this._operations[e-1],n=this._operations[e+1],i=r&&r.type,a=n&&n.type;i===l?(r.count+=t.count,r.items=r.items.concat(t.items),a===l?(r.count+=n.count,r.items=r.items.concat(n.items),this._operations.splice(e,2)):this._operations.splice(e,1)):a===l&&(t.count+=n.count,t.items=t.items.concat(n.items),this._operations.splice(e+1,1))},_composeDelete:function(e){var t,r,n,i=this._operations[e],a=i.count,s=this._operations[e-1],o=s&&s.type,u=!1,h=[];o===c&&(i=s,e-=1);for(var p=e+1;a>0;++p)t=this._operations[p],r=t.type,n=t.count,r!==c?(n>a?(h=h.concat(t.items.splice(0,a)),t.count-=a,p-=1,n=a,a=0):(n===a&&(u=!0),h=h.concat(t.items),a-=n),r===l&&(i.count-=n)):i.count+=n;return i.count>0?this._operations.splice(e+1,p-1-e):this._operations.splice(e,u?2:1),h},toString:function(){var e="";return o(this._operations,function(t){e+=" "+t.type+":"+t.count}),e.substring(1)}}}),e("ember-views",["ember-runtime","ember-views/system/jquery","ember-views/system/utils","ember-views/system/render_buffer","ember-views/system/ext","ember-views/views/states","ember-views/views/core_view","ember-views/views/view","ember-views/views/container_view","ember-views/views/collection_view","ember-views/views/component","ember-views/system/event_dispatcher","ember-views/mixins/view_target_action_support","exports"],function(e,t,r,n,i,a,s,o,u,l,c,h,p,m){"use strict";var f=e["default"],d=t["default"],v=r.isSimpleClick,b=n["default"],y=a.cloneStates,g=a.states,_=s["default"],w=o["default"],x=u["default"],C=l["default"],O=c["default"],E=h["default"],P=p["default"];f.$=d,f.ViewTargetActionSupport=P,f.RenderBuffer=b;var A=f.ViewUtils={};A.isSimpleClick=v,f.CoreView=_,f.View=w,f.View.states=g,f.View.cloneStates=y,f.ContainerView=x,f.CollectionView=C,f.Component=O,f.EventDispatcher=E,m["default"]=f}),e("ember-views/mixins/component_template_deprecation",["ember-metal/core","ember-metal/property_get","ember-metal/mixin","exports"],function(e,t,r,n){"use strict";var i=(e["default"],t.get),a=r.Mixin;n["default"]=a.create({willMergeMixin:function(e){this._super.apply(this,arguments);var t,r,n=e.layoutName||e.layout||i(this,"layoutName");e.templateName&&!n&&(t="templateName",r="layoutName",e.layoutName=e.templateName,delete e.templateName),e.template&&!n&&(t="template",r="layout",e.layout=e.template,delete e.template)}})}),e("ember-views/mixins/view_target_action_support",["ember-metal/mixin","ember-runtime/mixins/target_action_support","ember-metal/computed","exports"],function(e,t,r,n){"use strict";var i=e.Mixin,a=t["default"],s=r.computed,o=s.alias;n["default"]=i.create(a,{target:o("controller"),actionContext:o("context")})}),e("ember-views/system/action_manager",["exports"],function(e){"use strict";function t(){}t.registeredActions={},e["default"]=t}),e("ember-views/system/event_dispatcher",["ember-metal/core","ember-metal/property_get","ember-metal/property_set","ember-metal/is_none","ember-metal/run_loop","ember-metal/utils","ember-runtime/system/string","ember-runtime/system/object","ember-views/system/jquery","ember-views/system/action_manager","ember-views/views/view","ember-metal/merge","exports"],function(e,t,r,n,i,a,s,o,u,l,c,h,p){"use strict";var m=(e["default"],t.get),f=r.set,d=n.isNone,v=i["default"],b=a.typeOf,y=(s.fmt,o["default"]),g=u["default"],_=l["default"],w=c["default"],x=h["default"];p["default"]=y.extend({events:{touchstart:"touchStart",touchmove:"touchMove",touchend:"touchEnd",touchcancel:"touchCancel",keydown:"keyDown",keyup:"keyUp",keypress:"keyPress",mousedown:"mouseDown",mouseup:"mouseUp",contextmenu:"contextMenu",click:"click",dblclick:"doubleClick",mousemove:"mouseMove",focusin:"focusIn",focusout:"focusOut",mouseenter:"mouseEnter",mouseleave:"mouseLeave",submit:"submit",input:"input",change:"change",dragstart:"dragStart",drag:"drag",dragenter:"dragEnter",dragleave:"dragLeave",dragover:"dragOver",drop:"drop",dragend:"dragEnd"},rootElement:"body",canDispatchToEventManager:!0,setup:function(e,t){var r,n=m(this,"events");x(n,e||{}),d(t)||f(this,"rootElement",t),t=g(m(this,"rootElement")),t.addClass("ember-application");for(r in n)n.hasOwnProperty(r)&&this.setupHandler(t,r,n[r])},setupHandler:function(e,t,r){var n=this;e.on(t+".ember",".ember-view",function(e,t){var i=w.views[this.id],a=!0,s=n.canDispatchToEventManager?n._findNearestEventManager(i,r):null;return s&&s!==t?a=n._dispatchEvent(s,e,r,i):i&&(a=n._bubbleEvent(i,e,r)),a}),e.on(t+".ember","[data-ember-action]",function(e){var t=g(e.currentTarget).attr("data-ember-action"),n=_.registeredActions[t];return n&&n.eventName===r?n.handler(e):void 0})},_findNearestEventManager:function(e,t){for(var r=null;e&&(r=m(e,"eventManager"),!r||!r[t]);)e=m(e,"parentView");return r},_dispatchEvent:function(e,t,r,n){var i=!0,a=e[r];return"function"===b(a)?(i=v(e,a,t,n),t.stopPropagation()):i=this._bubbleEvent(n,t,r),i},_bubbleEvent:function(e,t,r){return v(e,e.handleEvent,r,t)},destroy:function(){var e=m(this,"rootElement");return g(e).off(".ember","**").removeClass("ember-application"),this._super()},toString:function(){return"(EventDispatcher)"}})}),e("ember-views/system/ext",["ember-metal/run_loop"],function(e){"use strict";{var t=e["default"];t.queues}t._addQueue("render","actions"),t._addQueue("afterRender","render")}),e("ember-views/system/jquery",["ember-metal/core","ember-runtime/system/string","ember-metal/enumerable_utils","exports"],function(e,t,n,i){"use strict";var a=e["default"],s=t.w,o=n.forEach,u=a.imports&&a.imports.jQuery||this&&this.jQuery;if(u||"function"!=typeof r||(u=r("jquery")),u){var l=s("dragstart drag dragenter dragleave dragover drop dragend");o(l,function(e){u.event.fixHooks[e]={props:["dataTransfer"]}})}i["default"]=u}),e("ember-views/system/render_buffer",["ember-views/system/jquery","morph","ember-metal/core","ember-metal/platform","exports"],function(e,t,r,n,i){"use strict";function a(e,t){if("TABLE"===t.tagName){var r=f.exec(e);if(r)return m[r[1].toLowerCase()]}}function s(){this.seen=p(null),this.list=[]}function o(e){return e&&d.test(e)?e.replace(v,""):e}function u(e){var t={"<":"<",">":">",'"':""","'":"'","`":"`"},r=function(e){return t[e]||"&"},n=e.toString();return y.test(n)?n.replace(b,r):n}function l(e,t){this.tagName=e,this._outerContextualElement=t,this.buffer=null,this.childViews=[],this.dom=new h}var c=e["default"],h=t.DOMHelper,p=(r["default"],n.create),m={tr:document.createElement("tbody"),col:document.createElement("colgroup")},f=/(?:"'`]/g,y=/[&<>"'`]/,g=function(){var e=document.createElement("div"),t=document.createElement("input");return t.setAttribute("name","foo"),e.appendChild(t),!!e.innerHTML.match("foo")}();i["default"]=function(e,t){return new l(e,t)},l.prototype={reset:function(e,t){this.tagName=e,this.buffer=null,this._element=null,this._outerContextualElement=t,this.elementClasses=null,this.elementId=null,this.elementAttributes=null,this.elementProperties=null,this.elementTag=null,this.elementStyle=null,this.childViews.length=0},_element:null,_outerContextualElement:null,elementClasses:null,classes:null,elementId:null,elementAttributes:null,elementProperties:null,elementTag:null,elementStyle:null,pushChildView:function(e){var t=this.childViews.length;this.childViews[t]=e,this.push("")},hydrateMorphs:function(e){for(var t=this.childViews,r=this._element,n=0,i=t.length;i>n;n++){var a=t[n],s=r.querySelector("#morph-"+n),o=s.parentNode;a._morph=this.dom.insertMorphBefore(o,s,1===o.nodeType?o:e),o.removeChild(s)}},push:function(e){return null===this.buffer&&(this.buffer=""),this.buffer+=e,this},addClass:function(e){return this.elementClasses=this.elementClasses||new s,this.elementClasses.add(e),this.classes=this.elementClasses.list,this},setClasses:function(e){this.elementClasses=null;var t,r=e.length;for(t=0;r>t;t++)this.addClass(e[t])},id:function(e){return this.elementId=e,this},attr:function(e,t){var r=this.elementAttributes=this.elementAttributes||{};return 1===arguments.length?r[e]:(r[e]=t,this)},removeAttr:function(e){var t=this.elementAttributes;return t&&delete t[e],this},prop:function(e,t){var r=this.elementProperties=this.elementProperties||{};return 1===arguments.length?r[e]:(r[e]=t,this)},removeProp:function(e){var t=this.elementProperties;return t&&delete t[e],this},style:function(e,t){return this.elementStyle=this.elementStyle||{},this.elementStyle[e]=t,this},generateElement:function(){var e,t,r,n=this.tagName,i=this.elementId,a=this.classes,s=this.elementAttributes,l=this.elementProperties,h=this.elementStyle,p="";r=s&&s.name&&!g?"<"+o(n)+' name="'+u(s.name)+'">':n;var m=this.dom.createElement(r,this.outerContextualElement()),f=c(m);if(i&&(this.dom.setAttribute(m,"id",i),this.elementId=null),a&&(this.dom.setAttribute(m,"class",a.join(" ")),this.classes=null,this.elementClasses=null),h){for(t in h)h.hasOwnProperty(t)&&(p+=t+":"+h[t]+";");this.dom.setAttribute(m,"style",p),this.elementStyle=null}if(s){for(e in s)s.hasOwnProperty(e)&&this.dom.setAttribute(m,e,s[e]);this.elementAttributes=null}if(l){for(t in l)l.hasOwnProperty(t)&&f.prop(t,l[t]);this.elementProperties=null}this._element=m},element:function(){var e=this.innerContent();if(null===e)return this._element;var t=this.innerContextualElement(e);this.dom.detectNamespace(t),this._element||(this._element=document.createDocumentFragment());for(var r=this.dom.parseHTML(e,t);r[0];)this._element.appendChild(r[0]);return this.hydrateMorphs(t),this._element},string:function(){if(this._element){var e=this.element(),t=e.outerHTML;return"undefined"==typeof t?c("
    ").append(e).html():t}return this.innerString()},outerContextualElement:function(){return this._outerContextualElement||(this.outerContextualElement=document.body),this._outerContextualElement},innerContextualElement:function(e){var t;t=this._element&&1===this._element.nodeType?this._element:this.outerContextualElement();var r;return e&&(r=a(e,t)),r||t},innerString:function(){var e=this.innerContent();return e&&!e.nodeType?e:void 0},innerContent:function(){return this.buffer}}}),e("ember-views/system/renderer",["ember-metal/core","ember-metal-views/renderer","ember-metal/platform","ember-views/system/render_buffer","ember-metal/run_loop","ember-metal/property_set","ember-metal/instrumentation","exports"],function(e,t,r,n,i,a,s,o){"use strict";function u(){this.buffer=h(),l.call(this)}var l=(e["default"],t["default"]),c=r.create,h=n["default"],p=i["default"],m=a.set,f=s._instrumentStart,d=s.subscribers;u.prototype=c(l.prototype),u.prototype.constructor=u;u.prototype.scheduleRender=function(e,t){return p.scheduleOnce("render",e,t)},u.prototype.cancelRender=function(e){p.cancel(e)},u.prototype.createChildViewsMorph=function(e,t){if(e.createChildViewsMorph)return e.createChildViewsMorph(t);var r=t;return""===e.tagName?e._morph?e._childViewsMorph=e._morph:(r=document.createDocumentFragment(),e._childViewsMorph=this._dom.appendMorph(r)):e._childViewsMorph=this._dom.createMorph(r,r.lastChild,null),r},u.prototype.createElement=function(e,t){{var r=e.tagName,n=e.classNameBindings;""===r&&n.length>0}(null===r||void 0===r)&&(r="div");var i=e.buffer=this.buffer;i.reset(r,t),e.beforeRender&&e.beforeRender(i),""!==r&&(e.applyAttributesToBuffer&&e.applyAttributesToBuffer(i),i.generateElement()),e.render&&e.render(i),e.afterRender&&e.afterRender(i);var a=i.element();return e.isContainer&&this.createChildViewsMorph(e,a),e.buffer=null,a&&1===a.nodeType&&m(e,"element",a),a},u.prototype.destroyView=function(e){e.removedFromDOM=!0,e.destroy()},u.prototype.childViews=function(e){return e._childViews},l.prototype.willCreateElement=function(e){d.length&&e.instrumentDetails&&(e._instrumentEnd=f("render."+e.instrumentName,function(){var t={};return e.instrumentDetails(t),t})),e._transitionTo&&e._transitionTo("inBuffer")},l.prototype.didCreateElement=function(e){e._transitionTo&&e._transitionTo("hasElement"),e._instrumentEnd&&e._instrumentEnd()},l.prototype.willInsertElement=function(e){e.trigger&&e.trigger("willInsertElement")},l.prototype.didInsertElement=function(e){e._transitionTo&&e._transitionTo("inDOM"),e.trigger&&e.trigger("didInsertElement")},l.prototype.willRemoveElement=function(){},l.prototype.willDestroyElement=function(e){e.trigger&&e.trigger("willDestroyElement"),e.trigger&&e.trigger("willClearRender")},l.prototype.didDestroyElement=function(e){m(e,"element",null),e._transitionTo&&e._transitionTo("preRender")},o["default"]=u}),e("ember-views/system/utils",["exports"],function(e){"use strict";function t(e){var t=e.shiftKey||e.metaKey||e.altKey||e.ctrlKey,r=e.which>1;return!t&&!r}e.isSimpleClick=t}),e("ember-views/views/collection_view",["ember-metal/core","ember-metal/platform","ember-metal/binding","ember-metal/merge","ember-metal/property_get","ember-metal/property_set","ember-runtime/system/string","ember-views/views/container_view","ember-views/views/core_view","ember-views/views/view","ember-metal/mixin","ember-handlebars/ext","ember-runtime/mixins/array","exports"],function(e,t,r,n,i,a,s,o,u,l,c,h,p,m){"use strict";var f=(e["default"],t.create,r.isGlobalPath),d=(n["default"],i.get),v=a.set,b=(s.fmt,o["default"]),y=u["default"],g=l["default"],_=c.observer,w=c.beforeObserver,x=h.handlebarsGetView,C=(p["default"],b.extend({content:null,emptyViewClass:g,emptyView:null,itemViewClass:g,init:function(){var e=this._super();return this._contentDidChange(),e},_contentWillChange:w("content",function(){var e=this.get("content");e&&e.removeArrayObserver(this);var t=e?d(e,"length"):0;this.arrayWillChange(e,0,t)}),_contentDidChange:_("content",function(){var e=d(this,"content");e&&(this._assertArrayLike(e),e.addArrayObserver(this));var t=e?d(e,"length"):0;this.arrayDidChange(e,0,null,t)}),_assertArrayLike:function(){},destroy:function(){if(this._super()){var e=d(this,"content");return e&&e.removeArrayObserver(this),this._createdEmptyView&&this._createdEmptyView.destroy(),this}},arrayWillChange:function(e,t,r){var n=d(this,"emptyView");n&&n instanceof g&&n.removeFromParent();var i,a,s=this._childViews;for(a=t+r-1;a>=t;a--)i=s[a],i.destroy()},arrayDidChange:function(e,t,r,n){var i,a,s,o,u,l,c=[];if(o=e?d(e,"length"):0)for(u=d(this,"itemViewClass"),u=x(e,u,this.container),s=t;t+n>s;s++)a=e.objectAt(s),i=this.createChildView(u,{content:a,contentIndex:s}),c.push(i);else{if(l=d(this,"emptyView"),!l)return;"string"==typeof l&&f(l)&&(l=d(l)||l),l=this.createChildView(l),c.push(l),v(this,"emptyView",l),y.detect(l)&&(this._createdEmptyView=l)}this.replace(t,0,c)},createChildView:function(e,t){e=this._super(e,t);var r=d(e,"tagName");return(null===r||void 0===r)&&(r=C.CONTAINER_MAP[d(this,"tagName")],v(e,"tagName",r)),e}}));C.CONTAINER_MAP={ul:"li",ol:"li",table:"tr",thead:"tr",tbody:"tr",tfoot:"tr",tr:"td",select:"option"},m["default"]=C}),e("ember-views/views/component",["ember-metal/core","ember-views/mixins/component_template_deprecation","ember-runtime/mixins/target_action_support","ember-views/views/view","ember-metal/property_get","ember-metal/property_set","ember-metal/is_none","ember-metal/computed","exports"],function(e,t,r,n,i,a,s,o,u){"use strict";var l=e["default"],c=t["default"],h=r["default"],p=n["default"],m=i.get,f=a.set,d=(s.isNone,o.computed),v=Array.prototype.slice,b=p.extend(h,c,{instrumentName:"component",instrumentDisplay:d(function(){return this._debugContainerKey?"{{"+this._debugContainerKey.split(":")[1]+"}}":void 0}),init:function(){this._super(),f(this,"origContext",m(this,"context")),f(this,"context",this),f(this,"controller",this)},defaultLayout:function(e,t){l.Handlebars.helpers["yield"].call(e,t)},template:d(function(e,t){if(void 0!==t)return t;var r=m(this,"templateName"),n=this.templateForName(r,"template");return n||m(this,"defaultTemplate")}).property("templateName"),templateName:null,cloneKeywords:function(){return{view:this,controller:this}},_yield:function(e,t){var r=t.data.view,n=this._parentView,i=m(this,"template");i&&r.appendChild(p,{isVirtual:!0,tagName:"",_contextView:n,template:i,context:t.data.insideGroup?m(this,"origContext"):m(n,"context"),controller:m(n,"controller"),templateData:{keywords:n.cloneKeywords(),insideGroup:t.data.insideGroup}})},targetObject:d(function(){var e=m(this,"_parentView");return e?m(e,"controller"):null}).property("_parentView"),sendAction:function(e){var t,r=v.call(arguments,1);t=void 0===e?m(this,"action"):m(this,e),void 0!==t&&this.triggerAction({action:t,actionContext:r})}});u["default"]=b}),e("ember-views/views/container_view",["ember-metal/core","ember-metal/merge","ember-runtime/mixins/mutable_array","ember-metal/property_get","ember-metal/property_set","ember-views/views/view","ember-views/views/states","ember-metal/error","ember-metal/enumerable_utils","ember-metal/computed","ember-metal/run_loop","ember-metal/properties","ember-views/system/render_buffer","ember-metal/mixin","ember-runtime/system/native_array","exports"],function(e,t,r,n,i,a,s,o,u,l,c,h,p,m,f,d){"use strict";var v=e["default"],b=t["default"],y=r["default"],g=n.get,_=i.set,w=a["default"],x=s.cloneStates,C=s.states,O=o["default"],E=u.forEach,P=l.computed,A=c["default"],T=h.defineProperty,N=(p["default"],m.observer),S=m.beforeObserver,V=(f.A,x(C)),I=w.extend(y,{isContainer:!0,_states:V,willWatchProperty:function(){},init:function(){this._super();var e=g(this,"childViews");T(this,"childViews",w.childViewsProperty);var t=this._childViews;E(e,function(e,r){var n;"string"==typeof e?(n=g(this,e),n=this.createChildView(n),_(this,e,n)):n=this.createChildView(e),t[r]=n},this);var r=g(this,"currentView");r&&(t.length||(t=this._childViews=this._childViews.slice()),t.push(this.createChildView(r)))},replace:function(e,t,r){var n=r?g(r,"length"):0;if(this.arrayContentWillChange(e,t,n),this.childViewsWillChange(this._childViews,e,t),0===n)this._childViews.splice(e,t);else{var i=[e,t].concat(r);r.length&&!this._childViews.length&&(this._childViews=this._childViews.slice()),this._childViews.splice.apply(this._childViews,i)}return this.arrayContentDidChange(e,t,n),this.childViewsDidChange(this._childViews,e,t,n),this},objectAt:function(e){return this._childViews[e]},length:P(function(){return this._childViews.length})["volatile"](),render:function(){},instrumentName:"container",childViewsWillChange:function(e,t,r){if(this.propertyWillChange("childViews"),r>0){var n=e.slice(t,t+r);this.currentState.childViewsWillChange(this,e,t,r),this.initializeViews(n,null,null)}},removeChild:function(e){return this.removeObject(e),this},childViewsDidChange:function(e,t,r,n){if(n>0){var i=e.slice(t,t+n);this.initializeViews(i,this,g(this,"templateData")),this.currentState.childViewsDidChange(this,e,t,n)}this.propertyDidChange("childViews")},initializeViews:function(e,t,r){E(e,function(e){_(e,"_parentView",t),!e.container&&t&&_(e,"container",t.container),g(e,"templateData")||_(e,"templateData",r)})},currentView:null,_currentViewWillChange:S("currentView",function(){var e=g(this,"currentView");e&&e.destroy()}),_currentViewDidChange:N("currentView",function(){var e=g(this,"currentView");e&&this.pushObject(e)}),_ensureChildrenAreInDOM:function(){this.currentState.ensureChildrenAreInDOM(this)}});b(V._default,{childViewsWillChange:v.K,childViewsDidChange:v.K,ensureChildrenAreInDOM:v.K}),b(V.inBuffer,{childViewsDidChange:function(){throw new O("You cannot modify child views while in the inBuffer state")}}),b(V.hasElement,{childViewsWillChange:function(e,t,r,n){for(var i=r;r+n>i;i++)t[i].remove()},childViewsDidChange:function(e){A.scheduleOnce("render",e,"_ensureChildrenAreInDOM")},ensureChildrenAreInDOM:function(e){var t,r,n,i=e._childViews,a=e._renderer;for(t=0,r=i.length;r>t;t++)n=i[t],n._elementCreated||a.renderTree(n,e,t)}}),d["default"]=I}),e("ember-views/views/core_view",["ember-views/system/renderer","ember-views/views/states","ember-runtime/system/object","ember-runtime/mixins/evented","ember-runtime/mixins/action_handler","ember-metal/property_get","ember-metal/property_set","ember-metal/computed","ember-metal/utils","ember-metal/instrumentation","exports"],function(e,t,r,n,a,s,o,u,l,c,h){"use strict";var p=e["default"],m=t.cloneStates,f=t.states,d=r["default"],v=n["default"],b=a["default"],y=s.get,g=(o.set,u.computed),_=l.typeOf,w=(c.instrument,d.extend(v,b,{isView:!0,isVirtual:!1,isContainer:!1,_states:m(f),init:function(){this._super(),this._transitionTo("preRender"),this._isVisible=y(this,"isVisible")},parentView:g("_parentView",function(){var e=this._parentView;return e&&e.isVirtual?y(e,"parentView"):e}),_state:null,_parentView:null,concreteView:g("parentView",function(){return this.isVirtual?y(this,"parentView.concreteView"):this}),instrumentName:"core_view",instrumentDetails:function(e){e.object=this.toString(),e.containerKey=this._debugContainerKey,e.view=this},trigger:function(){this._super.apply(this,arguments);var e=arguments[0],t=this[e];if(t){for(var r=arguments.length,n=new Array(r-1),i=1;r>i;i++)n[i-1]=arguments[i];return t.apply(this,n)}},has:function(e){return"function"===_(this[e])||this._super(e)},destroy:function(){var e=this._parentView;if(this._super())return!this.removedFromDOM&&this._renderer&&this._renderer.remove(this,!0),e&&e.removeChild(this),this._transitionTo("destroying",!1),this},clearRenderedChildren:i.K,_transitionTo:i.K,destroyElement:i.K}));w.reopenClass({renderer:new p}),h["default"]=w}),e("ember-views/views/states",["ember-metal/platform","ember-metal/merge","ember-views/views/states/default","ember-views/views/states/pre_render","ember-views/views/states/in_buffer","ember-views/views/states/has_element","ember-views/views/states/in_dom","ember-views/views/states/destroying","exports"],function(e,t,r,n,i,a,s,o,u){"use strict";function l(e){var t={};t._default={},t.preRender=c(t._default),t.destroying=c(t._default),t.inBuffer=c(t._default),t.hasElement=c(t._default),t.inDOM=c(t.hasElement);for(var r in e)e.hasOwnProperty(r)&&h(t[r],e[r]);return t}var c=e.create,h=t["default"],p=r["default"],m=n["default"],f=i["default"],d=a["default"],v=s["default"],b=o["default"];u.cloneStates=l;var y={_default:p,preRender:m,inDOM:v,inBuffer:f,hasElement:d,destroying:b};u.states=y}),e("ember-views/views/states/default",["ember-metal/core","ember-metal/property_get","ember-metal/property_set","ember-metal/run_loop","ember-metal/error","exports"],function(e,t,r,n,i,a){"use strict";var s=e["default"],o=(t.get,r.set,n["default"],i["default"]);a["default"]={appendChild:function(){throw new o("You can't use appendChild outside of the rendering process")},$:function(){return void 0},getElement:function(){return null},handleEvent:function(){return!0},destroyElement:function(e){return e._renderer&&e._renderer.remove(e,!1),e},rerender:s.K,invokeObserver:s.K}}),e("ember-views/views/states/destroying",["ember-metal/merge","ember-metal/platform","ember-runtime/system/string","ember-views/views/states/default","ember-metal/error","exports"],function(e,t,r,n,i,a){"use strict";var s=e["default"],o=t.create,u=r.fmt,l=n["default"],c=i["default"],h="You can't call %@ on a view being destroyed",p=o(l);s(p,{appendChild:function(){throw new c(u(h,["appendChild"]))},rerender:function(){throw new c(u(h,["rerender"]))},destroyElement:function(){throw new c(u(h,["destroyElement"]))}}),a["default"]=p}),e("ember-views/views/states/has_element",["ember-views/views/states/default","ember-metal/run_loop","ember-metal/merge","ember-metal/platform","ember-views/system/jquery","ember-metal/error","ember-metal/property_get","ember-metal/property_set","exports"],function(e,t,r,n,i,a,s,o,u){"use strict";var l=e["default"],c=t["default"],h=r["default"],p=n.create,m=i["default"],f=a["default"],d=s.get,v=(o.set,p(l));h(v,{$:function(e,t){var r=e.get("concreteView").element;return t?m(t,r):m(r)},getElement:function(e){var t=d(e,"parentView");return t&&(t=d(t,"element")),t?e.findElementInParentElement(t):m("#"+d(e,"elementId"))[0]},rerender:function(e){if(e._root._morph&&!e._elementInserted)throw new f("Something you did caused a view to re-render after it rendered but before it was inserted into the DOM.");c.scheduleOnce("render",function(){e.isDestroying||e._renderer.renderTree(e,e._parentView)})},destroyElement:function(e){return e._renderer.remove(e,!1),e},handleEvent:function(e,t,r){return e.has(t)?e.trigger(t,r):!0},invokeObserver:function(e,t){t.call(e)}}),u["default"]=v}),e("ember-views/views/states/in_buffer",["ember-views/views/states/default","ember-metal/error","ember-metal/core","ember-metal/platform","ember-metal/merge","exports"],function(e,t,r,n,i,a){"use strict";var s=e["default"],o=t["default"],u=r["default"],l=n.create,c=i["default"],h=l(s);c(h,{$:function(e){return e.rerender(),u.$()},rerender:function(){throw new o("Something you did caused a view to re-render after it rendered but before it was inserted into the DOM.")},appendChild:function(e,t,r){var n=e.buffer,i=e._childViews;return t=e.createChildView(t,r),i.length||(i=e._childViews=i.slice()),i.push(t),t._morph||n.pushChildView(t),e.propertyDidChange("childViews"),t},invokeObserver:function(e,t){t.call(e)}}),a["default"]=h}),e("ember-views/views/states/in_dom",["ember-metal/core","ember-metal/platform","ember-metal/merge","ember-metal/error","ember-views/views/states/has_element","exports"],function(e,r,n,i,a,s){"use strict";var o,u=(e["default"],r.create),l=n["default"],c=i["default"],h=a["default"],p=u(h);l(p,{enter:function(e){o||(o=t("ember-views/views/view")["default"]),e.isVirtual||(o.views[e.elementId]=e),e.addBeforeObserver("elementId",function(){throw new c("Changing a view's elementId after creation is not allowed")})},exit:function(e){o||(o=t("ember-views/views/view")["default"]),this.isVirtual||delete o.views[e.elementId]}}),s["default"]=p}),e("ember-views/views/states/pre_render",["ember-views/views/states/default","ember-metal/platform","ember-metal/merge","ember-views/system/jquery","exports"],function(e,t,r,n,i){"use strict";var a=e["default"],s=t.create,o=(r["default"],n["default"],s(a));i["default"]=o}),e("ember-views/views/view",["ember-metal/core","ember-runtime/mixins/evented","ember-runtime/system/object","ember-metal/error","ember-metal/property_get","ember-metal/property_set","ember-metal/set_properties","ember-metal/run_loop","ember-metal/observer","ember-metal/properties","ember-metal/utils","ember-metal/computed","ember-metal/mixin","ember-metal/is_none","ember-metal/deprecate_property","ember-runtime/system/native_array","ember-runtime/system/string","ember-metal/enumerable_utils","ember-runtime/copy","ember-metal/binding","ember-metal/property_events","ember-views/system/jquery","ember-views/system/ext","ember-views/views/core_view","exports"],function(e,t,r,n,i,a,s,o,u,l,c,h,p,m,f,d,v,b,y,g,_,w,x,C,O){"use strict";var E=e["default"],P=t["default"],A=r["default"],T=n["default"],N=i.get,S=a.set,V=s["default"],I=o["default"],k=u.addObserver,D=u.removeObserver,j=l.defineProperty,M=l.deprecateProperty,R=c.guidFor,L=(c.meta,h.computed),H=p.observer,z=c.typeOf,q=c.isArray,F=m.isNone,B=p.Mixin,M=f.deprecateProperty,U=d.A,K=v.dasherize,W=b.forEach,G=b.addObject,Q=b.removeObject,$=p.beforeObserver,Y=y["default"],J=g.isGlobalPath,Z=_.propertyWillChange,X=_.propertyDidChange,et=w["default"],tt=C["default"],rt=L(function(){var e=this._childViews,t=U();return W(e,function(e){var r;e.isVirtual?(r=N(e,"childViews"))&&t.pushObjects(r):t.push(e)}),t.replace=function(){throw new T("childViews is immutable")},t});E.TEMPLATES={};var nt=[],it=tt.extend({concatenatedProperties:["classNames","classNameBindings","attributeBindings"],isView:!0,templateName:null,layoutName:null,instrumentDisplay:L(function(){return this.helperName?"{{"+this.helperName+"}}":void 0 -}),template:L("templateName",function(e,t){if(void 0!==t)return t;var r=N(this,"templateName"),n=this.templateForName(r,"template");return n||N(this,"defaultTemplate")}),controller:L("_parentView",function(){var e=N(this,"_parentView");return e?N(e,"controller"):null}),layout:L(function(){var e=N(this,"layoutName"),t=this.templateForName(e,"layout");return t||N(this,"defaultLayout")}).property("layoutName"),_yield:function(e,t){var r=N(this,"template");r&&r(e,t)},templateForName:function(e){if(e){if(!this.container)throw new T("Container was not found when looking up a views template. This is most likely due to manually instantiating an Ember.View. See: http://git.io/EKPpnA");return this.container.lookup("template:"+e)}},context:L(function(e,t){return 2===arguments.length?(S(this,"_context",t),t):N(this,"_context")})["volatile"](),_context:L(function(){var e,t;return(t=N(this,"controller"))?t:(e=this._parentView,e?N(e,"_context"):null)}),_contextDidChange:H("context",function(){this.rerender()}),isVisible:!0,childViews:rt,_childViews:nt,_childViewsWillChange:$("childViews",function(){if(this.isVirtual){var e=N(this,"parentView");e&&Z(e,"childViews")}}),_childViewsDidChange:H("childViews",function(){if(this.isVirtual){var e=N(this,"parentView");e&&X(e,"childViews")}}),nearestInstanceOf:function(e){for(var t=N(this,"parentView");t;){if(t instanceof e)return t;t=N(t,"parentView")}},nearestOfType:function(e){for(var t=N(this,"parentView"),r=e instanceof B?function(t){return e.detect(t)}:function(t){return e.detect(t.constructor)};t;){if(r(t))return t;t=N(t,"parentView")}},nearestWithProperty:function(e){for(var t=N(this,"parentView");t;){if(e in t)return t;t=N(t,"parentView")}},nearestChildOf:function(e){for(var t=N(this,"parentView");t;){if(N(t,"parentView")instanceof e)return t;t=N(t,"parentView")}},_parentViewDidChange:H("_parentView",function(){this.isDestroying||(this.trigger("parentViewDidChange"),N(this,"parentView.controller")&&!N(this,"controller")&&this.notifyPropertyChange("controller"))}),_controllerDidChange:H("controller",function(){this.isDestroying||(this.rerender(),this.forEachChildView(function(e){e.propertyDidChange("controller")}))}),cloneKeywords:function(){var e=N(this,"templateData"),t=e?Y(e.keywords):{};return S(t,"view",this.isVirtual?t.view:this),S(t,"_view",this),S(t,"controller",N(this,"controller")),t},render:function(e){var t=N(this,"layout")||N(this,"template");if(t){var r,n=N(this,"context"),i=this.cloneKeywords(),a={view:this,buffer:e,isRenderData:!0,keywords:i,insideGroup:N(this,"templateData.insideGroup")};r=t(n,{data:a}),void 0!==r&&e.push(r)}},rerender:function(){return this.currentState.rerender(this)},_applyClassNameBindings:function(e){var t,r,n,i=this.classNames;W(e,function(e){var a,s=it._parsePropertyPath(e),o=function(){r=this._classStringForProperty(e),t=this.$(),a&&(t.removeClass(a),i.removeObject(a)),r?(t.addClass(r),a=r):a=null};n=this._classStringForProperty(e),n&&(G(i,n),a=n),this.registerObserver(this,s.path,o),this.one("willClearRender",function(){a&&(i.removeObject(a),a=null)})},this)},_unspecifiedAttributeBindings:null,_applyAttributeBindings:function(e,t){var r,n=this._unspecifiedAttributeBindings=this._unspecifiedAttributeBindings||{};W(t,function(t){var i=t.split(":"),a=i[0],s=i[1]||a;a in this?(this._setupAttributeBindingObservation(a,s),r=N(this,a),it.applyAttributeBindings(e,s,r)):n[a]=s},this),this.setUnknownProperty=this._setUnknownProperty},_setupAttributeBindingObservation:function(e,t){var r,n,i=function(){n=this.$(),r=N(this,e),it.applyAttributeBindings(n,t,r)};this.registerObserver(this,e,i)},setUnknownProperty:null,_setUnknownProperty:function(e,t){var r=this._unspecifiedAttributeBindings&&this._unspecifiedAttributeBindings[e];return r&&this._setupAttributeBindingObservation(e,r),j(this,e),S(this,e,t)},_classStringForProperty:function(e){var t=it._parsePropertyPath(e),r=t.path,n=N(this,r);return void 0===n&&J(r)&&(n=N(E.lookup,r)),it._classStringForValue(r,n,t.className,t.falsyClassName)},element:null,$:function(e){return this.currentState.$(this,e)},mutateChildViews:function(e){for(var t,r=this._childViews,n=r.length;--n>=0;)t=r[n],e(this,t,n);return this},forEachChildView:function(e){var t=this._childViews;if(!t)return this;var r,n,i=t.length;for(n=0;i>n;n++)r=t[n],e(r);return this},appendTo:function(e){var t=et(e);return this.constructor.renderer.appendTo(this,t[0]),this},replaceIn:function(e){var t=et(e);return this.constructor.renderer.replaceIn(this,t[0]),this},append:function(){return this.appendTo(document.body)},remove:function(){this.removedFromDOM||this.destroyElement()},elementId:null,findElementInParentElement:function(e){var t="#"+this.elementId;return et(t)[0]||et(t,e)[0]},createElement:function(){return this.element?this:(this._didCreateElementWithoutMorph=!0,this.constructor.renderer.renderTree(this),this)},willInsertElement:E.K,didInsertElement:E.K,willClearRender:E.K,destroyElement:function(){return this.currentState.destroyElement(this)},willDestroyElement:E.K,parentViewDidChange:E.K,instrumentName:"view",instrumentDetails:function(e){e.template=N(this,"templateName"),this._super(e)},beforeRender:function(){},afterRender:function(){},applyAttributesToBuffer:function(e){var t=N(this,"classNameBindings");t.length&&this._applyClassNameBindings(t);var r=N(this,"attributeBindings");r.length&&this._applyAttributeBindings(e,r),e.setClasses(this.classNames),e.id(this.elementId);var n=N(this,"ariaRole");n&&e.attr("role",n),N(this,"isVisible")===!1&&e.style("display","none")},tagName:null,ariaRole:null,classNames:["ember-view"],classNameBindings:nt,attributeBindings:nt,init:function(){this.isVirtual||this.elementId||(this.elementId=R(this)),this._super(),this._childViews=this._childViews.slice(),this.classNameBindings=U(this.classNameBindings.slice()),this.classNames=U(this.classNames.slice())},appendChild:function(e,t){return this.currentState.appendChild(this,e,t)},removeChild:function(e){if(!this.isDestroying){S(e,"_parentView",null);var t=this._childViews;return Q(t,e),this.propertyDidChange("childViews"),this}},removeAllChildren:function(){return this.mutateChildViews(function(e,t){e.removeChild(t)})},destroyAllChildren:function(){return this.mutateChildViews(function(e,t){t.destroy()})},removeFromParent:function(){var e=this._parentView;return this.remove(),e&&e.removeChild(this),this},destroy:function(){var e=(this._childViews,N(this,"parentView")),t=this.viewName;return this._super()?(t&&e&&e.set(t,null),this):void 0},createChildView:function(e,t){if(!e)throw new TypeError("createChildViews first argument must exist");if(e.isView&&e._parentView===this&&e.container===this.container)return e;if(t=t||{},t._parentView=this,tt.detect(e))t.templateData=t.templateData||N(this,"templateData"),t.container=this.container,e=e.create(t),e.viewName&&S(N(this,"concreteView"),e.viewName,e);else if("string"==typeof e){var r="view:"+e,n=this.container.lookupFactory(r);t.templateData=N(this,"templateData"),e=n.create(t)}else t.container=this.container,N(e,"templateData")||(t.templateData=N(this,"templateData")),V(e,t);return e},becameVisible:E.K,becameHidden:E.K,_isVisibleDidChange:H("isVisible",function(){this._isVisible!==N(this,"isVisible")&&I.scheduleOnce("render",this,this._toggleVisibility)}),_toggleVisibility:function(){var e=this.$(),t=N(this,"isVisible");this._isVisible!==t&&(this._isVisible=t,e&&(e.toggle(t),this._isAncestorHidden()||(t?this._notifyBecameVisible():this._notifyBecameHidden())))},_notifyBecameVisible:function(){this.trigger("becameVisible"),this.forEachChildView(function(e){var t=N(e,"isVisible");(t||null===t)&&e._notifyBecameVisible()})},_notifyBecameHidden:function(){this.trigger("becameHidden"),this.forEachChildView(function(e){var t=N(e,"isVisible");(t||null===t)&&e._notifyBecameHidden()})},_isAncestorHidden:function(){for(var e=N(this,"parentView");e;){if(N(e,"isVisible")===!1)return!0;e=N(e,"parentView")}return!1},transitionTo:function(e,t){this._transitionTo(e,t)},_transitionTo:function(e){var t=this.currentState,r=this.currentState=this._states[e];this._state=e,t&&t.exit&&t.exit(this),r.enter&&r.enter(this)},handleEvent:function(e,t){return this.currentState.handleEvent(this,e,t)},registerObserver:function(e,t,r,n){if(n||"function"!=typeof r||(n=r,r=null),e&&"object"==typeof e){var i=this,a=function(){i.currentState.invokeObserver(this,n)},s=function(){I.scheduleOnce("render",this,a)};k(e,t,r,s),this.one("willClearRender",function(){D(e,t,r,s)})}}});M(it.prototype,"state","_state"),M(it.prototype,"states","_states"),it.reopenClass({_parsePropertyPath:function(e){var t,r,n=e.split(":"),i=n[0],a="";return n.length>1&&(t=n[1],3===n.length&&(r=n[2]),a=":"+t,r&&(a+=":"+r)),{path:i,classNames:a,className:""===t?void 0:t,falsyClassName:r}},_classStringForValue:function(e,t,r,n){if(q(t)&&(t=0!==N(t,"length")),r||n)return r&&t?r:n&&!t?n:null;if(t===!0){var i=e.split(".");return K(i[i.length-1])}return t!==!1&&null!=t?t:null}});var at=A.extend(P).create();it.addMutationListener=function(e){at.on("change",e)},it.removeMutationListener=function(e){at.off("change",e)},it.notifyMutationListeners=function(){at.trigger("change")},it.views={},it.childViewsProperty=rt,it.applyAttributeBindings=function(e,t,r){var n=z(r);"value"===t||"string"!==n&&("number"!==n||isNaN(r))?"value"===t||"boolean"===n?F(r)||r===!1?(e.removeAttr(t),"required"===t?e.removeProp(t):e.prop(t,"")):r!==e.prop(t)&&e.prop(t,r):r||e.removeAttr(t):r!==e.attr(t)&&e.attr(t,r)},O["default"]=it}),e("ember",["ember-metal","ember-runtime","ember-handlebars","ember-views","ember-routing","ember-routing-handlebars","ember-application","ember-extension-support"],function(){"use strict";i.__loader.registry["ember-testing"]&&t("ember-testing")}),e("morph",["./morph/morph","./morph/dom-helper","exports"],function(e,t,r){"use strict";var n,n=e["default"];r.Morph=n;var i,i=t["default"];r.DOMHelper=i}),e("morph/dom-helper",["../morph/morph","./dom-helper/build-html-dom","exports"],function(e,t,r){"use strict";function n(e){return e===c}function i(e){return e&&e.namespaceURI===c&&!h[e.tagName]?c:null}function a(e,t){if("TABLE"===t.tagName){var r=f.exec(e);if(r){var n=r[1];return"tr"===n||"col"===n}}}function s(e,t){var r=t.document.createElement("div");return r.innerHTML=""+e+"",r.firstChild.childNodes}function o(e){this.document=e||window.document,this.namespace=null}var u=e["default"],l=t.buildHTMLDOM,c=t.svgNamespace,h=t.svgHTMLIntegrationPoints,p=function(){var e=document.createElement("div");e.appendChild(document.createTextNode(""));var t=e.cloneNode(!0);return 0===t.childNodes.length}(),m=function(){var e=document.createElement("input");e.setAttribute("checked","checked");var t=e.cloneNode(!1);return!t.checked}(),f=/<([\w:]+)/,d=o.prototype;d.constructor=o,d.insertBefore=function(e,t,r){return e.insertBefore(t,r)},d.appendChild=function(e,t){return e.appendChild(t)},d.appendText=function(e,t){return e.appendChild(this.document.createTextNode(t))},d.setAttribute=function(e,t,r){e.setAttribute(t,r)},d.createElement=document.createElementNS?function(e,t){var r=this.namespace;return t&&(r="svg"===e?c:i(t)),r?this.document.createElementNS(r,e):this.document.createElement(e)}:function(e){return this.document.createElement(e)},d.setNamespace=function(e){this.namespace=e},d.detectNamespace=function(e){this.namespace=i(e)},d.createDocumentFragment=function(){return this.document.createDocumentFragment()},d.createTextNode=function(e){return this.document.createTextNode(e)},d.repairClonedNode=function(e,t,r){if(p&&t.length>0)for(var n=0,i=t.length;i>n;n++){var a=this.document.createTextNode(""),s=t[n],o=e.childNodes[s];o?e.insertBefore(a,o):e.appendChild(a)}m&&r&&e.setAttribute("checked","checked")},d.cloneNode=function(e,t){var r=e.cloneNode(!!t);return r},d.createMorph=function(e,t,r,n){return n||1!==e.nodeType||(n=e),new u(e,t,r,this,n)},d.createMorphAt=function(e,t,r,n){var i=e.childNodes,a=-1===t?null:i[t],s=-1===r?null:i[r];return this.createMorph(e,a,s,n)},d.insertMorphBefore=function(e,t,r){var n=this.document.createTextNode(""),i=this.document.createTextNode("");return e.insertBefore(n,t),e.insertBefore(i,t),this.createMorph(e,n,i,r)},d.appendMorph=function(e,t){var r=this.document.createTextNode(""),n=this.document.createTextNode("");return e.appendChild(r),e.appendChild(n),this.createMorph(e,r,n,t)},d.parseHTML=function(e,t){var r=n(this.namespace)&&!h[t.tagName];if(r)return s(e,this);var i=l(e,t,this);if(a(e,t)){for(var o=i[0];o&&1!==o.nodeType;)o=o.nextSibling;return o.childNodes}return i},r["default"]=o}),e("morph/dom-helper/build-html-dom",["exports"],function(e){"use strict";function t(e,t){t="­"+t,e.innerHTML=t;for(var r=e.childNodes,n=r[0];1===n.nodeType&&!n.nodeName;)n=n.firstChild;if(3===n.nodeType&&"­"===n.nodeValue.charAt(0)){var i=n.nodeValue.slice(1);i.length?n.nodeValue=n.nodeValue.slice(1):n.parentNode.removeChild(n)}return r}function r(e,r){var n=r.tagName,i=r.outerHTML||(new XMLSerializer).serializeToString(r);if(!i)throw"Can't set innerHTML on "+n+" in this browser";for(var a=p[n.toLowerCase()],s=i.match(new RegExp("<"+n+"([^>]*)>","i"))[0],o="",u=[s,e,o],l=a.length,c=1+l;l--;)u.unshift("<"+a[l]+">"),u.push("");var h=document.createElement("div");t(h,u.join(""));for(var m=h;c--;)for(m=m.firstChild;m&&1!==m.nodeType;)m=m.nextSibling;for(;m&&m.tagName!==n;)m=m.nextSibling;return m?m.childNodes:[]}function n(e,t,r){var n=y(e,t,r);if("SELECT"===t.tagName)for(var i=0;n[i];i++)if("OPTION"===n[i].tagName){s(n[i].parentNode,n[i],e)&&(n[i].parentNode.selectedIndex=-1);break}return n}var i={foreignObject:1,desc:1,title:1};e.svgHTMLIntegrationPoints=i;var a="http://www.w3.org/2000/svg";e.svgNamespace=a;var s,o=document&&document.createElementNS&&function(){var e=document.createElementNS(a,"title");return e.innerHTML="
    ",0===e.childNodes.length||1!==e.childNodes[0].nodeType}(),u=document&&function(){var e=document.createElement("div");return e.innerHTML="
    ",e.firstChild.innerHTML="",""===e.firstChild.innerHTML}(),l=document&&function(){var e=document.createElement("div");return e.innerHTML="Test: Value","Test:"===e.childNodes[0].nodeValue&&" Value"===e.childNodes[2].nodeValue}(),c=document&&function(){var e=document.createElement("div");return e.innerHTML="","selected"===e.childNodes[0].childNodes[0].getAttribute("selected")}();if(c){var h=/]*selected/;s=function(e,t,r){return 0===e.selectedIndex&&!h.test(r)}}else s=function(e,t){var r=t.getAttribute("selected");return 0===e.selectedIndex&&(null===r||""!==r&&"selected"!==r.toLowerCase())};var p,m,f=document.createElement("table");try{f.innerHTML="
    "}catch(d){}finally{m=0===f.childNodes.length}m&&(p={colgroup:["table"],table:[],tbody:["table"],tfoot:["table"],thead:["table"],tr:["table","tbody"]});var v=document.createElement("select");v.innerHTML="",v&&(p=p||{},p.select=[]);var b;b=u?function(e,r,n){return r=n.cloneNode(r,!1),t(r,e),r.childNodes}:function(e,t,r){return t=r.cloneNode(t,!1),t.innerHTML=e,t.childNodes};var y;y=p||l?function(e,t,n){var i=[],a=[];e=e.replace(/(\s*)()(\s*)/g,function(e,t,r){return a.push(r),t});var s;s=p[t.tagName.toLowerCase()]?r(e,t):b(e,t,n);var o,u,l,c,h=[];for(o=0;l=s[o];o++)if(1===l.nodeType)if("SCRIPT"===l.tagName)h.push(l);else for(c=l.getElementsByTagName("script"),u=0;u0&&(f=n.document.createTextNode(d),m.parentNode.insertBefore(f,m)),v=a[o],v&&v.length>0&&(f=n.document.createTextNode(v),m.parentNode.insertBefore(f,m.nextSibling));return s}:b;var g;g=o?function(e,t,r){return i[t.tagName]?n(e,document.createElement("div"),r):n(e,t,r)}:n,e.buildHTMLDOM=g}),e("morph/morph",["exports"],function(e){"use strict";function t(e,t){if(null===e||null===t)throw new Error("a fragment parent must have boundary nodes in order to detect insertion")}function r(e){if(!e||1!==e.nodeType)throw new Error("An element node must be provided for a contextualElement, you provided "+(e?"nodeType "+e.nodeType:"nothing"))}function n(e,n,i,a,s){11===e.nodeType?(t(n,i),this.element=null):this.element=e,this._parent=e,this.start=n,this.end=i,this.domHelper=a,r(s),this.contextualElement=s,this.reset()}function i(e,t,r){for(var n,i=t,a=r.length;a--;)n=r[a],e.insertBefore(n,i),i=n}function a(e,t,r){var n,i;for(n=null===r?e.lastChild:r.previousSibling;null!==n&&n!==t;)i=n.previousSibling,e.removeChild(n),n=i}var s=Array.prototype.splice;n.prototype.reset=function(){this.text=null,this.owner=null,this.morphs=null,this.before=null,this.after=null,this.escaped=!0},n.prototype.parent=function(){if(!this.element){var e=this.start.parentNode;this._parent!==e&&(this.element=this._parent=e)}return this._parent},n.prototype.destroy=function(){this.owner?this.owner.removeMorph(this):a(this.element||this.parent(),this.start,this.end)},n.prototype.removeMorph=function(e){for(var t=this.morphs,r=0,n=t.length;n>r;r++)if(t[r]===e){this.replace(r,1);break}},n.prototype.update=function(e){this._update(this.element||this.parent(),e)},n.prototype.updateNode=function(e){var t=this.element||this.parent();return e?void this._updateNode(t,e):this._updateText(t,"")},n.prototype.updateText=function(e){this._updateText(this.element||this.parent(),e)},n.prototype.updateHTML=function(e){var t=this.element||this.parent();return e?void this._updateHTML(t,e):this._updateText(t,"")},n.prototype._update=function(e,t){null===t||void 0===t?this._updateText(e,""):"string"==typeof t?this.escaped?this._updateText(e,t):this._updateHTML(e,t):t.nodeType?this._updateNode(e,t):t.string?this._updateHTML(e,t.string):this._updateText(e,t.toString())},n.prototype._updateNode=function(e,t){if(this.text){if(3===t.nodeType)return void(this.text.nodeValue=t.nodeValue);this.text=null}var r=this.start,n=this.end;a(e,r,n),e.insertBefore(t,n),null!==this.before&&(this.before.end=r.nextSibling),null!==this.after&&(this.after.start=n.previousSibling)},n.prototype._updateText=function(e,t){if(this.text)return void(this.text.nodeValue=t);var r=this.domHelper.createTextNode(t);this.text=r,a(e,this.start,this.end),e.insertBefore(r,this.end),null!==this.before&&(this.before.end=r),null!==this.after&&(this.after.start=r)},n.prototype._updateHTML=function(e,t){var r=this.start,n=this.end;a(e,r,n),this.text=null;var s=this.domHelper.parseHTML(t,this.contextualElement);i(e,n,s),null!==this.before&&(this.before.end=r.nextSibling),null!==this.after&&(this.after.start=n.previousSibling)},n.prototype.append=function(e){null===this.morphs&&(this.morphs=[]);var t=this.morphs.length;return this.insert(t,e)},n.prototype.insert=function(e,t){null===this.morphs&&(this.morphs=[]);var r=this.element||this.parent(),i=this.morphs,a=e>0?i[e-1]:null,s=e0?c[e-1]:null,p=e+t0&&a(l,m,f),0===d)return null!==h&&(h.after=p,h.end=f),null!==p&&(p.before=h,p.start=m),void c.splice(e,t);if(i=new Array(d+2),d>0){for(o=0;d>o;o++)i[o+2]=u=new n(l,m,f,this.domHelper,this.contextualElement),u._update(l,r[o]),u.owner=this,null!==h&&(u.before=h,h.end=m.nextSibling,h.after=u),h=u,m=null===f?l.lastChild:f.previousSibling;null!==p&&(u.after=p,p.before=u,p.start=f.previousSibling)}i[0]=e,i[1]=t,s.apply(c,i)},e["default"]=n}),e("route-recognizer",["route-recognizer/dsl","exports"],function(e,t){"use strict";function r(e){return"[object Array]"===Object.prototype.toString.call(e)}function n(e){this.string=e}function i(e){this.name=e}function a(e){this.name=e}function s(){}function o(e,t,r){"/"===e.charAt(0)&&(e=e.substr(1));for(var o=e.split("/"),u=[],l=0,c=o.length;c>l;l++){var h,p=o[l];(h=p.match(/^:([^\/]+)$/))?(u.push(new i(h[1])),t.push(h[1]),r.dynamics++):(h=p.match(/^\*([^\/]+)$/))?(u.push(new a(h[1])),t.push(h[1]),r.stars++):""===p?u.push(new s):(u.push(new n(p)),r.statics++)}return u}function u(e){this.charSpec=e,this.nextStates=[]}function l(e){return e.sort(function(e,t){if(e.types.stars!==t.types.stars)return e.types.stars-t.types.stars;if(e.types.stars){if(e.types.statics!==t.types.statics)return t.types.statics-e.types.statics;if(e.types.dynamics!==t.types.dynamics)return t.types.dynamics-e.types.dynamics}return e.types.dynamics!==t.types.dynamics?e.types.dynamics-t.types.dynamics:e.types.statics!==t.types.statics?t.types.statics-e.types.statics:0})}function c(e,t){for(var r=[],n=0,i=e.length;i>n;n++){var a=e[n];r=r.concat(a.match(t))}return r}function h(e){this.queryParams=e||{}}function p(e,t,r){for(var n=e.handlers,i=e.regex,a=t.match(i),s=1,o=new h(r),u=0,l=n.length;l>u;u++){for(var c=n[u],p=c.names,m={},f=0,d=p.length;d>f;f++)m[p[f]]=a[s++];o.push({handler:c.handler,params:m,isDynamic:!!p.length})}return o}function m(e,t){return t.eachChar(function(t){e=e.put(t)}),e}var f=e["default"],d=["/",".","*","+","?","|","(",")","[","]","{","}","\\"],v=new RegExp("(\\"+d.join("|\\")+")","g");n.prototype={eachChar:function(e){for(var t,r=this.string,n=0,i=r.length;i>n;n++)t=r.charAt(n),e({validChars:t})},regex:function(){return this.string.replace(v,"\\$1")},generate:function(){return this.string}},i.prototype={eachChar:function(e){e({invalidChars:"/",repeat:!0})},regex:function(){return"([^/]+)"},generate:function(e){return e[this.name]}},a.prototype={eachChar:function(e){e({invalidChars:"",repeat:!0})},regex:function(){return"(.+)"},generate:function(e){return e[this.name]}},s.prototype={eachChar:function(){},regex:function(){return""},generate:function(){return""}},u.prototype={get:function(e){for(var t=this.nextStates,r=0,n=t.length;n>r;r++){var i=t[r],a=i.charSpec.validChars===e.validChars;if(a=a&&i.charSpec.invalidChars===e.invalidChars)return i}},put:function(e){var t;return(t=this.get(e))?t:(t=new u(e),this.nextStates.push(t),e.repeat&&t.nextStates.push(t),t)},match:function(e){for(var t,r,n,i=this.nextStates,a=[],s=0,o=i.length;o>s;s++)t=i[s],r=t.charSpec,"undefined"!=typeof(n=r.validChars)?-1!==n.indexOf(e)&&a.push(t):"undefined"!=typeof(n=r.invalidChars)&&-1===n.indexOf(e)&&a.push(t);return a}};var b=Object.create||function(e){function t(){}return t.prototype=e,new t};h.prototype=b({splice:Array.prototype.splice,slice:Array.prototype.slice,push:Array.prototype.push,length:0,queryParams:null});var y=function(){this.rootState=new u,this.names={}};y.prototype={add:function(e,t){for(var r,n=this.rootState,i="^",a={statics:0,dynamics:0,stars:0},u=[],l=[],c=!0,h=0,p=e.length;p>h;h++){var f=e[h],d=[],v=o(f.path,d,a);l=l.concat(v);for(var b=0,y=v.length;y>b;b++){var g=v[b];g instanceof s||(c=!1,n=n.put({validChars:"/"}),i+="/",n=m(n,g),i+=g.regex())}var _={handler:f.handler,names:d};u.push(_)}c&&(n=n.put({validChars:"/"}),i+="/"),n.handlers=u,n.regex=new RegExp(i+"$"),n.types=a,(r=t&&t.as)&&(this.names[r]={segments:l,handlers:u})},handlersFor:function(e){var t=this.names[e],r=[];if(!t)throw new Error("There is no route named "+e);for(var n=0,i=t.handlers.length;i>n;n++)r.push(t.handlers[n]);return r},hasRoute:function(e){return!!this.names[e]},generate:function(e,t){var r=this.names[e],n="";if(!r)throw new Error("There is no route named "+e);for(var i=r.segments,a=0,o=i.length;o>a;a++){var u=i[a];u instanceof s||(n+="/",n+=u.generate(t))}return"/"!==n.charAt(0)&&(n="/"+n),t&&t.queryParams&&(n+=this.generateQueryString(t.queryParams,r.handlers)),n},generateQueryString:function(e){var t=[],n=[];for(var i in e)e.hasOwnProperty(i)&&n.push(i);n.sort();for(var a=0,s=n.length;s>a;a++){i=n[a];var o=e[i];if(null!=o){var u=encodeURIComponent(i);if(r(o))for(var l=0,c=o.length;c>l;l++){var h=i+"[]="+encodeURIComponent(o[l]);t.push(h)}else u+="="+encodeURIComponent(o),t.push(u)}}return 0===t.length?"":"?"+t.join("&")},parseQueryString:function(e){for(var t=e.split("&"),r={},n=0;n2&&"[]"===s.slice(o-2)&&(u=!0,s=s.slice(0,o-2),r[s]||(r[s]=[])),i=a[1]?decodeURIComponent(a[1]):""),u?r[s].push(i):r[s]=i}return r},recognize:function(e){var t,r,n,i,a=[this.rootState],s={},o=!1;if(i=e.indexOf("?"),-1!==i){var u=e.substr(i+1,e.length);e=e.substr(0,i),s=this.parseQueryString(u)}for(e=decodeURI(e),"/"!==e.charAt(0)&&(e="/"+e),t=e.length,t>1&&"/"===e.charAt(t-1)&&(e=e.substr(0,t-1),o=!0),r=0,n=e.length;n>r&&(a=c(a,e.charAt(r)),a.length);r++);var h=[];for(r=0,n=a.length;n>r;r++)a[r].handlers&&h.push(a[r]);a=l(h);var m=h[0];return m&&m.handlers?(o&&"(.+)$"===m.regex.source.slice(-5)&&(e+="/"),p(m,e,s)):void 0}},y.prototype.map=f,t["default"]=y}),e("route-recognizer/dsl",["exports"],function(e){"use strict";function t(e,t,r){this.path=e,this.matcher=t,this.delegate=r}function r(e){this.routes={},this.children={},this.target=e}function n(e,r,i){return function(a,s){var o=e+a;return s?void s(n(o,r,i)):new t(e+a,r,i)}}function i(e,t,r){for(var n=0,i=0,a=e.length;a>i;i++)n+=e[i].path.length;t=t.substr(n);var s={path:t,handler:r};e.push(s)}function a(e,t,r,n){var s=t.routes;for(var o in s)if(s.hasOwnProperty(o)){var u=e.slice();i(u,o,s[o]),t.children[o]?a(u,t.children[o],r,n):r.call(n,u)}}t.prototype={to:function(e,t){var r=this.delegate;if(r&&r.willAddRoute&&(e=r.willAddRoute(this.matcher.target,e)),this.matcher.add(this.path,e),t){if(0===t.length)throw new Error("You must have an argument in the function passed to `to`");this.matcher.addChild(this.path,e,t,this.delegate)}return this}},r.prototype={add:function(e,t){this.routes[e]=t},addChild:function(e,t,i,a){var s=new r(t);this.children[e]=s;var o=n(e,s,a);a&&a.contextEntered&&a.contextEntered(t,o),i(o)}},e["default"]=function(e,t){var i=new r;e(n("",i,this.delegate)),a([],i,function(e){t?t(this,e):this.add(e)},this)}}),e("router",["./router/router","exports"],function(e,t){"use strict";var r=e["default"];t["default"]=r}),e("router/handler-info",["./utils","rsvp/promise","exports"],function(e,t,r){"use strict";function n(e){var t=e||{};s(this,t),this.initialize(t)}function i(e,t){if(!e^!t)return!1;if(!e)return!0;for(var r in e)if(e.hasOwnProperty(r)&&e[r]!==t[r])return!1;return!0}var a=e.bind,s=e.merge,o=(e.serialize,e.promiseLabel),u=e.applyHook,l=t["default"];n.prototype={name:null,handler:null,params:null,context:null,factory:null,initialize:function(){},log:function(e,t){e.log&&e.log(this.name+": "+t)},promiseLabel:function(e){return o("'"+this.name+"' "+e)},getUnresolved:function(){return this},serialize:function(){return this.params||{}},resolve:function(e,t){var r=a(this,this.checkForAbort,e),n=a(this,this.runBeforeModelHook,t),i=a(this,this.getModel,t),s=a(this,this.runAfterModelHook,t),o=a(this,this.becomeResolved,t);return l.resolve(void 0,this.promiseLabel("Start handler")).then(r,null,this.promiseLabel("Check for abort")).then(n,null,this.promiseLabel("Before model")).then(r,null,this.promiseLabel("Check if aborted during 'beforeModel' hook")).then(i,null,this.promiseLabel("Model")).then(r,null,this.promiseLabel("Check if aborted in 'model' hook")).then(s,null,this.promiseLabel("After model")).then(r,null,this.promiseLabel("Check if aborted in 'afterModel' hook")).then(o,null,this.promiseLabel("Become resolved"))},runBeforeModelHook:function(e){return e.trigger&&e.trigger(!0,"willResolveModel",e,this.handler),this.runSharedModelHook(e,"beforeModel",[])},runAfterModelHook:function(e,t){var r=this.name;return this.stashResolvedModel(e,t),this.runSharedModelHook(e,"afterModel",[t]).then(function(){return e.resolvedModels[r]},null,this.promiseLabel("Ignore fulfillment value and return model value"))},runSharedModelHook:function(e,t,r){this.log(e,"calling "+t+" hook"),this.queryParams&&r.push(this.queryParams),r.push(e);var n=u(this.handler,t,r);return n&&n.isTransition&&(n=null),l.resolve(n,this.promiseLabel("Resolve value returned from one of the model hooks"))},getModel:null,checkForAbort:function(e,t){return l.resolve(e(),this.promiseLabel("Check for abort")).then(function(){return t},null,this.promiseLabel("Ignore fulfillment value and continue"))},stashResolvedModel:function(e,t){e.resolvedModels=e.resolvedModels||{},e.resolvedModels[this.name]=t},becomeResolved:function(e,t){var r=this.serialize(t);return e&&(this.stashResolvedModel(e,t),e.params=e.params||{},e.params[this.name]=r),this.factory("resolved",{context:t,name:this.name,handler:this.handler,params:r})},shouldSupercede:function(e){if(!e)return!0;var t=e.context===this.context;return e.name!==this.name||this.hasOwnProperty("context")&&!t||this.hasOwnProperty("params")&&!i(this.params,e.params)}},r["default"]=n}),e("router/handler-info/factory",["router/handler-info/resolved-handler-info","router/handler-info/unresolved-handler-info-by-object","router/handler-info/unresolved-handler-info-by-param","exports"],function(e,t,r,n){"use strict";function i(e,t){var r=i.klasses[e],n=new r(t||{});return n.factory=i,n}var a=e["default"],s=t["default"],o=r["default"];i.klasses={resolved:a,param:o,object:s},n["default"]=i}),e("router/handler-info/resolved-handler-info",["../handler-info","router/utils","rsvp/promise","exports"],function(e,t,r,n){"use strict";var i=e["default"],a=t.subclass,s=(t.promiseLabel,r["default"]),o=a(i,{resolve:function(e,t){return t&&t.resolvedModels&&(t.resolvedModels[this.name]=this.context),s.resolve(this,this.promiseLabel("Resolve"))},getUnresolved:function(){return this.factory("param",{name:this.name,handler:this.handler,params:this.params})},isResolved:!0});n["default"]=o}),e("router/handler-info/unresolved-handler-info-by-object",["../handler-info","router/utils","rsvp/promise","exports"],function(e,t,r,n){"use strict";var i=e["default"],a=(t.merge,t.subclass),s=(t.promiseLabel,t.isParam),o=r["default"],u=a(i,{getModel:function(e){return this.log(e,this.name+": resolving provided model"),o.resolve(this.context)},initialize:function(e){this.names=e.names||[],this.context=e.context},serialize:function(e){var t=e||this.context,r=this.names,n=this.handler,i={};if(s(t))return i[r[0]]=t,i;if(n.serialize)return n.serialize(t,r);if(1===r.length){var a=r[0];return i[a]=/_id$/.test(a)?t.id:t,i}}});n["default"]=u}),e("router/handler-info/unresolved-handler-info-by-param",["../handler-info","router/utils","exports"],function(e,t,r){"use strict";var n=e["default"],i=t.resolveHook,a=t.merge,s=t.subclass,o=(t.promiseLabel,s(n,{initialize:function(e){this.params=e.params||{}},getModel:function(e){var t=this.params;e&&e.queryParams&&(t={},a(t,this.params),t.queryParams=e.queryParams);var r=this.handler,n=i(r,"deserialize")||i(r,"model");return this.runSharedModelHook(e,n,[t])}}));r["default"]=o}),e("router/router",["route-recognizer","rsvp/promise","./utils","./transition-state","./transition","./transition-intent/named-transition-intent","./transition-intent/url-transition-intent","./handler-info","exports"],function(e,t,r,n,i,a,s,o,u){"use strict";function l(){this.recognizer=new w,this.reset()}function c(e,t){var r,n=!!this.activeTransition,i=n?this.activeTransition.state:this.state,a=e.applyToState(i,this.recognizer,this.getHandler,t),s=N(i.queryParams,a.queryParams);return y(a.handlerInfos,i.handlerInfos)?s&&(r=this.queryParamsTransition(s,n,i,a))?r:new D(this):t?void p(this,a):(r=new D(this,e,a),this.activeTransition&&this.activeTransition.abort(),this.activeTransition=r,r.promise=r.promise.then(function(e){return v(r,e.state) -},null,S("Settle transition promise when transition is finalized")),n||_(this,a,r),h(this,a,s),r)}function h(e,t,r){r&&(e._changedQueryParams=r.all,C(e,t.handlerInfos,!0,["queryParamsDidChange",r.changed,r.all,r.removed]),e._changedQueryParams=null)}function p(e,t,r){var n=f(e.state,t);P(n.exited,function(e){var t=e.handler;delete t.context,V(t,"reset",!0,r),V(t,"exit",r)});var i=e.oldState=e.state;e.state=t;var a=e.currentHandlerInfos=n.unchanged.slice();try{P(n.reset,function(e){var t=e.handler;V(t,"reset",!1,r)}),P(n.updatedContext,function(e){return m(a,e,!1,r)}),P(n.entered,function(e){return m(a,e,!0,r)})}catch(s){throw e.state=i,e.currentHandlerInfos=i.handlerInfos,s}e.state.queryParams=g(e,a,t.queryParams,r)}function m(e,t,r,n){var i=t.handler,a=t.context;if(r&&V(i,"enter",n),n&&n.isAborted)throw new j;if(i.context=a,V(i,"contextDidChange"),V(i,"setup",a,n),n&&n.isAborted)throw new j;return e.push(t),!0}function f(e,t){var r,n,i,a=e.handlerInfos,s=t.handlerInfos,o={updatedContext:[],exited:[],entered:[],unchanged:[]},u=!1;for(n=0,i=s.length;i>n;n++){var l=a[n],c=s[n];l&&l.handler===c.handler||(r=!0),r?(o.entered.push(c),l&&o.exited.unshift(l)):u||l.context!==c.context?(u=!0,o.updatedContext.push(c)):o.unchanged.push(l)}for(n=s.length,i=a.length;i>n;n++)o.exited.unshift(a[n]);return o.reset=o.updatedContext.slice(),o.reset.reverse(),o}function d(e,t){var r=e.urlMethod;if(r){for(var n=e.router,i=t.handlerInfos,a=i[i.length-1].name,s={},o=i.length-1;o>=0;--o){var u=i[o];A(s,u.params),u.handler.inaccessibleByURL&&(r=null)}if(r){s.queryParams=e._visibleQueryParams||t.queryParams;var l=n.recognizer.generate(a,s);"replace"===r?n.replaceURL(l):n.updateURL(l)}}}function v(e,t){try{O(e.router,e.sequence,"Resolved all models on destination route; finalizing transition.");{var r=e.router,n=t.handlerInfos;e.sequence}return p(r,t,e),e.isAborted?(r.state.handlerInfos=r.currentHandlerInfos,x.reject(k(e))):(d(e,t,e.intent.url),e.isActive=!1,r.activeTransition=null,C(r,r.currentHandlerInfos,!0,["didTransition"]),r.didTransition&&r.didTransition(r.currentHandlerInfos),O(r,e.sequence,"TRANSITION COMPLETE."),n[n.length-1].handler)}catch(i){if(!(i instanceof j)){var a=e.state.handlerInfos;e.trigger(!0,"error",i,e,a[a.length-1].handler),e.abort()}throw i}}function b(e,t,r){var n=t[0]||"/",i=t[t.length-1],a={};i&&i.hasOwnProperty("queryParams")&&(a=L.call(t).queryParams);var s;if(0===t.length){O(e,"Updating query params");var o=e.state.handlerInfos;s=new M({name:o[o.length-1].name,contexts:[],queryParams:a})}else"/"===n.charAt(0)?(O(e,"Attempting URL transition to "+n),s=new R({url:n})):(O(e,"Attempting transition to "+n),s=new M({name:t[0],contexts:E.call(t,1),queryParams:a}));return e.transitionByIntent(s,r)}function y(e,t){if(e.length!==t.length)return!1;for(var r=0,n=e.length;n>r;++r)if(e[r]!==t[r])return!1;return!0}function g(e,t,r,n){for(var i in r)r.hasOwnProperty(i)&&null===r[i]&&delete r[i];var a=[];C(e,t,!0,["finalizeQueryParamChange",r,a,n]),n&&(n._visibleQueryParams={});for(var s={},o=0,u=a.length;u>o;++o){var l=a[o];s[l.key]=l.value,n&&l.visible!==!1&&(n._visibleQueryParams[l.key]=l.value)}return s}function _(e,t,r){var n,i,a,s,o,u,l=e.state.handlerInfos,c=[],h=null;for(s=l.length,a=0;s>a;a++){if(o=l[a],u=t.handlerInfos[a],!u||o.name!==u.name){h=a;break}u.isResolved||c.push(o)}null!==h&&(n=l.slice(h,s),i=function(e){for(var t=0,r=n.length;r>t;t++)if(n[t].name===e)return!0;return!1},e._triggerWillLeave(n,r,i)),c.length>0&&e._triggerWillChangeContext(c,r),C(e,l,!0,["willTransition",r])}var w=e["default"],x=t["default"],C=r.trigger,O=r.log,E=r.slice,P=r.forEach,A=r.merge,T=(r.serialize,r.extractQueryParams),N=r.getChangelist,S=r.promiseLabel,V=r.callHook,I=n["default"],k=i.logAbort,D=i.Transition,j=i.TransitionAborted,M=a["default"],R=s["default"],L=(o.ResolvedHandlerInfo,Array.prototype.pop);l.prototype={map:function(e){this.recognizer.delegate=this.delegate,this.recognizer.map(e,function(e,t){for(var r=t.length-1,n=!0;r>=0&&n;--r){var i=t[r];e.add(t,{as:i.handler}),n="/"===i.path||""===i.path||".index"===i.handler.slice(-6)}})},hasRoute:function(e){return this.recognizer.hasRoute(e)},queryParamsTransition:function(e,t,r,n){var i=this;if(h(this,n,e),!t&&this.activeTransition)return this.activeTransition;var a=new D(this);return a.queryParamsOnly=!0,r.queryParams=g(this,n.handlerInfos,n.queryParams,a),a.promise=a.promise.then(function(e){return d(a,r,!0),i.didTransition&&i.didTransition(i.currentHandlerInfos),e},null,S("Transition complete")),a},transitionByIntent:function(e){try{return c.apply(this,arguments)}catch(t){return new D(this,e,null,t)}},reset:function(){this.state&&P(this.state.handlerInfos.slice().reverse(),function(e){var t=e.handler;V(t,"exit")}),this.state=new I,this.currentHandlerInfos=null},activeTransition:null,handleURL:function(e){var t=E.call(arguments);return"/"!==e.charAt(0)&&(t[0]="/"+e),b(this,t).method(null)},updateURL:function(){throw new Error("updateURL is not implemented")},replaceURL:function(e){this.updateURL(e)},transitionTo:function(){return b(this,arguments)},intermediateTransitionTo:function(){return b(this,arguments,!0)},refresh:function(e){for(var t=this.activeTransition?this.activeTransition.state:this.state,r=t.handlerInfos,n={},i=0,a=r.length;a>i;++i){var s=r[i];n[s.name]=s.params||{}}O(this,"Starting a refresh transition");var o=new M({name:r[r.length-1].name,pivotHandler:e||r[0].handler,contexts:[],queryParams:this._changedQueryParams||t.queryParams||{}});return this.transitionByIntent(o,!1)},replaceWith:function(){return b(this,arguments).method("replace")},generate:function(e){for(var t=T(E.call(arguments,1)),r=t[0],n=t[1],i=new M({name:e,contexts:r}),a=i.applyToState(this.state,this.recognizer,this.getHandler),s={},o=0,u=a.handlerInfos.length;u>o;++o){var l=a.handlerInfos[o],c=l.serialize();A(s,c)}return s.queryParams=n,this.recognizer.generate(e,s)},applyIntent:function(e,t){var r=new M({name:e,contexts:t}),n=this.activeTransition&&this.activeTransition.state||this.state;return r.applyToState(n,this.recognizer,this.getHandler)},isActiveIntent:function(e,t,r){var n,i,a=this.state.handlerInfos;if(!a.length)return!1;var s=a[a.length-1].name,o=this.recognizer.handlersFor(s),u=0;for(i=o.length;i>u&&(n=a[u],n.name!==e);++u);if(u===o.length)return!1;var l=new I;l.handlerInfos=a.slice(0,u+1),o=o.slice(0,u+1);var c=new M({name:s,contexts:t}),h=c.applyToHandlers(l,o,this.getHandler,s,!0,!0),p=y(h.handlerInfos,l.handlerInfos);if(!r||!p)return p;var m={};A(m,r);var f=this.state.queryParams;for(var d in f)f.hasOwnProperty(d)&&m.hasOwnProperty(d)&&(m[d]=f[d]);return p&&!N(m,r)},isActive:function(e){var t=T(E.call(arguments,1));return this.isActiveIntent(e,t[0],t[1])},trigger:function(){var e=E.call(arguments);C(this,this.currentHandlerInfos,!1,e)},log:null,_willChangeContextEvent:"willChangeContext",_triggerWillChangeContext:function(e,t){C(this,e,!0,[this._willChangeContextEvent,t])},_triggerWillLeave:function(e,t,r){C(this,e,!0,["willLeave",t,r])}},u["default"]=l}),e("router/transition-intent",["./utils","exports"],function(e,t){"use strict";function r(e){this.initialize(e),this.data=this.data||{}}e.merge;r.prototype={initialize:null,applyToState:null},t["default"]=r}),e("router/transition-intent/named-transition-intent",["../transition-intent","../transition-state","../handler-info/factory","../utils","exports"],function(e,t,r,n,i){"use strict";var a=e["default"],s=t["default"],o=r["default"],u=n.isParam,l=n.extractQueryParams,c=n.merge,h=n.subclass;i["default"]=h(a,{name:null,pivotHandler:null,contexts:null,queryParams:null,initialize:function(e){this.name=e.name,this.pivotHandler=e.pivotHandler,this.contexts=e.contexts||[],this.queryParams=e.queryParams},applyToState:function(e,t,r,n){var i=l([this.name].concat(this.contexts)),a=i[0],s=(i[1],t.handlersFor(a[0])),o=s[s.length-1].handler;return this.applyToHandlers(e,s,r,o,n)},applyToHandlers:function(e,t,r,n,i,a){var o,u,l=new s,h=this.contexts.slice(0),p=t.length;if(this.pivotHandler)for(o=0,u=t.length;u>o;++o)if(r(t[o].handler)===this.pivotHandler){p=o;break}!this.pivotHandler;for(o=t.length-1;o>=0;--o){var m=t[o],f=m.handler,d=r(f),v=e.handlerInfos[o],b=null;if(b=m.names.length>0?o>=p?this.createParamHandlerInfo(f,d,m.names,h,v):this.getHandlerInfoForDynamicSegment(f,d,m.names,h,v,n,o):this.createParamHandlerInfo(f,d,m.names,h,v),a){b=b.becomeResolved(null,b.context);var y=v&&v.context;m.names.length>0&&b.context===y&&(b.params=v&&v.params),b.context=y}var g=v;(o>=p||b.shouldSupercede(v))&&(p=Math.min(o,p),g=b),i&&!a&&(g=g.becomeResolved(null,g.context)),l.handlerInfos.unshift(g)}if(h.length>0)throw new Error("More context objects were passed than there are dynamic segments for the route: "+n);return i||this.invalidateChildren(l.handlerInfos,p),c(l.queryParams,this.queryParams||{}),l},invalidateChildren:function(e,t){for(var r=t,n=e.length;n>r;++r){{e[r]}e[r]=e[r].getUnresolved()}},getHandlerInfoForDynamicSegment:function(e,t,r,n,i,a,s){{var l;r.length}if(n.length>0){if(l=n[n.length-1],u(l))return this.createParamHandlerInfo(e,t,r,n,i);n.pop()}else{if(i&&i.name===e)return i;if(!this.preTransitionState)return i;var c=this.preTransitionState.handlerInfos[s];l=c&&c.context}return o("object",{name:e,handler:t,context:l,names:r})},createParamHandlerInfo:function(e,t,r,n,i){for(var a={},s=r.length;s--;){var l=i&&e===i.name&&i.params||{},c=n[n.length-1],h=r[s];if(u(c))a[h]=""+n.pop();else{if(!l.hasOwnProperty(h))throw new Error("You didn't provide enough string/numeric parameters to satisfy all of the dynamic segments for route "+e);a[h]=l[h]}}return o("param",{name:e,handler:t,params:a})}})}),e("router/transition-intent/url-transition-intent",["../transition-intent","../transition-state","../handler-info/factory","../utils","exports"],function(e,t,r,n,i){"use strict";function a(e){this.message=e||"UnrecognizedURLError",this.name="UnrecognizedURLError"}var s=e["default"],o=t["default"],u=r["default"],l=(n.oCreate,n.merge),c=n.subclass;i["default"]=c(s,{url:null,initialize:function(e){this.url=e.url},applyToState:function(e,t,r){var n,i,s=new o,c=t.recognize(this.url);if(!c)throw new a(this.url);var h=!1;for(n=0,i=c.length;i>n;++n){var p=c[n],m=p.handler,f=r(m);if(f.inaccessibleByURL)throw new a(this.url);var d=u("param",{name:m,handler:f,params:p.params}),v=e.handlerInfos[n];h||d.shouldSupercede(v)?(h=!0,s.handlerInfos[n]=d):s.handlerInfos[n]=v}return l(s.queryParams,c.queryParams),s}})}),e("router/transition-state",["./handler-info","./utils","rsvp/promise","exports"],function(e,t,r,n){"use strict";function i(){this.handlerInfos=[],this.queryParams={},this.params={}}var a=(e.ResolvedHandlerInfo,t.forEach),s=t.promiseLabel,o=t.callHook,u=r["default"];i.prototype={handlerInfos:null,queryParams:null,params:null,promiseLabel:function(e){var t="";return a(this.handlerInfos,function(e){""!==t&&(t+="."),t+=e.name}),s("'"+t+"': "+e)},resolve:function(e,t){function r(){return u.resolve(e(),c.promiseLabel("Check if should continue"))["catch"](function(e){return h=!0,u.reject(e)},c.promiseLabel("Handle abort"))}function n(e){var r=c.handlerInfos,n=t.resolveIndex>=r.length?r.length-1:t.resolveIndex;return u.reject({error:e,handlerWithError:c.handlerInfos[n].handler,wasAborted:h,state:c})}function i(e){var n=c.handlerInfos[t.resolveIndex].isResolved;if(c.handlerInfos[t.resolveIndex++]=e,!n){var i=e.handler;o(i,"redirect",e.context,t)}return r().then(s,null,c.promiseLabel("Resolve handler"))}function s(){if(t.resolveIndex===c.handlerInfos.length)return{error:null,state:c};var e=c.handlerInfos[t.resolveIndex];return e.resolve(r,t).then(i,null,c.promiseLabel("Proceed"))}var l=this.params;a(this.handlerInfos,function(e){l[e.name]=e.params||{}}),t=t||{},t.resolveIndex=0;var c=this,h=!1;return u.resolve(null,this.promiseLabel("Start transition")).then(s,null,this.promiseLabel("Resolve handler"))["catch"](n,this.promiseLabel("Handle error"))}},n["default"]=i}),e("router/transition",["rsvp/promise","./handler-info","./utils","exports"],function(e,t,r,n){"use strict";function i(e,t,r,n){function s(){return u.isAborted?o.reject(void 0,h("Transition aborted - reject")):void 0}var u=this;if(this.state=r||e.state,this.intent=t,this.router=e,this.data=this.intent&&this.intent.data||{},this.resolvedModels={},this.queryParams={},n)return void(this.promise=o.reject(n));if(r){this.params=r.params,this.queryParams=r.queryParams,this.handlerInfos=r.handlerInfos;var l=r.handlerInfos.length;l&&(this.targetName=r.handlerInfos[l-1].name);for(var c=0;l>c;++c){var p=r.handlerInfos[c];if(!p.isResolved)break;this.pivotHandler=p.handler}this.sequence=i.currentSequence++,this.promise=r.resolve(s,this)["catch"](function(e){return e.wasAborted||u.isAborted?o.reject(a(u)):(u.trigger("error",e.error,u,e.handlerWithError),u.abort(),o.reject(e.error))},h("Handle Abort"))}else this.promise=o.resolve(this.state),this.params={}}function a(e){return c(e.router,e.sequence,"detected abort."),new s}function s(e){this.message=e||"TransitionAborted",this.name="TransitionAborted"}var o=e["default"],u=(t.ResolvedHandlerInfo,r.trigger),l=r.slice,c=r.log,h=r.promiseLabel;i.currentSequence=0,i.prototype={targetName:null,urlMethod:"update",intent:null,params:null,pivotHandler:null,resolveIndex:0,handlerInfos:null,resolvedModels:null,isActive:!0,state:null,queryParamsOnly:!1,isTransition:!0,isExiting:function(e){for(var t=this.handlerInfos,r=0,n=t.length;n>r;++r){var i=t[r];if(i.name===e||i.handler===e)return!1}return!0},promise:null,data:null,then:function(e,t,r){return this.promise.then(e,t,r)},"catch":function(e,t){return this.promise["catch"](e,t)},"finally":function(e,t){return this.promise["finally"](e,t)},abort:function(){return this.isAborted?this:(c(this.router,this.sequence,this.targetName+": transition was aborted"),this.intent.preTransitionState=this.router.state,this.isAborted=!0,this.isActive=!1,this.router.activeTransition=null,this)},retry:function(){return this.abort(),this.router.transitionByIntent(this.intent,!1)},method:function(e){return this.urlMethod=e,this},trigger:function(e){var t=l.call(arguments);"boolean"==typeof e?t.shift():e=!1,u(this.router,this.state.handlerInfos.slice(0,this.resolveIndex+1),e,t)},followRedirects:function(){var e=this.router;return this.promise["catch"](function(t){return e.activeTransition?e.activeTransition.followRedirects():o.reject(t)})},toString:function(){return"Transition (sequence "+this.sequence+")"},log:function(e){c(this.router,this.sequence,e)}},i.prototype.send=i.prototype.trigger,n.Transition=i,n.logAbort=a,n.TransitionAborted=s}),e("router/utils",["exports"],function(e){"use strict";function t(e,t){for(var r in t)t.hasOwnProperty(r)&&(e[r]=t[r])}function r(e){var t,r,n=e&&e.length;return n&&n>0&&e[n-1]&&e[n-1].hasOwnProperty("queryParams")?(r=e[n-1].queryParams,t=v.call(e,0,n-1),[t,r]):[e,null]}function n(e){for(var t in e)if("number"==typeof e[t])e[t]=""+e[t];else if(b(e[t]))for(var r=0,n=e[t].length;n>r;r++)e[t][r]=""+e[t][r]}function i(e,t,r){e.log&&(3===arguments.length?e.log("Transition #"+t+": "+r):(r=t,e.log(r)))}function a(e,t){var r=arguments;return function(n){var i=v.call(r,2);return i.push(n),t.apply(e,i)}}function s(e){return"string"==typeof e||e instanceof String||"number"==typeof e||e instanceof Number}function o(e,t){for(var r=0,n=e.length;n>r&&!1!==t(e[r]);r++);}function u(e,t,r,n){if(e.triggerEvent)return void e.triggerEvent(t,r,n);var i=n.shift();if(!t){if(r)return;throw new Error("Could not trigger event '"+i+"'. There are no active handlers")}for(var a=!1,s=t.length-1;s>=0;s--){var o=t[s],u=o.handler;if(u.events&&u.events[i]){if(u.events[i].apply(u,n)!==!0)return;a=!0}}if(!a&&!r)throw new Error("Nothing handled the event '"+i+"'.")}function l(e,r){var i,a={all:{},changed:{},removed:{}};t(a.all,r);var s=!1;n(e),n(r);for(i in e)e.hasOwnProperty(i)&&(r.hasOwnProperty(i)||(s=!0,a.removed[i]=e[i]));for(i in r)if(r.hasOwnProperty(i))if(b(e[i])&&b(r[i]))if(e[i].length!==r[i].length)a.changed[i]=r[i],s=!0;else for(var o=0,u=e[i].length;u>o;o++)e[i][o]!==r[i][o]&&(a.changed[i]=r[i],s=!0);else e[i]!==r[i]&&(a.changed[i]=r[i],s=!0);return s&&a}function c(e){return"Router: "+e}function h(e,r){function n(t){e.call(this,t||{})}return n.prototype=y(e.prototype),t(n.prototype,r),n}function p(e,t){if(e){var r="_"+t;return e[r]&&r||e[t]&&t}}function m(e,t){var r=v.call(arguments,2);return f(e,t,r)}function f(e,t,r){var n=p(e,t);return n?e[n].apply(e,r):void 0}var d,v=Array.prototype.slice;d=Array.isArray?Array.isArray:function(e){return"[object Array]"===Object.prototype.toString.call(e)};var b=d;e.isArray=b;var y=Object.create||function(e){function t(){}return t.prototype=e,new t};e.oCreate=y,e.extractQueryParams=r,e.log=i,e.bind=a,e.forEach=o,e.trigger=u,e.getChangelist=l,e.promiseLabel=c,e.subclass=h,e.merge=t,e.slice=v,e.isParam=s,e.coerceQueryParamsToString=n,e.callHook=m,e.resolveHook=p,e.applyHook=f}),e("rsvp",["./rsvp/promise","./rsvp/events","./rsvp/node","./rsvp/all","./rsvp/all-settled","./rsvp/race","./rsvp/hash","./rsvp/hash-settled","./rsvp/rethrow","./rsvp/defer","./rsvp/config","./rsvp/map","./rsvp/resolve","./rsvp/reject","./rsvp/filter","./rsvp/asap","exports"],function(e,t,r,n,i,a,s,o,u,l,c,h,p,m,f,d,v){"use strict";function b(e,t){S.async(e,t)}function y(){S.on.apply(S,arguments)}function g(){S.off.apply(S,arguments)}var _=e["default"],w=t["default"],x=r["default"],C=n["default"],O=i["default"],E=a["default"],P=s["default"],A=o["default"],T=u["default"],N=l["default"],S=c.config,V=c.configure,I=h["default"],k=p["default"],D=m["default"],j=f["default"],M=d["default"];S.async=M;var R=k;if("undefined"!=typeof window&&"object"==typeof window.__PROMISE_INSTRUMENTATION__){var L=window.__PROMISE_INSTRUMENTATION__;V("instrument",!0);for(var H in L)L.hasOwnProperty(H)&&y(H,L[H])}v.cast=R,v.Promise=_,v.EventTarget=w,v.all=C,v.allSettled=O,v.race=E,v.hash=P,v.hashSettled=A,v.rethrow=T,v.defer=N,v.denodeify=x,v.configure=V,v.on=y,v.off=g,v.resolve=k,v.reject=D,v.async=b,v.map=I,v.filter=j}),e("rsvp.umd",["./rsvp"],function(t){"use strict";var r=t.Promise,n=t.allSettled,i=t.hash,a=t.hashSettled,s=t.denodeify,o=t.on,u=t.off,l=t.map,c=t.filter,h=t.resolve,p=t.reject,m=t.rethrow,f=t.all,d=t.defer,v=t.EventTarget,b=t.configure,y=t.race,g=t.async,_={race:y,Promise:r,allSettled:n,hash:i,hashSettled:a,denodeify:s,on:o,off:u,map:l,filter:c,resolve:h,reject:p,all:f,rethrow:m,defer:d,EventTarget:v,configure:b,async:g};"function"==typeof e&&e.amd?e(function(){return _}):"undefined"!=typeof module&&module.exports?module.exports=_:"undefined"!=typeof this&&(this.RSVP=_)}),e("rsvp/-internal",["./utils","./instrument","./config","exports"],function(e,t,r,n){"use strict";function i(){return new TypeError("A promises callback cannot return that same promise.")}function a(){}function s(e){try{return e.then}catch(t){return T.error=t,T}}function o(e,t,r,n){try{e.call(t,r,n)}catch(i){return i}}function u(e,t,r){O.async(function(e){var n=!1,i=o(r,t,function(r){n||(n=!0,t!==r?h(e,r):m(e,r))},function(t){n||(n=!0,f(e,t))},"Settle: "+(e._label||" unknown promise"));!n&&i&&(n=!0,f(e,i))},e)}function l(e,t){t._state===P?m(e,t._result):e._state===A?f(e,t._result):d(t,void 0,function(r){t!==r?h(e,r):m(e,r)},function(t){f(e,t)})}function c(e,t){if(t.constructor===e.constructor)l(e,t);else{var r=s(t);r===T?f(e,T.error):void 0===r?m(e,t):x(r)?u(e,t,r):m(e,t)}}function h(e,t){e===t?m(e,t):w(t)?c(e,t):m(e,t)}function p(e){e._onerror&&e._onerror(e._result),v(e)}function m(e,t){e._state===E&&(e._result=t,e._state=P,0===e._subscribers.length?O.instrument&&C("fulfilled",e):O.async(v,e))}function f(e,t){e._state===E&&(e._state=A,e._result=t,O.async(p,e))}function d(e,t,r,n){var i=e._subscribers,a=i.length;e._onerror=null,i[a]=t,i[a+P]=r,i[a+A]=n,0===a&&e._state&&O.async(v,e)}function v(e){var t=e._subscribers,r=e._state;if(O.instrument&&C(r===P?"fulfilled":"rejected",e),0!==t.length){for(var n,i,a=e._result,s=0;se;e+=2){var t=d[e],r=d[e+1];t(r),d[e]=void 0,d[e+1]=void 0}l=0}function u(){try{{var e=r("vertx");e.runOnLoop||e.runOnContext}return n()}catch(t){return s()}}var l=0;e["default"]=function(e,t){d[l]=e,d[l+1]=t,l+=2,2===l&&c()};var c,h="undefined"!=typeof window?window:void 0,p=h||{},m=p.MutationObserver||p.WebKitMutationObserver,f="undefined"!=typeof Uint8ClampedArray&&"undefined"!=typeof importScripts&&"undefined"!=typeof MessageChannel,d=new Array(1e3);c="undefined"!=typeof process&&"[object process]"==={}.toString.call(process)?t():m?i():f?a():void 0===h&&"function"==typeof r?u():s()}),e("rsvp/config",["./events","exports"],function(e,t){"use strict";function r(e,t){return"onerror"===e?void i.on("error",t):2!==arguments.length?i[e]:void(i[e]=t)}var n=e["default"],i={instrument:!1};n.mixin(i),t.config=i,t.configure=r}),e("rsvp/defer",["./promise","exports"],function(e,t){"use strict";var r=e["default"];t["default"]=function(e){var t={};return t.promise=new r(function(e,r){t.resolve=e,t.reject=r},e),t}}),e("rsvp/enumerator",["./utils","./-internal","exports"],function(e,t,r){"use strict";function n(e,t,r){return e===h?{state:"fulfilled",value:r}:{state:"rejected",reason:r}}function i(e,t,r,n){this._instanceConstructor=e,this.promise=new e(o,n),this._abortOnReject=r,this._validateInput(t)?(this._input=t,this.length=t.length,this._remaining=t.length,this._init(),0===this.length?l(this.promise,this._result):(this.length=this.length||0,this._enumerate(),0===this._remaining&&l(this.promise,this._result))):u(this.promise,this._validationError())}var a=e.isArray,s=e.isMaybeThenable,o=t.noop,u=t.reject,l=t.fulfill,c=t.subscribe,h=t.FULFILLED,p=t.REJECTED,m=t.PENDING;r.makeSettledResult=n,i.prototype._validateInput=function(e){return a(e)},i.prototype._validationError=function(){return new Error("Array Methods must be provided an Array")},i.prototype._init=function(){this._result=new Array(this.length)},r["default"]=i,i.prototype._enumerate=function(){for(var e=this.length,t=this.promise,r=this._input,n=0;t._state===m&&e>n;n++)this._eachEntry(r[n],n)},i.prototype._eachEntry=function(e,t){var r=this._instanceConstructor;s(e)?e.constructor===r&&e._state!==m?(e._onerror=null,this._settledAt(e._state,t,e._result)):this._willSettleAt(r.resolve(e),t):(this._remaining--,this._result[t]=this._makeResult(h,t,e))},i.prototype._settledAt=function(e,t,r){var n=this.promise;n._state===m&&(this._remaining--,this._abortOnReject&&e===p?u(n,r):this._result[t]=this._makeResult(e,t,r)),0===this._remaining&&l(n,this._result)},i.prototype._makeResult=function(e,t,r){return r},i.prototype._willSettleAt=function(e,t){var r=this;c(e,void 0,function(e){r._settledAt(h,t,e)},function(e){r._settledAt(p,t,e)})}}),e("rsvp/events",["exports"],function(e){"use strict";function t(e,t){for(var r=0,n=e.length;n>r;r++)if(e[r]===t)return r;return-1}function r(e){var t=e._promiseCallbacks;return t||(t=e._promiseCallbacks={}),t}e["default"]={mixin:function(e){return e.on=this.on,e.off=this.off,e.trigger=this.trigger,e._promiseCallbacks=void 0,e},on:function(e,n){var i,a=r(this);i=a[e],i||(i=a[e]=[]),-1===t(i,n)&&i.push(n)},off:function(e,n){var i,a,s=r(this);return n?(i=s[e],a=t(i,n),void(-1!==a&&i.splice(a,1))):void(s[e]=[])},trigger:function(e,t){var n,i,a=r(this);if(n=a[e])for(var s=0;so;o++)s[o]=t(e[o]);return n.all(s,r).then(function(t){for(var r=new Array(a),n=0,i=0;a>i;i++)t[i]&&(r[n]=e[i],n++);return r.length=n,r})})}}),e("rsvp/hash-settled",["./promise","./enumerator","./promise-hash","./utils","exports"],function(e,t,r,n,i){"use strict";function a(e,t,r){this._superConstructor(e,t,!1,r)}var s=e["default"],o=t.makeSettledResult,u=r["default"],l=t["default"],c=n.o_create;a.prototype=c(u.prototype),a.prototype._superConstructor=l,a.prototype._makeResult=o,a.prototype._validationError=function(){return new Error("hashSettled must be called with an object")},i["default"]=function(e,t){return new a(s,e,t).promise}}),e("rsvp/hash",["./promise","./promise-hash","exports"],function(e,t,r){"use strict";var n=e["default"],i=t["default"];r["default"]=function(e,t){return new i(n,e,t).promise}}),e("rsvp/instrument",["./config","./utils","exports"],function(e,t,r){"use strict";function n(){setTimeout(function(){for(var e,t=0;to;o++)s[o]=t(e[o]);return n.all(s,r)})}}),e("rsvp/node",["./promise","./-internal","./utils","exports"],function(e,t,r,n){"use strict";function i(){this.value=void 0}function a(e){try{return e.then}catch(t){return y.value=t,y}}function s(e,t,r){try{e.apply(t,r)}catch(n){return y.value=n,y}}function o(e,t){for(var r,n,i={},a=e.length,s=new Array(a),o=0;a>o;o++)s[o]=e[o];for(n=0;nn;n++)r[n-1]=e[n];return r}function l(e,t){return{then:function(r,n){return e.call(t,r,n)}}}function c(e,t,r,n){var i=s(r,n,t);return i===y&&v(e,i.value),e}function h(e,t,r,n){return m.all(t).then(function(t){var i=s(r,n,t);return i===y&&v(e,i.value),e})}function p(e){return e&&"object"==typeof e?e.constructor===m?!0:a(e):!1}var m=e["default"],f=t.noop,d=t.resolve,v=t.reject,b=r.isArray,y=new i,g=new i;n["default"]=function(e,t){var r=function(){for(var r,n=this,i=arguments.length,a=new Array(i+1),s=!1,y=0;i>y;++y){if(r=arguments[y],!s){if(s=p(r),s===g){var _=new m(f);return v(_,g.value),_}s&&s!==!0&&(r=l(s,r))}a[y]=r}var w=new m(f);return a[i]=function(e,r){e?v(w,e):void 0===t?d(w,r):t===!0?d(w,u(arguments)):b(t)?d(w,o(arguments,t)):d(w,r)},s?h(w,a,e,n):c(w,a,e,n)};return r.__proto__=e,r}}),e("rsvp/promise-hash",["./enumerator","./-internal","./utils","exports"],function(e,t,r,n){"use strict";function i(e,t,r){this._superConstructor(e,t,!0,r)}var a=e["default"],s=t.PENDING,o=r.o_create;n["default"]=i,i.prototype=o(a.prototype),i.prototype._superConstructor=a,i.prototype._init=function(){this._result={}},i.prototype._validateInput=function(e){return e&&"object"==typeof e},i.prototype._validationError=function(){return new Error("Promise.hash must be called with an object")},i.prototype._enumerate=function(){var e=this.promise,t=this._input,r=[];for(var n in t)e._state===s&&t.hasOwnProperty(n)&&r.push({position:n,entry:t[n]});var i=r.length;this._remaining=i;for(var a,o=0;e._state===s&&i>o;o++)a=r[o],this._eachEntry(a.entry,a.position)}}),e("rsvp/promise",["./config","./instrument","./utils","./-internal","./promise/all","./promise/race","./promise/resolve","./promise/reject","exports"],function(e,t,r,n,i,a,s,o,u){"use strict";function l(){throw new TypeError("You must pass a resolver function as the first argument to the promise constructor")}function c(){throw new TypeError("Failed to construct 'Promise': Please use the 'new' operator, this object constructor cannot be called as a function.")}function h(e,t){this._id=A++,this._label=t,this._state=void 0,this._result=void 0,this._subscribers=[],p.instrument&&m("created",this),v!==e&&(f(e)||l(),this instanceof h||c(),y(this,e))}var p=e.config,m=t["default"],f=r.isFunction,d=r.now,v=n.noop,b=n.subscribe,y=n.initializePromise,g=n.invokeCallback,_=n.FULFILLED,w=n.REJECTED,x=i["default"],C=a["default"],O=s["default"],E=o["default"],P="rsvp_"+d()+"-",A=0;u["default"]=h,h.cast=O,h.all=x,h.race=C,h.resolve=O,h.reject=E,h.prototype={constructor:h,_guidKey:P,_onerror:function(e){p.trigger("error",e)},then:function(e,t,r){var n=this,i=n._state;if(i===_&&!e||i===w&&!t)return p.instrument&&m("chained",this,this),this;n._onerror=null;var a=new this.constructor(v,r),s=n._result;if(p.instrument&&m("chained",n,a),i){var o=arguments[i-1];p.async(function(){g(i,a,o,s)})}else b(n,a,e,t);return a},"catch":function(e,t){return this.then(null,e,t)},"finally":function(e,t){var r=this.constructor;return this.then(function(t){return r.resolve(e()).then(function(){return t})},function(t){return r.resolve(e()).then(function(){throw t})},t)}}}),e("rsvp/promise/all",["../enumerator","exports"],function(e,t){"use strict";var r=e["default"];t["default"]=function(e,t){return new r(this,e,!0,t).promise}}),e("rsvp/promise/race",["../utils","../-internal","exports"],function(e,t,r){"use strict";var n=e.isArray,i=t.noop,a=t.resolve,s=t.reject,o=t.subscribe,u=t.PENDING;r["default"]=function(e,t){function r(e){a(h,e)}function l(e){s(h,e)}var c=this,h=new c(i,t);if(!n(e))return s(h,new TypeError("You must pass an array to race.")),h;for(var p=e.length,m=0;h._state===u&&p>m;m++)o(c.resolve(e[m]),void 0,r,l);return h}}),e("rsvp/promise/reject",["../-internal","exports"],function(e,t){"use strict";var r=e.noop,n=e.reject;t["default"]=function(e,t){var i=this,a=new i(r,t);return n(a,e),a}}),e("rsvp/promise/resolve",["../-internal","exports"],function(e,t){"use strict";var r=e.noop,n=e.resolve;t["default"]=function(e,t){var i=this;if(e&&"object"==typeof e&&e.constructor===i)return e;var a=new i(r,t);return n(a,e),a}}),e("rsvp/race",["./promise","exports"],function(e,t){"use strict";var r=e["default"];t["default"]=function(e,t){return r.race(e,t)}}),e("rsvp/reject",["./promise","exports"],function(e,t){"use strict";var r=e["default"];t["default"]=function(e,t){return r.reject(e,t)}}),e("rsvp/resolve",["./promise","exports"],function(e,t){"use strict";var r=e["default"];t["default"]=function(e,t){return r.resolve(e,t)}}),e("rsvp/rethrow",["exports"],function(e){"use strict"; -e["default"]=function(e){throw setTimeout(function(){throw e}),e}}),e("rsvp/utils",["exports"],function(e){"use strict";function t(e){return"function"==typeof e||"object"==typeof e&&null!==e}function r(e){return"function"==typeof e}function n(e){return"object"==typeof e&&null!==e}function i(){}e.objectOrFunction=t,e.isFunction=r,e.isMaybeThenable=n;var a;a=Array.isArray?Array.isArray:function(e){return"[object Array]"===Object.prototype.toString.call(e)};var s=a;e.isArray=s;var o=Date.now||function(){return(new Date).getTime()};e.now=o;var u=Object.create||function(e){if(arguments.length>1)throw new Error("Second argument not supported");if("object"!=typeof e)throw new TypeError("Argument must be an object");return i.prototype=e,new i};e.o_create=u}),t("ember")}();