|
1 YUI.add('template-base', function (Y, NAME) { |
|
2 |
|
3 /** |
|
4 Virtual rollup of the `template-base` and `template-micro` modules. |
|
5 |
|
6 @module template |
|
7 @main template |
|
8 @since 3.8.0 |
|
9 **/ |
|
10 |
|
11 /** |
|
12 Provides a generic API for using template engines such as Handlebars and |
|
13 `Y.Template.Micro`. |
|
14 |
|
15 @module template |
|
16 @submodule template-base |
|
17 @since 3.8.0 |
|
18 **/ |
|
19 |
|
20 /** |
|
21 Provides a generic API for using template engines such as Handlebars and |
|
22 `Y.Template.Micro`. |
|
23 |
|
24 ### Examples |
|
25 |
|
26 Using with `Y.Template.Micro` (the default template engine): |
|
27 |
|
28 YUI().use('template', function (Y) { |
|
29 var micro = new Y.Template(), |
|
30 html = micro.render('<%= data.message %>', {message: 'hello!'}); |
|
31 |
|
32 // ... |
|
33 }); |
|
34 |
|
35 Using with Handlebars: |
|
36 |
|
37 YUI().use('template-base', 'handlebars', function (Y) { |
|
38 var handlebars = new Y.Template(Y.Handlebars), |
|
39 html = handlebars.render('{{message}}', {message: 'hello!'}); |
|
40 |
|
41 // ... |
|
42 }); |
|
43 |
|
44 @class Template |
|
45 @param {Mixed} [engine=Y.Template.Micro] Template engine to use, such as |
|
46 `Y.Template.Micro` or `Y.Handlebars`. Defaults to `Y.Template.Micro` if not |
|
47 specified. |
|
48 @param {Object} [defaults] Default options to use when instance methods are |
|
49 invoked. |
|
50 @constructor |
|
51 @since 3.8.0 |
|
52 **/ |
|
53 |
|
54 function Template(engine, defaults) { |
|
55 /** |
|
56 Default options. |
|
57 |
|
58 @property {Object} defaults |
|
59 @since 3.8.1 |
|
60 **/ |
|
61 this.defaults = defaults; |
|
62 |
|
63 /** |
|
64 Template engine class. |
|
65 |
|
66 @property {Mixed} engine |
|
67 @since 3.8.0 |
|
68 **/ |
|
69 this.engine = engine || Y.Template.Micro; |
|
70 |
|
71 if (!this.engine) { |
|
72 Y.error('No template engine loaded.'); |
|
73 } |
|
74 } |
|
75 |
|
76 /** |
|
77 Registry that maps template names to revived template functions. |
|
78 |
|
79 @property _registry |
|
80 @type Object |
|
81 @static |
|
82 @protected |
|
83 @since 3.12.0 |
|
84 **/ |
|
85 Template._registry = {}; |
|
86 |
|
87 /** |
|
88 Registers a pre-compiled template into the central template registry with a |
|
89 given template string, allowing that template to be called and rendered by |
|
90 that name using the `Y.Template.render()` static method. |
|
91 |
|
92 For example, given the following simple Handlebars template, in `foo.hbs`: |
|
93 @example |
|
94 <p>{{tagline}}</p> |
|
95 |
|
96 It can be precompiled using the Handlebars CLI, and added into a YUI module |
|
97 in the following way. Alternatively, `locator` can be used to automate this |
|
98 process for you: |
|
99 @example |
|
100 YUI.add('templates-foo', function (Y) { |
|
101 |
|
102 var engine = new Y.Template(Y.Handlebars), |
|
103 precompiled; |
|
104 |
|
105 precompiled = // Long precompiled template function here // |
|
106 |
|
107 Y.Template.register('foo', engine.revive(precompiled)); |
|
108 |
|
109 }, '0.0.1', {requires: ['template-base', 'handlebars-base']}); |
|
110 |
|
111 See the `Y.Template#render` method to see how a registered template is used. |
|
112 |
|
113 @method register |
|
114 @param {String} templateName The template name. |
|
115 @param {Function} template The function that returns the rendered string. The |
|
116 function should take the following parameters. If a pre-compiled template |
|
117 does not accept these parameters, it is up to the developer to normalize it. |
|
118 @param {Object} [template.data] Data object to provide when rendering the |
|
119 template. |
|
120 @param {Object} [template.options] Options to pass along to the template |
|
121 engine. See template engine docs for options supported by each engine. |
|
122 @return {Function} revivedTemplate This is the same function as in `template`, |
|
123 and is done to maintain compatibility with the `Y.Template#revive()` method. |
|
124 @static |
|
125 @since 3.12.0 |
|
126 **/ |
|
127 Template.register = function (templateName, template) { |
|
128 Template._registry[templateName] = template; |
|
129 return template; |
|
130 }; |
|
131 |
|
132 /** |
|
133 Returns the registered template function, given the template name. If an |
|
134 unregistered template is accessed, this will return `undefined`. |
|
135 |
|
136 @method get |
|
137 @param {String} templateName The template name. |
|
138 @return {Function} revivedTemplate The revived template function, or `undefined` |
|
139 if it has not been registered. |
|
140 @static |
|
141 @since 3.12.0 |
|
142 **/ |
|
143 |
|
144 Template.get = function (templateName) { |
|
145 return Template._registry[templateName]; |
|
146 } |
|
147 |
|
148 /** |
|
149 Renders a template into a string, given the registered template name and data |
|
150 to be interpolated. The template name must have been registered previously with |
|
151 `register()`. |
|
152 |
|
153 Once the template has been registered and built into a YUI module, it can be |
|
154 listed as a dependency for any other YUI module. Continuing from the above |
|
155 example, the registered template can be used in the following way: |
|
156 |
|
157 @example |
|
158 YUI.add('bar', function (Y) { |
|
159 |
|
160 var html = Y.Template.render('foo', { |
|
161 tagline: '"bar" is now template language agnostic' |
|
162 }); |
|
163 |
|
164 }, '0.0.1', {requires: ['template-base', 'templates-foo']}); |
|
165 |
|
166 The template can now be used without having to know which specific rendering |
|
167 engine generated it. |
|
168 |
|
169 @method render |
|
170 @param {String} templateName The abstracted name to reference the template. |
|
171 @param {Object} [data] The data to be interpolated into the template. |
|
172 @param {Object} [options] Any additional options to be passed into the template. |
|
173 @return {String} output The rendered result. |
|
174 @static |
|
175 @since 3.12.0 |
|
176 **/ |
|
177 Template.render = function (templateName, data, options) { |
|
178 var template = Template._registry[templateName], |
|
179 result = ''; |
|
180 |
|
181 if (template) { |
|
182 result = template(data, options); |
|
183 } else { |
|
184 Y.error('Unregistered template: "' + templateName + '"'); |
|
185 } |
|
186 |
|
187 return result; |
|
188 }; |
|
189 |
|
190 Template.prototype = { |
|
191 /** |
|
192 Compiles a template with the current template engine and returns a compiled |
|
193 template function. |
|
194 |
|
195 @method compile |
|
196 @param {String} text Template text to compile. |
|
197 @param {Object} [options] Options to pass along to the template engine. See |
|
198 template engine docs for options supported by each engine. |
|
199 @return {Function} Compiled template function. |
|
200 @since 3.8.0 |
|
201 **/ |
|
202 compile: function (text, options) { |
|
203 options = options ? Y.merge(this.defaults, options) : this.defaults; |
|
204 return this.engine.compile(text, options); |
|
205 }, |
|
206 |
|
207 /** |
|
208 Precompiles a template with the current template engine and returns a string |
|
209 containing JavaScript source code for the precompiled template. |
|
210 |
|
211 @method precompile |
|
212 @param {String} text Template text to compile. |
|
213 @param {Object} [options] Options to pass along to the template engine. See |
|
214 template engine docs for options supported by each engine. |
|
215 @return {String} Source code for the precompiled template. |
|
216 @since 3.8.0 |
|
217 **/ |
|
218 precompile: function (text, options) { |
|
219 options = options ? Y.merge(this.defaults, options) : this.defaults; |
|
220 return this.engine.precompile(text, options); |
|
221 }, |
|
222 |
|
223 /** |
|
224 Compiles and renders a template with the current template engine in a single |
|
225 step, and returns the rendered result. |
|
226 |
|
227 @method render |
|
228 @param {String} text Template text to render. |
|
229 @param {Object} data Data object to provide when rendering the template. |
|
230 @param {Object} [options] Options to pass along to the template engine. See |
|
231 template engine docs for options supported by each engine. |
|
232 @return {String} Rendered result. |
|
233 @since 3.8.0 |
|
234 **/ |
|
235 render: function (text, data, options) { |
|
236 options = options ? Y.merge(this.defaults, options) : this.defaults; |
|
237 |
|
238 if (this.engine.render) { |
|
239 return this.engine.render(text, data, options); |
|
240 } |
|
241 |
|
242 return this.engine.compile(text, options)(data, options); |
|
243 }, |
|
244 |
|
245 /** |
|
246 Revives a precompiled template function into an executable template function |
|
247 using the current template engine. The precompiled code must already have |
|
248 been evaluated; this method won't evaluate it for you. |
|
249 |
|
250 @method revive |
|
251 @param {Function} precompiled Precompiled template function. |
|
252 @param {Object} [options] Options to pass along to the template engine. See |
|
253 template engine docs for options supported by each engine. |
|
254 @return {Function} Compiled template function. |
|
255 @since 3.8.0 |
|
256 **/ |
|
257 revive: function (precompiled, options) { |
|
258 options = options ? Y.merge(this.defaults, options) : this.defaults; |
|
259 |
|
260 return this.engine.revive ? this.engine.revive(precompiled, options) : |
|
261 precompiled; |
|
262 } |
|
263 }; |
|
264 |
|
265 // Copy existing namespaced properties from Y.Template to the Template function |
|
266 // if Y.Template already exists, then make the function the new Y.Template. |
|
267 // This ensures that other modules can safely add stuff to the Y.Template |
|
268 // namespace even if they're loaded before this one. |
|
269 Y.Template = Y.Template ? Y.mix(Template, Y.Template) : Template; |
|
270 |
|
271 |
|
272 }, '@VERSION@', {"requires": ["yui-base"]}); |