forked from hurrymaplelad/rendr-handlebars
-
Notifications
You must be signed in to change notification settings - Fork 31
Expand file tree
/
Copy pathhelpers.js
More file actions
128 lines (106 loc) · 3.67 KB
/
helpers.js
File metadata and controls
128 lines (106 loc) · 3.67 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
var _ = require('underscore');
// Lazy-required.
var BaseView = null;
module.exports = function(Handlebars, getTemplate) {
var oldEach = Handlebars.helpers.each;
return {
view: function(viewName, options) {
var ViewClass, html, viewOptions, view;
// it's lazy loaded, not a compile time dependency
// hiding it from r.js compiler
var lazyRequire_baseView = 'rendr/shared/base/view';
BaseView = BaseView || require(lazyRequire_baseView);
viewOptions = options.hash || {};
// Pass through a reference to the app.
var app = getProperty('_app', this, options);
if (app) {
viewOptions.app = app;
viewName = app.modelUtils.underscorize(viewName);
} else{
throw new Error("An App instance is required when rendering a view, it could not be extracted from the options.")
}
// Pass through a reference to the parent view.
var parentView = getProperty('_view', this, options);
if (parentView) {
viewOptions.parentView = parentView;
}
// get the Backbone.View based on viewName
ViewClass = BaseView.getView(viewName, app.options.entryPath);
view = new ViewClass(viewOptions);
// create the outerHTML using className, tagName
html = view.getHtml();
return new Handlebars.SafeString(html);
},
partial: function(templateName, options) {
var data, html, context, template;
template = getTemplate(templateName);
context = options.hash || {};
// First try to use Handlebars' hash arguments as the context for the
// partial, if present.
//
// ex: `{{partial "users/photo" user=user}}`
if (_.isEmpty(context)) {
// If there are no hash arguments given, then inherit the parent context.
//
// ex: `{{partial "users/photo"}}`
context = this;
} else {
// If a hash argument is given with key `context`, then use that as the context.
//
// ex: `{{partial "users/photo" context=user}}`
if (context.hasOwnProperty('context')) {
context = context.context;
}
}
context = _.clone(context);
context._app = getProperty('_app', this, options);
html = template(context);
return new Handlebars.SafeString(html);
},
json: function(object, spacing) {
return new Handlebars.SafeString(
JSON.stringify(object, null, spacing).replace(/\//g, '\\/') || 'null'
);
},
/**
* Extend `each` to pass through important context.
*/
each: function(context, options) {
options.data = Handlebars.createFrame(options.data || {});
// Make sure `this._app`, `this._view`, etc are available.
_.extend(options.data, getOptionsFromContext(this));
// Call the original helper with new context.
return oldEach.call(this, context, options);
}
};
};
/**
* Grab important underscored properties from the current context.
* These properties come from BaseView::decorateTemplateData().
*/
function getOptionsFromContext(obj) {
var options, keys, value;
keys = [
'_app',
'_view',
'_model',
'_collection'
];
options = keys.reduce(function(memo, key) {
value = obj[key];
if (value) {
memo[key] = value;
}
return memo;
}, {});
return options;
}
/**
* Get a property that is being passed down through helpers, such as `_app`
* or `_view`. It can either live on the context, i.e. `this._app`, or in the
* `options.data` object passed to the helper, i.e. `options.data._app`, in the
* case of a block helper like `each`.
*/
function getProperty(key, context, options) {
return context[key] || (options.data || {})[key];
}