Skip to content
This repository has been archived by the owner on Oct 30, 2018. It is now read-only.

[bz5800733] Handlebars Template Helpers (second attempt after #922) #1011

Merged
merged 5 commits into from
Feb 26, 2013
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
92 changes: 92 additions & 0 deletions lib/app/addons/ac/helpers.common.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
/*
* Copyright (c) 2011-2013, Yahoo! Inc. All rights reserved.
* Copyrights licensed under the New BSD License.
* See the accompanying LICENSE file for terms.
*/

/*jslint nomen:true*/
/*global YUI*/

/**
* @module ActionContextAddon
*/
YUI.add('mojito-helpers-addon', function (Y, NAME) {

'use strict';

/**
* <strong>Access point:</strong> <em>ac.helpers.*</em>
* Addon that provides helpers functionalities
* @class Helpers.common
*/
function Addon(command, adapter) {
this._page = adapter.page;
// exposing instance helpers for render engine can use it,
// also, mixing in any previously exposed helper.
this._helpers = command.instance.helpers = Y.merge({},
(this._page.helpers || {}));
}

Addon.prototype = {

namespace: 'helpers',

/**
* Gets one specific helper if the name is specified,
* otherwise returns all available helpers.
* @method get
* @param {string} helperName The optional helper name
* @return {function|object} a helper function or all available helpers
*/
get: function (helperName) {
return helperName ? this._helpers[helperName] : this._helpers;
},

/**
* set a helper function at the mojit instance.
* @method set
* @param {string} helperName The helper name.
* @param {function} helper The helper function.
*/
set: function (helperName, helper) {
if (!helperName || !helper) {
Y.log('Invalid helper name or helper function ' +
'when calling `ac.helpers.set()`: ' + helperName, 'error', NAME);
return;
}
if (this._helpers[helperName]) {
Y.log('Overiding an existing helper function with name: ' +
helperName, 'warn', NAME);
}
this._helpers[helperName] = helper;
},

/**
* Expose a helper function as global. On the server side
* this means any mojit instance under a particular request
* can use the helper. On the client, any
* mojit instance on the page can use the helper.
* @method expose
* @param {string} helperName The helper name.
* @param {function} helper Optional helper function, if not
* present, the helper will be lookup by name.
*/
expose: function (helperName, helper) {
this._page.helpers = this._page.helpers || {};
// you might want to expose an existing local helper
helper = helper || this._helpers[helperName];
// exposing thru global page object
this._page.helpers[helperName] = helper;
// exposing at the instance level
this._helpers[helperName] = helper;
Y.log('Exposing a global helper: ' + helperName, 'info', NAME);
}

};

Y.namespace('mojito.addons.ac').helpers = Addon;

}, '0.1.0', {requires: [
'mojito',
'mojito-util'
]});
79 changes: 40 additions & 39 deletions lib/app/addons/ac/models.common.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,26 +14,14 @@ YUI.add('mojito-models-addon', function (Y, NAME) {

'use strict';

// global model cache when on the client to store
// models at the page level, while running on the
// server we store them on adapter.req object per
// request.
var _clientCache = {};

// TODO:
// - update tests
// - update fixtures
// - update documentation
// - update examples

/**
* <strong>Access point:</strong> <em>ac.models.get()</em>
* <strong>Access point:</strong> <em>ac.models.*</em>
* Addon that provides access to the models collection
* @class Models.common
*/
function Addon(command, adapter) {
this._models = {};
this._adapter = adapter;
this._page = adapter.page;
this._instance = command.instance;
}

Expand All @@ -49,9 +37,8 @@ YUI.add('mojito-models-addon', function (Y, NAME) {
*/
get: function (modelName) {

var model = this._models[modelName] || _clientCache[modelName] ||
(this._adapter.req && this._adapter.req.models &&
this._adapter.req.models[modelName]);
var cache = this._page.models || {},
model = this._models[modelName] || cache[modelName];

// instantanting the model once during the lifetime of
// the ac object, this acts like an internal cache.
Expand All @@ -76,33 +63,47 @@ YUI.add('mojito-models-addon', function (Y, NAME) {
},

/**
* Set a model instance as global. On the server side
* set a model instance at the mojit instance.
* @method set
* @param {string} modelName The model name.
* @param {object} model The model instance.
*/
set: function (modelName, model) {
if (!modelName || !model) {
Y.log('Invalid model name or model instance ' +
'when calling `ac.models.set()`: ' + modelName, 'error', NAME);
return;
}
if (this._models[modelName]) {
Y.log('Overiding an existing model instance with name: ' +
modelName, 'warn', NAME);
}
this._models[modelName] = model;
},

/**
* Expose a model instance as global. On the server side
* this means any mojit instance under a particular request
* will have access to the model. On the client, any
* mojit instance on the page will have access to
* the model as well.
* @method get
* @param {string} name The model name.
* @param {object} model The model instance
* @method expose
* @param {string} modelName The model name.
* @param {object} model Optional model instance, if not
* present, the instance will be lookup by modelName.
*/
registerGlobal: function (name, model) {
if (this._adapter.req) {
// server side routine to store on the request
// to avoid leaks.
// NOTE: models on req object will be destroyed
// with the request lifecycle.
this._adapter.req.models = this._adapter.req.models || {};
this._adapter.req.models[name] = model;
Y.log('Storing a global model on the server: ' + name, 'info', NAME);
} else {
// client side routine to store on a global
// cache structure.
// NOTE: there is no way to destroy this model at
// the moment, it is now tied to the page
// life cycle.
_clientCache[name] = model;
Y.log('Storing a global model on the client: ' + name, 'info', NAME);
}
expose: function (modelName, model) {
this._page.models = this._page.models || {};
// you might want to expose an existing local model
model = model || this.get(modelName);

// NOTE: models on the server will be destroyed
// with the request lifecycle.
// NOTE: for models on the client, there is no way
// to destroy them at the moment, it is tied
// to the page life cycle.
this._page.models[modelName] = model;
Y.log('Exposing a global model: ' + modelName, 'info', NAME);
}

};
Expand Down
13 changes: 11 additions & 2 deletions lib/app/addons/view-engines/hb.client.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,15 +41,24 @@ YUI.add('mojito-hb', function(Y, NAME) {
render: function (data, instance, template, adapter, meta, more) {
var cacheTemplates = (this.options.cacheTemplates === false ? false : true),
handler = function (err, obj) {
var output;
var output,
helpers = HB.helpers;

if (err) {
adapter.error(err);
return;
}

// making sure we preserve the original helpers
// from Y.Handlebars.helpers but letting the custom
// helpers per mojit instance to override any of them.
if (instance && instance.helpers) {
helpers = Y.merge(HB.helpers, instance.helpers);
}

output = obj.compiled(data, {
partials: obj.partials
partials: obj.partials,
helpers: helpers
});

if (more) {
Expand Down
13 changes: 11 additions & 2 deletions lib/app/addons/view-engines/hb.server.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,15 +43,24 @@ YUI.add('mojito-hb', function (Y, NAME) {
render: function (data, instance, template, adapter, meta, more) {
var cacheTemplates = (this.options.cacheTemplates === false ? false : true),
handler = function (err, obj) {
var output;
var output,
helpers = HB.helpers;

if (err) {
adapter.error(err);
return;
}

// making sure we preserve the original helpers
// from Y.Handlebars.helpers but letting the custom
// helpers per mojit instance to override any of them.
if (instance && instance.helpers) {
helpers = Y.merge(HB.helpers, instance.helpers);
}

output = obj.compiled(data, {
partials: obj.partials
partials: obj.partials,
helpers: helpers
});

// HookSystem::StartBlock
Expand Down
1 change: 1 addition & 0 deletions lib/app/autoload/mojito-client.client.js
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,7 @@ YUI.add('mojito-client', function(Y, NAME) {
* server to start up mojito.
*/
function MojitoClient(config) {
this.page = {};
this.timeLogStack = [];
this.yuiConsole = null;
this._pauseQueue = [];
Expand Down
1 change: 1 addition & 0 deletions lib/app/autoload/output-handler.client.js
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ YUI.add('mojito-output-handler', function(Y, NAME) {
this.callback = cb;
this.buffer = '';
this.mojitoClient = mojitoClient;
this.page = mojitoClient.page;
}


Expand Down
1 change: 1 addition & 0 deletions lib/output-handler.server.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ var NAME = 'OutputHandler.server',
this.res = res;
this.next = next;
this.headers = {};
this.page = {};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oooooooh, me like.

};


Expand Down
Loading