diff --git a/assets/scripts/app/controllers/current_user.coffee b/assets/scripts/app/controllers/current_user.coffee index 4b8ca9e4..affccf9c 100644 --- a/assets/scripts/app/controllers/current_user.coffee +++ b/assets/scripts/app/controllers/current_user.coffee @@ -1,11 +1,19 @@ +delegate = (name, options) -> + options ||= options + -> + target = @get(options.to) + target[name].apply(target, arguments) + Travis.CurrentUserController = Em.ObjectController.extend sync: -> - @get('model').sync() + @get('content').sync() - model: Ember.computed.alias('auth.currentUser') + content: (-> + @get('auth.currentUser') + ).property('auth.currentUser') syncingDidChange: (-> - if (user = @get('model')) && user.get('isSyncing') && !user.get('syncedAt') + if (user = @get('content')) && user.get('isSyncing') && !user.get('syncedAt') Ember.run.scheduleOnce 'routerTransitions', this, -> @container.lookup('router:main').send('renderFirstSync') - ).observes('isSyncing', 'auth.currentUser') + ).observes('isSyncing', 'content') diff --git a/assets/scripts/app/controllers/flash.coffee b/assets/scripts/app/controllers/flash.coffee index 9b857656..721b629f 100644 --- a/assets/scripts/app/controllers/flash.coffee +++ b/assets/scripts/app/controllers/flash.coffee @@ -6,13 +6,13 @@ Travis.FlashController = Ember.ArrayController.extend @_super.apply this, arguments @set('flashes', Travis.LimitedArray.create(limit: 2, content: [])) - model: (-> + content: (-> broadcasts = @get('unseenBroadcasts') flashes = @get('flashes') - model = [] - model = model.concat(broadcasts.toArray()) if broadcasts - model = model.concat(flashes.toArray().reverse()) if flashes - model.uniq() + content = [] + content = content.concat(broadcasts.toArray()) if broadcasts + content = content.concat(flashes.toArray().reverse()) if flashes + content.uniq() ).property('unseenBroadcasts.length', 'flashes.length') unseenBroadcasts: (-> diff --git a/assets/scripts/app/controllers/repo.coffee b/assets/scripts/app/controllers/repo.coffee index 18468063..4144b681 100644 --- a/assets/scripts/app/controllers/repo.coffee +++ b/assets/scripts/app/controllers/repo.coffee @@ -10,8 +10,7 @@ Travis.RepoController = Travis.Controller.extend init: -> @_super.apply this, arguments - if !Ember.testing - Visibility.every Travis.INTERVALS.updateTimes, @updateTimes.bind(this) + Visibility.every Travis.INTERVALS.updateTimes, @updateTimes.bind(this) updateTimes: -> Ember.run this, -> diff --git a/assets/scripts/app/helpers/handlebars.coffee b/assets/scripts/app/helpers/handlebars.coffee index c10bf131..bc555d96 100644 --- a/assets/scripts/app/helpers/handlebars.coffee +++ b/assets/scripts/app/helpers/handlebars.coffee @@ -1,3 +1,5 @@ +require 'ext/ember/bound_helper' + safe = (string) -> new Handlebars.SafeString(string) @@ -123,7 +125,7 @@ Ember.Handlebars.helper('travis-errors', (name, options) -> Handlebars.registerHelper 'tipsy', (text, tip) -> safe '' + text + '' -Ember.Handlebars.registerBoundHelper 'capitalize', (value, options) -> +Ember.registerBoundHelper 'capitalize', (value, options) -> if value? safe $.capitalize(value) else @@ -138,10 +140,10 @@ Ember.Handlebars.helper('githubCommitLink', (slug, commitSha) -> safe '' + sha + '' ) -Ember.Handlebars.registerBoundHelper 'formatTime', (value, options) -> +Ember.registerBoundHelper 'formatTime', (value, options) -> safe Travis.Helpers.timeAgoInWords(value) || '-' -Ember.Handlebars.registerBoundHelper 'formatDuration', (duration, options) -> +Ember.registerBoundHelper 'formatDuration', (duration, options) -> safe Travis.Helpers.timeInWords(duration) Ember.Handlebars.helper('formatCommit', (commit) -> @@ -151,16 +153,16 @@ Ember.Handlebars.helper('formatCommit', (commit) -> Ember.Handlebars.helper 'formatSha', (sha) -> safe Travis.Helpers.formatSha(sha) -Ember.Handlebars.registerBoundHelper 'pathFrom', (url, options) -> +Ember.registerBoundHelper 'pathFrom', (url, options) -> safe Travis.Helpers.pathFrom(url) Ember.Handlebars.helper 'formatMessage', (message, options) -> safe Travis.Helpers.formatMessage(message, options.hash) -Ember.Handlebars.registerBoundHelper 'formatConfig', (config, options) -> +Ember.registerBoundHelper 'formatConfig', (config, options) -> safe Travis.Helpers.formatConfig(config) -Ember.Handlebars.registerBoundHelper 'shortCompareShas', (url, options) -> +Ember.registerBoundHelper 'shortCompareShas', (url, options) -> path = Travis.Helpers.pathFrom(url) if path.indexOf('...') >= 0 shas = path.split('...') @@ -168,7 +170,7 @@ Ember.Handlebars.registerBoundHelper 'shortCompareShas', (url, options) -> else path -Ember.Handlebars.registerBoundHelper 'formatLog', (log, options) -> +Ember.registerBoundHelper 'formatLog', (log, options) -> parentView = @get 'parentView' repo = parentView.get(options.repo) item = parentView.get(options.item) diff --git a/assets/scripts/app/templates/builds/show.hbs b/assets/scripts/app/templates/builds/show.hbs index dc23f0ab..eadc1042 100644 --- a/assets/scripts/app/templates/builds/show.hbs +++ b/assets/scripts/app/templates/builds/show.hbs @@ -54,13 +54,13 @@ {{#unless build.isMatrix}} - {{view 'annotations' annotations=build.jobs.firstObject.annotations}} + {{view Travis.AnnotationsView annotationsBinding="build.jobs.firstObject.annotations"}} {{/unless}} {{#if build.isMatrix}} - {{view 'jobs' jobs=build.requiredJobs required="true"}} - {{view 'jobs' jobs=build.allowedFailureJobs}} + {{view Travis.JobsView jobsBinding="build.requiredJobs" required="true"}} + {{view Travis.JobsView jobsBinding="build.allowedFailureJobs"}} {{else}} - {{view 'log' job=build.jobs.firstObject}} + {{view Travis.LogView jobBinding="build.jobs.firstObject"}} {{/if}} {{/if}} diff --git a/assets/scripts/app/templates/jobs/list.hbs b/assets/scripts/app/templates/jobs/list.hbs index d576baee..046d2981 100644 --- a/assets/scripts/app/templates/jobs/list.hbs +++ b/assets/scripts/app/templates/jobs/list.hbs @@ -1,14 +1,15 @@ {{#if view.jobs.length}} -
{{#if job.id}}
diff --git a/assets/scripts/app/templates/jobs/log.hbs b/assets/scripts/app/templates/jobs/log.hbs
index 0c74f7b8..1c1ffb84 100644
--- a/assets/scripts/app/templates/jobs/log.hbs
+++ b/assets/scripts/app/templates/jobs/log.hbs
@@ -1,5 +1,5 @@
{{#if view.log.isLoaded}}
- {{view 'pre' job=view.job log=view.log}}
+ {{view Travis.PreView jobBinding="view.job" logBinding="view.log"}}
{{else}}
Loading
diff --git a/assets/scripts/app/templates/jobs/show.hbs b/assets/scripts/app/templates/jobs/show.hbs
index e47a5653..2158964d 100644
--- a/assets/scripts/app/templates/jobs/show.hbs
+++ b/assets/scripts/app/templates/jobs/show.hbs
@@ -52,9 +52,9 @@
- {{view 'annotations' annotations=view.annotations}}
+ {{view Travis.AnnotationsView annotationsBinding="view.annotations"}}
- {{view 'log' job=job}}
+ {{view Travis.LogView jobBinding="job"}}
{{else}}
diff --git a/assets/scripts/app/templates/repos/list.hbs b/assets/scripts/app/templates/repos/list.hbs
index 961db9b6..17ea50f4 100644
--- a/assets/scripts/app/templates/repos/list.hbs
+++ b/assets/scripts/app/templates/repos/list.hbs
@@ -1,12 +1,12 @@
- {{input value=controller.search placeholder="Search all repositories"}}
+ {{view Ember.TextField valueBinding="controller.search" placeholder="Search all repositories"}}
-{{view 'repos-list-tabs'}}
+{{view Travis.ReposListTabsView}}
{{#if isLoaded}}
- {{#collection 'repos-list' content=this}}
+ {{#collection Travis.ReposListView contentBinding="this"}}
{{#with view.repo}}
diff --git a/assets/scripts/app/templates/repos/show.hbs b/assets/scripts/app/templates/repos/show.hbs
index 25905896..01dbc972 100644
--- a/assets/scripts/app/templates/repos/show.hbs
+++ b/assets/scripts/app/templates/repos/show.hbs
@@ -7,13 +7,13 @@
{{#link-to "repo" this}}{{slug}}{{/link-to}}- {{view 'repo-show-tools'}} + {{view Travis.RepoShowToolsView}}{{description}} - {{view 'repo-show-tabs'}} - {{view 'repo-actions'}} + {{view Travis.RepoShowTabsView}} + {{view Travis.RepoActionsView}} {{/with}}
diff --git a/assets/scripts/app/templates/repos/show/tabs.hbs b/assets/scripts/app/templates/repos/show/tabs.hbs
index 8b8174b8..793bd65c 100644
--- a/assets/scripts/app/templates/repos/show/tabs.hbs
+++ b/assets/scripts/app/templates/repos/show/tabs.hbs
@@ -2,7 +2,7 @@
- ```
-
- `unbound` can also be used in conjunction with a bound helper to
- render it in its unbound form:
-
- ```handlebars
- {{#if repo.slug}} - {{#link-to "repo" repo current-when="repo.index"}} + {{#link-to "repo" repo currentWhen="repo.index"}} Current {{/link-to}} {{/if}} @@ -75,7 +75,7 @@ {{/if}}{{#if repo.slug}} diff --git a/assets/scripts/app/templates/repos/show/tools.hbs b/assets/scripts/app/templates/repos/show/tools.hbs index b6de3888..ed110ae6 100644 --- a/assets/scripts/app/templates/repos/show/tools.hbs +++ b/assets/scripts/app/templates/repos/show/tools.hbs @@ -19,7 +19,7 @@Integrating Code Climate's test coverage reporting with your test suite on Travis CI allows to track changes in coverage over time. If you haven't tried it out already, sign + {{bind-attr href="Travis.config.code_climate_url"}}" target="_blank">sign up today to improve your code's quality. New customers get 20% off for the first three months! diff --git a/assets/scripts/app/templates/settings.hbs b/assets/scripts/app/templates/settings.hbs index ec0f6259..9c9458e4 100644 --- a/assets/scripts/app/templates/settings.hbs +++ b/assets/scripts/app/templates/settings.hbs @@ -1,7 +1,7 @@ diff --git a/assets/scripts/app/views/application.coffee b/assets/scripts/app/views/application.coffee index aa07c99e..45d414e0 100644 --- a/assets/scripts/app/views/application.coffee +++ b/assets/scripts/app/views/application.coffee @@ -1,6 +1,6 @@ Travis.reopen ApplicationView: Travis.View.extend - templateName: Ember.computed.alias('controller.templateName') + templateName: (-> @get 'controller.templateName' ).property('controller.templateName') classNames: ['application'] templateNameDidChange: (-> diff --git a/assets/scripts/app/views/job.coffee b/assets/scripts/app/views/job.coffee index 40d89b14..44cb5862 100644 --- a/assets/scripts/app/views/job.coffee +++ b/assets/scripts/app/views/job.coffee @@ -3,13 +3,6 @@ Travis.reopen templateName: 'jobs/list' buildBinding: 'controller.build' - jobTableId: Ember.computed(-> - if @get('required') - 'jobs' - else - 'allowed_failure_jobs' - ) - JobsItemView: Travis.View.extend tagName: 'tr' classNameBindings: ['color'] diff --git a/assets/scripts/app/views/log.coffee b/assets/scripts/app/views/log.coffee index 6a6ed987..2f92104c 100644 --- a/assets/scripts/app/views/log.coffee +++ b/assets/scripts/app/views/log.coffee @@ -37,12 +37,12 @@ Travis.reopen @lineSelector?.willDestroy() versionDidChange: (-> - @rerender() if @get('_state') == 'inDOM' + @rerender() if @get('state') == 'inDOM' ).observes('log.version') logDidChange: (-> console.log 'log view: log did change: rerender' if Log.DEBUG - @rerender() if @get('_state') == 'inDOM' + @rerender() if @get('state') == 'inDOM' ).observes('log') createEngine: -> diff --git a/assets/scripts/app/views/repo/show.coffee b/assets/scripts/app/views/repo/show.coffee index 63a348d7..4bd5cc7c 100644 --- a/assets/scripts/app/views/repo/show.coffee +++ b/assets/scripts/app/views/repo/show.coffee @@ -17,9 +17,9 @@ Travis.reopen # TODO: look into fixing it in more general way Ember.run.schedule('afterRender', this, -> pane = Ember.get('_outlets.pane') - if @get('controller.repo.isLoaded') && @_state == 'inDOM' && + if @get('controller.repo.isLoaded') && @state == 'inDOM' && @get('controller.repo.lastBuild') && - @get('controller.tab') == 'current' && (!pane || pane._state == 'destroyed') + @get('controller.tab') == 'current' && (!pane || pane.state == 'destroyed') view = @get('controller.container').lookup('view:build') view.set('controller', @get('controller.container').lookup('controller:build')) Ember.run.next => diff --git a/assets/scripts/lib/ext/ember/bound_helper.js b/assets/scripts/lib/ext/ember/bound_helper.js new file mode 100644 index 00000000..6b6fe699 --- /dev/null +++ b/assets/scripts/lib/ext/ember/bound_helper.js @@ -0,0 +1,68 @@ +// https://gist.github.com/2018185 +// For reference: https://github.com/wagenet/ember.js/blob/ac66dcb8a1cbe91d736074441f853e0da474ee6e/packages/ember-handlebars/lib/views/bound_property_view.js +var BoundHelperView = Ember.View.extend(Ember._Metamorph, { + + context: null, + options: null, + property: null, + // paths of the property that are also observed + propertyPaths: [], + + value: Ember.K, + + valueForRender: function() { + var value = this.value(Ember.get(this.context, this.property), this.options); + if (this.options.escaped) { value = Handlebars.Utils.escapeExpression(value); } + return value; + }, + + render: function(buffer) { + buffer.push(this.valueForRender()); + }, + + valueDidChange: function() { + if (this.morph.isRemoved()) { return; } + this.morph.html(this.valueForRender()); + }, + + didInsertElement: function() { + this.valueDidChange(); + }, + + init: function() { + this._super(); + Ember.addObserver(this.context, this.property, this, 'valueDidChange'); + this.get('propertyPaths').forEach(function(propName) { + Ember.addObserver(this.context, this.property + '.' + propName, this, 'valueDidChange'); + }, this); + }, + + destroy: function() { + Ember.removeObserver(this.context, this.property, this, 'valueDidChange'); + this.get('propertyPaths').forEach(function(propName) { + this.context.removeObserver(this.property + '.' + propName, this, 'valueDidChange'); + }, this); + this._super(); + } + +}); + +Ember.registerBoundHelper = function(name, func) { + var propertyPaths = Array.prototype.slice.call(arguments, 2); + Ember.Handlebars.registerHelper(name, function(property, options) { + var data = options.data, + view = data.view, + ctx = this; + + var bindView = view.createChildView(BoundHelperView, { + property: property, + propertyPaths: propertyPaths, + context: ctx, + options: options.hash, + value: func + }); + + view.appendChild(bindView); + }); +}; + diff --git a/assets/scripts/lib/travis/log_chunks.coffee b/assets/scripts/lib/travis/log_chunks.coffee index 9570ad4a..5ed7596a 100644 --- a/assets/scripts/lib/travis/log_chunks.coffee +++ b/assets/scripts/lib/travis/log_chunks.coffee @@ -76,7 +76,6 @@ Travis.LogChunks = Em.ArrayProxy.extend if part.final @notifyPropertyChange('final') - Ember.run this, -> - Ember.run.once this, -> - @tryFinalizing() - @resetTimeout() + Ember.run.once this, -> + @tryFinalizing() + @resetTimeout() diff --git a/assets/scripts/spec/integration/build_spec.coffee b/assets/scripts/spec/integration/build_spec.coffee index 8e9b4f88..9716d7f4 100644 --- a/assets/scripts/spec/integration/build_spec.coffee +++ b/assets/scripts/spec/integration/build_spec.coffee @@ -5,56 +5,53 @@ module "Build page", Ember.run -> Travis.reset() test "displaying information on build page", -> - visit('/travis-ci/travis-core/builds') - visit('/travis-ci/travis-core/builds/1') - andThen(-> - listsRepos [ - { slug: 'travis-ci/travis-hub', build: { number: 4, url: '/travis-ci/travis-hub/builds/4', duration: '1 min', finishedAt: '-' } } - { slug: 'travis-ci/travis-core', build: { number: 1, url: '/travis-ci/travis-core/builds/1', duration: '30 sec', finishedAt: '3 minutes ago' } } - { slug: 'travis-ci/travis-assets', build: { number: 3, url: '/travis-ci/travis-assets/builds/3', duration: '30 sec', finishedAt: 'a day ago' } } - ] - - displaysRepository - href: '/travis-ci/travis-core' - - displaysSummary - type: 'build' - id: 1 - repo: 'travis-ci/travis-core' - commit: '1234567' - branch: 'master' - compare: '0123456..1234567' - finishedAt: '3 minutes ago' - duration: '30 sec' - message: 'commit message 1' - - displaysSummaryGravatars - authorEmail: 'author@email.com' - committerEmail: 'committer@email.com' - - - displaysTabs - current: { href: '/travis-ci/travis-core' } - builds: { href: '/travis-ci/travis-core/builds' } - build: { href: '/travis-ci/travis-core/builds/1', active: true } - job: { hidden: true } - - listsJobs - table: '#jobs' - headers: ['Job', 'Duration', 'Finished', 'Ruby'] - jobs: [ - { color: 'green', id: 1, number: '1.1', repo: 'travis-ci/travis-core', finishedAt: '3 minutes ago', duration: '30 sec', rvm: 'rbx' } - { color: 'red', id: 2, number: '1.2', repo: 'travis-ci/travis-core', finishedAt: '2 minutes ago', duration: '40 sec', rvm: '1.9.3' } + visit('/travis-ci/travis-core/builds').then -> + visit('/travis-ci/travis-core/builds/1').then -> + listsRepos [ + { slug: 'travis-ci/travis-hub', build: { number: 4, url: '/travis-ci/travis-hub/builds/4', duration: '1 min', finishedAt: '-' } } + { slug: 'travis-ci/travis-core', build: { number: 1, url: '/travis-ci/travis-core/builds/1', duration: '30 sec', finishedAt: '3 minutes ago' } } + { slug: 'travis-ci/travis-assets', build: { number: 3, url: '/travis-ci/travis-assets/builds/3', duration: '30 sec', finishedAt: 'a day ago' } } ] - listsJobs - table: '#allowed_failure_jobs' - headers: ['Job', 'Duration', 'Finished', 'Ruby'] - jobs: [ - { color: '', id: 3, number: '1.3', repo: 'travis-ci/travis-core', finishedAt: '-', duration: '-', rvm: 'jruby' } - ] - ) + displaysRepository + href: '/travis-ci/travis-core' + displaysSummary + type: 'build' + id: 1 + repo: 'travis-ci/travis-core' + commit: '1234567' + branch: 'master' + compare: '0123456..1234567' + finishedAt: '3 minutes ago' + duration: '30 sec' + message: 'commit message 1' + + displaysSummaryGravatars + authorEmail: 'author@email.com' + committerEmail: 'committer@email.com' + + + displaysTabs + current: { href: '/travis-ci/travis-core' } + builds: { href: '/travis-ci/travis-core/builds' } + build: { href: '/travis-ci/travis-core/builds/1', active: true } + job: { hidden: true } + + listsJobs + table: '#jobs' + headers: ['Job', 'Duration', 'Finished', 'Ruby'] + jobs: [ + { color: 'green', id: 1, number: '1.1', repo: 'travis-ci/travis-core', finishedAt: '3 minutes ago', duration: '30 sec', rvm: 'rbx' } + { color: 'red', id: 2, number: '1.2', repo: 'travis-ci/travis-core', finishedAt: '2 minutes ago', duration: '40 sec', rvm: '1.9.3' } + ] + + listsJobs + table: '#allowed_failure_jobs' + headers: ['Job', 'Duration', 'Finished', 'Ruby'] + jobs: [ + { color: '', id: 3, number: '1.3', repo: 'travis-ci/travis-core', finishedAt: '-', duration: '-', rvm: 'jruby' } + ] test "updating current build", -> visit('/travis-ci/travis-core').then -> diff --git a/assets/scripts/spec/integration/routes_spec.coffee b/assets/scripts/spec/integration/routes_spec.coffee index 1992cfab..1cfe3fe8 100644 --- a/assets/scripts/spec/integration/routes_spec.coffee +++ b/assets/scripts/spec/integration/routes_spec.coffee @@ -1,4 +1,6 @@ module "Router", + setup: -> + Ember.run -> Travis.advanceReadiness() teardown: -> Ember.run -> Travis.reset() diff --git a/assets/scripts/spec/support/expectations.coffee b/assets/scripts/spec/support/expectations.coffee index d0a74bf7..8d9c5531 100644 --- a/assets/scripts/spec/support/expectations.coffee +++ b/assets/scripts/spec/support/expectations.coffee @@ -105,7 +105,7 @@ element = $("td.finished_at", row) equal(element.text().trim(), job.finishedAt) - element = $("td:nth-child(4)", row) + element = $("td:nth-child(6)", row) equal(element.text().trim(), job.rvm) @listsQueuedJobs = (jobs) -> diff --git a/assets/scripts/spec/unit/log_chunks_spec.coffee b/assets/scripts/spec/unit/log_chunks_spec.coffee index 724ace17..d08bedd0 100644 --- a/assets/scripts/spec/unit/log_chunks_spec.coffee +++ b/assets/scripts/spec/unit/log_chunks_spec.coffee @@ -40,7 +40,7 @@ test "it triggers downloading missing parts if there is a missing part, even tho , 40 test "it triggers downloading next parts if there is no final part", -> - expect(4) + expect(2) stop() callback = (missingNumbers, after) -> @@ -58,7 +58,7 @@ test "it triggers downloading next parts if there is no final part", -> , 35 test "it triggers downloading all available parts if there is no parts yet", -> - expect(2) + expect(1) stop() callback = (missingNumbers, after) -> diff --git a/assets/scripts/travis.coffee b/assets/scripts/travis.coffee index 412db1bf..08835a6c 100644 --- a/assets/scripts/travis.coffee +++ b/assets/scripts/travis.coffee @@ -154,15 +154,6 @@ Travis.initializer s = document.getElementsByTagName('script')[0] s.parentNode.insertBefore(ga, s) -Travis.initializer - name: 'inject-config' - - initialize: (container, application) -> - application.register 'config:main', Travis.config, { instantiate: false } - - application.inject('controller', 'config', 'config:main') - - Travis.Router.reopen didTransition: -> @_super.apply @, arguments diff --git a/assets/scripts/vendor/ember.js b/assets/scripts/vendor/ember.js index 54e8739e..647ee015 100644 --- a/assets/scripts/vendor/ember.js +++ b/assets/scripts/vendor/ember.js @@ -5,24 +5,25 @@ * 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 + * @version 1.6.1 */ + (function() { -var enifed, requireModule, eriuqer, requirejs, Ember; +var define, requireModule, require, requirejs, Ember; (function() { Ember = this.Ember = this.Ember || {}; - if (typeof Ember === 'undefined') { Ember = {}; }; + if (typeof Ember === 'undefined') { Ember = {} }; if (typeof Ember.__loader === 'undefined') { var registry = {}, seen = {}; - enifed = function(name, deps, callback) { + define = function(name, deps, callback) { registry[name] = { deps: deps, callback: callback }; }; - requirejs = eriuqer = requireModule = function(name) { + requirejs = require = requireModule = function(name) { if (seen.hasOwnProperty(name)) { return seen[name]; } seen[name] = {}; @@ -30,11 +31,11 @@ var enifed, requireModule, eriuqer, requirejs, Ember; throw new Error("Could not find module " + name); } - var mod = registry[name]; - var deps = mod.deps; - var callback = mod.callback; - var reified = []; - var exports; + var mod = registry[name], + deps = mod.deps, + callback = mod.callback, + reified = [], + exports; for (var i=0, l=deps.length; i
{{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
-
-
- ```
-
- ### 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
-
- my parent: ember1
-
-
-
- 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
-
-
- ```
-
- ### 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('
- hi
-
- {{yield}} '),
- template: Ember.Handlebars.compile('I am wrapped')
- });
-
- aView = AView.create();
- aView.appendTo('body');
- ```
-
- Will result in the following HTML output:
-
- ```html
-
-
-
-
- ```
-
- 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('
- I am wrapped
-
- 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
- click me
-
- ```
-
- And application code
-
- ```javascript
- App.ApplicationController = Ember.Controller.extend({
- actions: {
- anActionName: function() {
- }
- }
- });
- ```
-
- Will result in the following rendered HTML
-
- ```html
-
-
- ```
-
- 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
-
- click me
-
-
-
-
-
- ```
-
- 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
- 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
-
- ```
-
- You could render it inside the `post` template using the `render` helper.
-
- ```handlebars
-
-
- ```
-
- @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:
- // {{title}}-{{body}}
- {{render "author" author}}
- 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:
- //
- ```
- @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:
- // FooChild view:
-
- var FooView = Ember.View.extend({
- template: Ember.Handlebars.compile('Foo') - }); - var fooView = FooView.create(); - myView.connectOutlet('main', fooView); - // myView's html: - //Child view:
- //
-
- myView.disconnectOutlet('main');
- // myView's html:
- // FooChild 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
+ @method all
+ @for RSVP
+ @param {Array} array Array of promises.
+ @param {String} label An optional label. This is useful
+ for tooling.
@static
*/
- __exports__["default"] = {
- /**
- This is deprecated in favor of using the container to lookup the location
- implementation as desired.
+ __exports__["default"] = function all(array, label) {
+ return Promise.all(array, label);
+ };
+ });
+define("rsvp/all_settled",
+ ["./promise","./utils","exports"],
+ function(__dependency1__, __dependency2__, __exports__) {
+ "use strict";
+ var Promise = __dependency1__["default"];
+ var isArray = __dependency2__.isArray;
+ var isNonThenable = __dependency2__.isNonThenable;
- For example:
+ /**
+ `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.
- ```javascript
- // Given a location registered as follows:
- container.register('location:history-test', HistoryTestLocation);
+ 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.
- // You could create a new instance via:
- container.lookup('location:history-test');
- ```
+ 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:
- @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);
+ ```javascript
+ { state: 'fulfilled', value: value }
+ or
+ { state: 'rejected', reason: reason }
+ ```
- var implementationClass = this.implementations[implementation];
- Ember.assert("Ember.Location.create: " + implementation + " is not a valid implementation", !!implementationClass);
+ Example:
- return implementationClass.create.apply(implementationClass, arguments);
- },
+ ```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 ];
- /**
- This is deprecated in favor of using the container to register the
- location implementation as desired.
+ 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.)
+ });
+ ```
- Example:
+ @method allSettled
+ @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.
+ @static
+ */
- ```javascript
- Application.initializer({
- name: "history-test-location",
-
- initialize: function(container, application) {
- application.register('location:history-test', HistoryTestLocation);
+ __exports__["default"] = function allSettled(entries, label) {
+ return new Promise(function(resolve, reject) {
+ if (!isArray(entries)) {
+ throw new TypeError('You must pass an array to allSettled.');
}
+
+ var remaining = entries.length;
+ var entry;
+
+ if (remaining === 0) {
+ resolve([]);
+ return;
+ }
+
+ var results = new Array(remaining);
+
+ function fulfilledResolver(index) {
+ return function(value) {
+ resolveAll(index, fulfilled(value));
+ };
+ }
+
+ function rejectedResolver(index) {
+ return function(reason) {
+ resolveAll(index, rejected(reason));
+ };
+ }
+
+ function resolveAll(index, value) {
+ results[index] = value;
+ if (--remaining === 0) {
+ resolve(results);
+ }
+ }
+
+ for (var index = 0; index < entries.length; index++) {
+ entry = entries[index];
+
+ if (isNonThenable(entry)) {
+ resolveAll(index, fulfilled(entry));
+ } else {
+ Promise.cast(entry).then(fulfilledResolver(index), rejectedResolver(index));
+ }
+ }
+ }, label);
+ };
+
+ function fulfilled(value) {
+ return { state: 'fulfilled', value: value };
+ }
+
+ function rejected(reason) {
+ return { state: 'rejected', reason: reason };
+ }
+ });
+define("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;
+ });
+define("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!");
+
+ deferred.promise.then(function(value){
+ // value here is "Success!"
});
```
- @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);
+ @method defer
+ @for RSVP
+ @param {String} label optional string for labeling the promise.
+ Useful for tooling.
+ @return {Object}
+ */
- this.implementations[name] = implementation;
- },
+ __exports__["default"] = function defer(label) {
+ var deferred = { };
- implementations: {},
- _location: window.location,
+ deferred.promise = new Promise(function(resolve, reject) {
+ deferred.resolve = resolve;
+ deferred.reject = reject;
+ }, label);
- /**
- 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);
- }
- }
+ return deferred;
};
});
-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__) {
+define("rsvp/events",
+ ["exports"],
+ function(__exports__) {
"use strict";
- var Ember = __dependency1__["default"];
- // FEATURES
- var get = __dependency2__.get;
- var set = __dependency3__.set;
+ var indexOf = function(callbacks, callback) {
+ for (var i=0, l=callbacks.length; i
- {{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 }); - } + if (!callback) { + allCallbacks[eventName] = []; return; } - options = normalizeOptions(this, name, template, options); - view = setupView(view, container, options); + callbacks = allCallbacks[eventName]; - if (options.outlet === 'main') { this.lastRenderedTemplate = name; } + index = indexOf(callbacks, callback); - appendView(this, view, options); + if (index !== -1) { callbacks.splice(index, 1); } }, /** - Disconnects a view that has been rendered into an outlet. + Use `trigger` to fire custom events. For example: - 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' - }); - } - } + ```javascript + object.on('foo', function(){ + console.log('foo event happened!'); }); + object.trigger('foo'); + // 'foo event happened!' logged to the console ``` - Alternatively, you can pass the `outlet` name directly as a string. + You can also pass a value as a second argument to `trigger` that will be + passed as an argument to all event listeners for the event: - Example: + ```javascript + object.on('foo', function(value){ + console.log(value.name); + }); - ```js - hideModal: function(evt) { - this.disconnectOutlet('modal'); - } + object.trigger('foo', { name: 'bar' }); + // 'bar' logged to the console ``` - @method disconnectOutlet - @param {Object|String} options the options hash or outlet name + @method trigger + @param {String} eventName name of the event to be triggered + @param {Any} options optional value to be passed to any event handlers for + the given `eventName` + @private */ - disconnectOutlet: function(options) { - if (!options || typeof options === "string") { - var outletName = options; - options = {}; - options.outlet = outletName; + trigger: function(eventName, options) { + var allCallbacks = callbacksFor(this), + callbacks, callbackTuple, callback, binding; + + if (callbacks = allCallbacks[eventName]) { + // Don't cache the callbacks.length since it may grow + for (var i=0; i |