From eb040cdff50554117851145b800aaaa969cb237b Mon Sep 17 00:00:00 2001 From: David Greenspan Date: Mon, 17 Jun 2013 11:03:27 -0700 Subject: [PATCH] implement Spacebars.{index,call} --- packages/spacebars/spacebars.js | 48 +++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/packages/spacebars/spacebars.js b/packages/spacebars/spacebars.js index d863a97585..807973e357 100644 --- a/packages/spacebars/spacebars.js +++ b/packages/spacebars/spacebars.js @@ -793,4 +793,52 @@ Spacebars.compile = function (inputString) { }; return tokensToRenderFunc(tree.bodyTokens); +}; + +Spacebars.index = function (value/*, identifiers*/) { + var identifiers = Array.prototype.slice.call(arguments, 1); + + // The object we got `curValue` from by indexing. + // For the value itself, we don't know the appropriate value + // of `this`, so we assume it is already bound. + var nextThis = null; + + _.each(identifiers, function (id) { + if (typeof value === 'function' && + ! UI.isComponentClass(value)) { + // Call a getter -- in `{{foo.bar}}`, call `foo()` if it + // is a function before indexing it with `bar`. + // + // In `{{foo blah=FooComponent.Bar}}`, treat + // `FooComponent` as a non-function. + value = value.call(nextThis); + } + nextThis = value; + if (value) + value = value[id]; + }); + + if (typeof value === 'function' && + ! UI.isComponentClass(value)) { + // bind `this` for resulting function, so it can be + // called with `Spacebars.call`. + value = _.bind(value, nextThis); + } + + return value; +}; + +Spacebars.call = function (value/*, args*/) { + if (typeof value !== 'function' || + UI.isComponentClass(value)) + return value; // ignore args + + var args = Array.prototype.slice.call(arguments, 1); + + // There is a correct value of `this` for any given + // call, but we don't know it here. It must be + // bound to the function in advance (so that `value` + // is actually a wrapper which ignores its `this` + // and supplies one). + return value.apply(null, args); }; \ No newline at end of file