-
Notifications
You must be signed in to change notification settings - Fork 0
/
botox.js
192 lines (160 loc) · 5.74 KB
/
botox.js
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
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
/*
* Botox.js v0.0.1 - Application Mediator/Sandbox Library
* This module performs the function of mediator/sandbox.
*
* @author Erik Toth <ertoth@paypal.com>
*/
/*global define:false, requirejs:true */
/*jslint plusplus:true, nomen:true */
define(['jquery', 'dust', 'dust-helpers-supplement'], function ($) {
'use strict';
var ViewRenderer = null,
DustRenderer = null,
Botox = null;
/**
* Executes a provided function once per array element or object property.
* Based on http://es5.github.com/#x15.4.4.18
* @param {Object} obj the array or object to enumerate
* @param {Function} fn the function to invoke on each element
* @param {Object} [context] Object to use as this when executing callback.
*/
function forEach(obj, fn, context) {
if (obj instanceof Array && Array.prototype.forEach) {
return obj.forEach(fn, context);
}
var object = Object(obj),
prop = null,
result = null;
for (prop in object) {
if (object.hasOwnProperty(prop)) {
result = fn.call(context, object[prop], prop, object);
// Provide the ability to short circuit and fail-fast
if (result === false) {
break;
}
}
}
}
/**
* A basic object mixin implementation. Copies the properties from the source
* object to the destination object.
* @param {Object} src the object containing the properties to be copied
* @param {Object} dest the object to which the properties should be copied
*/
function mixin(src, dest) {
var prop = null;
for (prop in src) {
if (src.hasOwnProperty(prop)) {
dest[prop] = src[prop];
}
}
return dest;
}
/**
* A simple object extend implementation that copies properties from several
* source objects into the destination object.
* @param {Object} dest the object to which the properties should be copied
* @param {Object...} sources the objects from which the properties should be copied
*/
function extend(dest) {
forEach(Array.prototype.slice.call(arguments, 1), function (src) {
mixin(src, dest);
});
return dest;
}
/**
* An abstract view renderer implementation that"s based on Promises
* @constructor
*/
ViewRenderer = function () {
// Intentionally left blank
};
ViewRenderer.prototype = {
/**
* The main public API for rendering a template
* @param template the name of the template to render
* @param context the context to pass to the renderer
* @returns a Promise
*/
render: function (template, context) {
var deferred = new $.Deferred();
this._doRender(template, context, function (err, out) {
if (err) { return deferred.reject(err); }
deferred.resolve(out, template);
});
return deferred.promise();
},
/**
* The method to override to provide the view rendering implementation
* @private
* @param template the name of the template to render
* @param context the content to pass to the renderer
* @param callback the callback invoked when rendering is complete
*/
_doRender: function (template, context, callback) {
// TODO: Implement
}
};
/**
* A Dust view rendering implementation
* @constructor
*/
DustRenderer = function (botox) {
var DEFAULT_PATH = '/templates/%s.js';
dust.onLoad = function (name, callback) {
var path = botox.getContext().templatePath || DEFAULT_PATH,
specialization = botox.getContext().specialization,
resolvedName = (specialization && specialization[name]) || name,
template = path.replace('%s', resolvedName);
require([template], function () {
// Merely using requireJs to the load compiled template so undefining
// it as soon as it's loaded so doesn't sit in the requireJs *and* dust.js
// caches. Also, we know it's JS, thus doesn't need to be compiled so
// callback has no arguments.
requirejs.undef(template);
//also fill this into the dust cache in case we resolved the template name to
//something else for specialization
if(name != resolvedName) {
dust.cache[name] = dust.cache[resolvedName];
delete dust.cache[resolvedName];
}
setTimeout(callback, 0);
});
};
};
DustRenderer.prototype = extend(ViewRenderer.prototype, {
_doRender: function (template, context, callback) {
var base = {};
context = context || {};
// Ugh.
if (context.content) {
base.cn = context.content;
delete context.content;
}
context = dust.makeBase(base).push(context);
dust.render(template, context, callback);
}
});
Botox = function () {
this._context = {};
this.viewRenderer = new DustRenderer(this);
};
Botox.prototype = {
/**
*
* @param context
* @returns
*/
setContext : function (context) {
return mixin(context, this._context);
},
/**
*
* @returns the current context object
*/
getContext : function () {
return this._context;
}
};
return new Botox();
});