eyeballs 0.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG +15 -0
- data/README.md +293 -0
- data/Rakefile +45 -0
- data/bin/eyeballs +9 -0
- data/config.ru +2 -0
- data/dist/jquery-1.4.2.min.js +154 -0
- data/dist/jquery.livequery.js +226 -0
- data/dist/mustache.js +324 -0
- data/eyeballs.gemspec +86 -0
- data/eyeballs.js.gemspec +83 -0
- data/lib/eyeballs.rb +11 -0
- data/lib/eyeballs/app_detector.rb +29 -0
- data/lib/eyeballs/app_generator.rb +30 -0
- data/lib/eyeballs/cli.rb +14 -0
- data/lib/eyeballs/controller_generator.rb +26 -0
- data/lib/eyeballs/model_generator.rb +26 -0
- data/lib/eyeballs/scaffold_generator.rb +66 -0
- data/spec/app_generator_spec.rb +51 -0
- data/spec/controller_generator_spec.rb +22 -0
- data/spec/model_generator_spec.rb +23 -0
- data/spec/rack_app_detector_spec.rb +25 -0
- data/spec/scaffold_generator_spec.rb +42 -0
- data/spec/spec_helper.rb +42 -0
- data/src/jquery.o_O.couchdb.js +107 -0
- data/src/jquery.o_O.dom.js +37 -0
- data/src/jquery.o_O.js +120 -0
- data/src/jquery.o_O.rails.js +68 -0
- data/src/o_O.js +286 -0
- data/src/o_O.localstorage.js +60 -0
- data/templates/app_root/index.html +26 -0
- data/templates/controller.js +3 -0
- data/templates/model.js +3 -0
- data/templates/scaffold_controller.js +75 -0
- data/templates/scaffold_edit.html.mustache +13 -0
- data/templates/scaffold_index.html +47 -0
- data/templates/scaffold_partial.html.mustache +12 -0
- data/test/unit/qunit.css +119 -0
- data/test/unit/qunit.js +1069 -0
- data/test/unit/test_controller.html +137 -0
- data/test/unit/test_dom.html +81 -0
- data/test/unit/test_dom_with_callbacks.html +121 -0
- data/test/unit/test_form.html +42 -0
- data/test/unit/test_localstorage.html +79 -0
- data/test/unit/test_model.html +136 -0
- data/test/unit/test_model_with_callbacks.html +118 -0
- data/test/unit/test_rails.html +97 -0
- metadata +117 -0
@@ -0,0 +1,226 @@
|
|
1
|
+
/*! Copyright (c) 2010 Brandon Aaron (http://brandonaaron.net)
|
2
|
+
* Dual licensed under the MIT (MIT_LICENSE.txt)
|
3
|
+
* and GPL Version 2 (GPL_LICENSE.txt) licenses.
|
4
|
+
*
|
5
|
+
* Version: 1.1.1
|
6
|
+
* Requires jQuery 1.3+
|
7
|
+
* Docs: http://docs.jquery.com/Plugins/livequery
|
8
|
+
*/
|
9
|
+
|
10
|
+
(function($) {
|
11
|
+
|
12
|
+
$.extend($.fn, {
|
13
|
+
livequery: function(type, fn, fn2) {
|
14
|
+
var self = this, q;
|
15
|
+
|
16
|
+
// Handle different call patterns
|
17
|
+
if ($.isFunction(type))
|
18
|
+
fn2 = fn, fn = type, type = undefined;
|
19
|
+
|
20
|
+
// See if Live Query already exists
|
21
|
+
$.each( $.livequery.queries, function(i, query) {
|
22
|
+
if ( self.selector == query.selector && self.context == query.context &&
|
23
|
+
type == query.type && (!fn || fn.$lqguid == query.fn.$lqguid) && (!fn2 || fn2.$lqguid == query.fn2.$lqguid) )
|
24
|
+
// Found the query, exit the each loop
|
25
|
+
return (q = query) && false;
|
26
|
+
});
|
27
|
+
|
28
|
+
// Create new Live Query if it wasn't found
|
29
|
+
q = q || new $.livequery(this.selector, this.context, type, fn, fn2);
|
30
|
+
|
31
|
+
// Make sure it is running
|
32
|
+
q.stopped = false;
|
33
|
+
|
34
|
+
// Run it immediately for the first time
|
35
|
+
q.run();
|
36
|
+
|
37
|
+
// Contnue the chain
|
38
|
+
return this;
|
39
|
+
},
|
40
|
+
|
41
|
+
expire: function(type, fn, fn2) {
|
42
|
+
var self = this;
|
43
|
+
|
44
|
+
// Handle different call patterns
|
45
|
+
if ($.isFunction(type))
|
46
|
+
fn2 = fn, fn = type, type = undefined;
|
47
|
+
|
48
|
+
// Find the Live Query based on arguments and stop it
|
49
|
+
$.each( $.livequery.queries, function(i, query) {
|
50
|
+
if ( self.selector == query.selector && self.context == query.context &&
|
51
|
+
(!type || type == query.type) && (!fn || fn.$lqguid == query.fn.$lqguid) && (!fn2 || fn2.$lqguid == query.fn2.$lqguid) && !this.stopped )
|
52
|
+
$.livequery.stop(query.id);
|
53
|
+
});
|
54
|
+
|
55
|
+
// Continue the chain
|
56
|
+
return this;
|
57
|
+
}
|
58
|
+
});
|
59
|
+
|
60
|
+
$.livequery = function(selector, context, type, fn, fn2) {
|
61
|
+
this.selector = selector;
|
62
|
+
this.context = context;
|
63
|
+
this.type = type;
|
64
|
+
this.fn = fn;
|
65
|
+
this.fn2 = fn2;
|
66
|
+
this.elements = [];
|
67
|
+
this.stopped = false;
|
68
|
+
|
69
|
+
// The id is the index of the Live Query in $.livequery.queries
|
70
|
+
this.id = $.livequery.queries.push(this)-1;
|
71
|
+
|
72
|
+
// Mark the functions for matching later on
|
73
|
+
fn.$lqguid = fn.$lqguid || $.livequery.guid++;
|
74
|
+
if (fn2) fn2.$lqguid = fn2.$lqguid || $.livequery.guid++;
|
75
|
+
|
76
|
+
// Return the Live Query
|
77
|
+
return this;
|
78
|
+
};
|
79
|
+
|
80
|
+
$.livequery.prototype = {
|
81
|
+
stop: function() {
|
82
|
+
var query = this;
|
83
|
+
|
84
|
+
if ( this.type )
|
85
|
+
// Unbind all bound events
|
86
|
+
this.elements.unbind(this.type, this.fn);
|
87
|
+
else if (this.fn2)
|
88
|
+
// Call the second function for all matched elements
|
89
|
+
this.elements.each(function(i, el) {
|
90
|
+
query.fn2.apply(el);
|
91
|
+
});
|
92
|
+
|
93
|
+
// Clear out matched elements
|
94
|
+
this.elements = [];
|
95
|
+
|
96
|
+
// Stop the Live Query from running until restarted
|
97
|
+
this.stopped = true;
|
98
|
+
},
|
99
|
+
|
100
|
+
run: function() {
|
101
|
+
// Short-circuit if stopped
|
102
|
+
if ( this.stopped ) return;
|
103
|
+
var query = this;
|
104
|
+
|
105
|
+
var oEls = this.elements,
|
106
|
+
els = $(this.selector, this.context),
|
107
|
+
nEls = els.not(oEls);
|
108
|
+
|
109
|
+
// Set elements to the latest set of matched elements
|
110
|
+
this.elements = els;
|
111
|
+
|
112
|
+
if (this.type) {
|
113
|
+
// Bind events to newly matched elements
|
114
|
+
nEls.bind(this.type, this.fn);
|
115
|
+
|
116
|
+
// Unbind events to elements no longer matched
|
117
|
+
if (oEls.length > 0)
|
118
|
+
$.each(oEls, function(i, el) {
|
119
|
+
if ( $.inArray(el, els) < 0 )
|
120
|
+
$.event.remove(el, query.type, query.fn);
|
121
|
+
});
|
122
|
+
}
|
123
|
+
else {
|
124
|
+
// Call the first function for newly matched elements
|
125
|
+
nEls.each(function() {
|
126
|
+
query.fn.apply(this);
|
127
|
+
});
|
128
|
+
|
129
|
+
// Call the second function for elements no longer matched
|
130
|
+
if ( this.fn2 && oEls.length > 0 )
|
131
|
+
$.each(oEls, function(i, el) {
|
132
|
+
if ( $.inArray(el, els) < 0 )
|
133
|
+
query.fn2.apply(el);
|
134
|
+
});
|
135
|
+
}
|
136
|
+
}
|
137
|
+
};
|
138
|
+
|
139
|
+
$.extend($.livequery, {
|
140
|
+
guid: 0,
|
141
|
+
queries: [],
|
142
|
+
queue: [],
|
143
|
+
running: false,
|
144
|
+
timeout: null,
|
145
|
+
|
146
|
+
checkQueue: function() {
|
147
|
+
if ( $.livequery.running && $.livequery.queue.length ) {
|
148
|
+
var length = $.livequery.queue.length;
|
149
|
+
// Run each Live Query currently in the queue
|
150
|
+
while ( length-- )
|
151
|
+
$.livequery.queries[ $.livequery.queue.shift() ].run();
|
152
|
+
}
|
153
|
+
},
|
154
|
+
|
155
|
+
pause: function() {
|
156
|
+
// Don't run anymore Live Queries until restarted
|
157
|
+
$.livequery.running = false;
|
158
|
+
},
|
159
|
+
|
160
|
+
play: function() {
|
161
|
+
// Restart Live Queries
|
162
|
+
$.livequery.running = true;
|
163
|
+
// Request a run of the Live Queries
|
164
|
+
$.livequery.run();
|
165
|
+
},
|
166
|
+
|
167
|
+
registerPlugin: function() {
|
168
|
+
$.each( arguments, function(i,n) {
|
169
|
+
// Short-circuit if the method doesn't exist
|
170
|
+
if (!$.fn[n]) return;
|
171
|
+
|
172
|
+
// Save a reference to the original method
|
173
|
+
var old = $.fn[n];
|
174
|
+
|
175
|
+
// Create a new method
|
176
|
+
$.fn[n] = function() {
|
177
|
+
// Call the original method
|
178
|
+
var r = old.apply(this, arguments);
|
179
|
+
|
180
|
+
// Request a run of the Live Queries
|
181
|
+
$.livequery.run();
|
182
|
+
|
183
|
+
// Return the original methods result
|
184
|
+
return r;
|
185
|
+
}
|
186
|
+
});
|
187
|
+
},
|
188
|
+
|
189
|
+
run: function(id) {
|
190
|
+
if (id != undefined) {
|
191
|
+
// Put the particular Live Query in the queue if it doesn't already exist
|
192
|
+
if ( $.inArray(id, $.livequery.queue) < 0 )
|
193
|
+
$.livequery.queue.push( id );
|
194
|
+
}
|
195
|
+
else
|
196
|
+
// Put each Live Query in the queue if it doesn't already exist
|
197
|
+
$.each( $.livequery.queries, function(id) {
|
198
|
+
if ( $.inArray(id, $.livequery.queue) < 0 )
|
199
|
+
$.livequery.queue.push( id );
|
200
|
+
});
|
201
|
+
|
202
|
+
// Clear timeout if it already exists
|
203
|
+
if ($.livequery.timeout) clearTimeout($.livequery.timeout);
|
204
|
+
// Create a timeout to check the queue and actually run the Live Queries
|
205
|
+
$.livequery.timeout = setTimeout($.livequery.checkQueue, 20);
|
206
|
+
},
|
207
|
+
|
208
|
+
stop: function(id) {
|
209
|
+
if (id != undefined)
|
210
|
+
// Stop are particular Live Query
|
211
|
+
$.livequery.queries[ id ].stop();
|
212
|
+
else
|
213
|
+
// Stop all Live Queries
|
214
|
+
$.each( $.livequery.queries, function(id) {
|
215
|
+
$.livequery.queries[ id ].stop();
|
216
|
+
});
|
217
|
+
}
|
218
|
+
});
|
219
|
+
|
220
|
+
// Register core DOM manipulation methods
|
221
|
+
$.livequery.registerPlugin('append', 'prepend', 'after', 'before', 'wrap', 'attr', 'removeAttr', 'addClass', 'removeClass', 'toggleClass', 'empty', 'remove', 'html');
|
222
|
+
|
223
|
+
// Run Live Queries when the Document is ready
|
224
|
+
$(function() { $.livequery.play(); });
|
225
|
+
|
226
|
+
})(jQuery);
|
data/dist/mustache.js
ADDED
@@ -0,0 +1,324 @@
|
|
1
|
+
/*
|
2
|
+
mustache.js — Logic-less templates in JavaScript
|
3
|
+
|
4
|
+
See http://mustache.github.com/ for more info.
|
5
|
+
*/
|
6
|
+
|
7
|
+
var Mustache = function() {
|
8
|
+
var Renderer = function() {};
|
9
|
+
|
10
|
+
Renderer.prototype = {
|
11
|
+
otag: "{{",
|
12
|
+
ctag: "}}",
|
13
|
+
pragmas: {},
|
14
|
+
buffer: [],
|
15
|
+
pragmas_implemented: {
|
16
|
+
"IMPLICIT-ITERATOR": true
|
17
|
+
},
|
18
|
+
|
19
|
+
render: function(template, context, partials, in_recursion) {
|
20
|
+
// reset buffer
|
21
|
+
// TODO: make this non-lazy
|
22
|
+
if(!in_recursion)
|
23
|
+
this.buffer = [];
|
24
|
+
// fail fast
|
25
|
+
if(!this.includes("", template)) {
|
26
|
+
if(in_recursion) {
|
27
|
+
return template;
|
28
|
+
} else {
|
29
|
+
this.send(template);
|
30
|
+
return;
|
31
|
+
}
|
32
|
+
}
|
33
|
+
|
34
|
+
if(!in_recursion) {
|
35
|
+
this.buffer = [];
|
36
|
+
}
|
37
|
+
|
38
|
+
template = this.render_pragmas(template);
|
39
|
+
var html = this.render_section(template, context, partials);
|
40
|
+
if(in_recursion) {
|
41
|
+
return this.render_tags(html, context, partials, in_recursion);
|
42
|
+
}
|
43
|
+
|
44
|
+
this.render_tags(html, context, partials, in_recursion);
|
45
|
+
},
|
46
|
+
|
47
|
+
/*
|
48
|
+
Sends parsed lines
|
49
|
+
*/
|
50
|
+
send: function(line) {
|
51
|
+
if(line != "") {
|
52
|
+
this.buffer.push(line);
|
53
|
+
}
|
54
|
+
},
|
55
|
+
|
56
|
+
/*
|
57
|
+
Looks for %PRAGMAS
|
58
|
+
*/
|
59
|
+
render_pragmas: function(template) {
|
60
|
+
// no pragmas
|
61
|
+
if(!this.includes("%", template)) {
|
62
|
+
return template;
|
63
|
+
}
|
64
|
+
|
65
|
+
var that = this;
|
66
|
+
var regex = new RegExp(this.otag + "%([\\w_-]+) ?([\\w]+=[\\w]+)?"
|
67
|
+
+ this.ctag);
|
68
|
+
return template.replace(regex, function(match, pragma, options) {
|
69
|
+
if(!that.pragmas_implemented[pragma]) {
|
70
|
+
throw({message: "This implementation of mustache doesn't understand the '"
|
71
|
+
+ pragma + "' pragma"});
|
72
|
+
}
|
73
|
+
that.pragmas[pragma] = {};
|
74
|
+
if(options) {
|
75
|
+
var opts = options.split("=");
|
76
|
+
that.pragmas[pragma][opts[0]] = opts[1];
|
77
|
+
}
|
78
|
+
return "";
|
79
|
+
// ignore unknown pragmas silently
|
80
|
+
});
|
81
|
+
},
|
82
|
+
|
83
|
+
/*
|
84
|
+
Tries to find a partial in the global scope and render it
|
85
|
+
*/
|
86
|
+
render_partial: function(name, context, partials) {
|
87
|
+
if(!partials || !partials[name]) {
|
88
|
+
throw({message: "unknown_partial '" + name + "'"});
|
89
|
+
}
|
90
|
+
if(typeof(context[name]) != "object") {
|
91
|
+
return partials[name];
|
92
|
+
}
|
93
|
+
return this.render(partials[name], context[name], partials, true);
|
94
|
+
},
|
95
|
+
|
96
|
+
/*
|
97
|
+
Renders inverted (^) and normal (#) sections
|
98
|
+
*/
|
99
|
+
render_section: function(template, context, partials) {
|
100
|
+
if(!this.includes("#", template) && !this.includes("^", template)) {
|
101
|
+
return template;
|
102
|
+
}
|
103
|
+
|
104
|
+
var that = this;
|
105
|
+
// CSW - Added "+?" so it finds the tighest bound, not the widest
|
106
|
+
var regex = new RegExp(this.otag + "(\\^|\\#)(.+)" + this.ctag +
|
107
|
+
"\\s*([\\s\\S]+?)" + this.otag + "\\/\\2" + this.ctag +
|
108
|
+
"\\s*", "mg");
|
109
|
+
|
110
|
+
// for each {{#foo}}{{/foo}} section do...
|
111
|
+
return template.replace(regex, function(match, type, name, content) {
|
112
|
+
var value = that.find(name, context);
|
113
|
+
if(type == "^") { // inverted section
|
114
|
+
if(!value || that.is_array(value) && value.length == 0) {
|
115
|
+
// false or empty list, render it
|
116
|
+
return that.render(content, context, partials, true);
|
117
|
+
} else {
|
118
|
+
return "";
|
119
|
+
}
|
120
|
+
} else if(type == "#") { // normal section
|
121
|
+
if(that.is_array(value)) { // Enumerable, Let's loop!
|
122
|
+
return that.map(value, function(row) {
|
123
|
+
return that.render(content, that.merge(context,
|
124
|
+
that.create_context(row)), partials, true);
|
125
|
+
}).join("");
|
126
|
+
} else if(that.is_object(value)) { // Object, Use it as subcontext!
|
127
|
+
return that.render(content,
|
128
|
+
that.merge(context, that.create_context(value)), partials, true);
|
129
|
+
} else if(typeof value === "function") {
|
130
|
+
// higher order section
|
131
|
+
return value.call(context, content, function(text) {
|
132
|
+
return that.render(text, context, partials, true);
|
133
|
+
})
|
134
|
+
} else if(value) { // boolean section
|
135
|
+
return that.render(content, context, partials, true);
|
136
|
+
} else {
|
137
|
+
return "";
|
138
|
+
}
|
139
|
+
}
|
140
|
+
});
|
141
|
+
},
|
142
|
+
|
143
|
+
/*
|
144
|
+
Replace {{foo}} and friends with values from our view
|
145
|
+
*/
|
146
|
+
render_tags: function(template, context, partials, in_recursion) {
|
147
|
+
// tit for tat
|
148
|
+
var that = this;
|
149
|
+
|
150
|
+
var new_regex = function() {
|
151
|
+
return new RegExp(that.otag + "(=|!|>|\\{|%)?([^\/#\^]+?)\\1?" +
|
152
|
+
that.ctag + "+", "g");
|
153
|
+
};
|
154
|
+
|
155
|
+
var regex = new_regex();
|
156
|
+
var lines = template.split("\n");
|
157
|
+
for (var i=0; i < lines.length; i++) {
|
158
|
+
lines[i] = lines[i].replace(regex, function(match, operator, name) {
|
159
|
+
switch(operator) {
|
160
|
+
case "!": // ignore comments
|
161
|
+
return "";
|
162
|
+
case "=": // set new delimiters, rebuild the replace regexp
|
163
|
+
that.set_delimiters(name);
|
164
|
+
regex = new_regex();
|
165
|
+
return "";
|
166
|
+
case ">": // render partial
|
167
|
+
return that.render_partial(name, context, partials);
|
168
|
+
case "{": // the triple mustache is unescaped
|
169
|
+
return that.find(name, context);
|
170
|
+
default: // escape the value
|
171
|
+
return that.escape(that.find(name, context));
|
172
|
+
}
|
173
|
+
}, this);
|
174
|
+
if(!in_recursion) {
|
175
|
+
this.send(lines[i]);
|
176
|
+
}
|
177
|
+
}
|
178
|
+
|
179
|
+
if(in_recursion) {
|
180
|
+
return lines.join("\n");
|
181
|
+
}
|
182
|
+
},
|
183
|
+
|
184
|
+
set_delimiters: function(delimiters) {
|
185
|
+
var dels = delimiters.split(" ");
|
186
|
+
this.otag = this.escape_regex(dels[0]);
|
187
|
+
this.ctag = this.escape_regex(dels[1]);
|
188
|
+
},
|
189
|
+
|
190
|
+
escape_regex: function(text) {
|
191
|
+
// thank you Simon Willison
|
192
|
+
if(!arguments.callee.sRE) {
|
193
|
+
var specials = [
|
194
|
+
'/', '.', '*', '+', '?', '|',
|
195
|
+
'(', ')', '[', ']', '{', '}', '\\'
|
196
|
+
];
|
197
|
+
arguments.callee.sRE = new RegExp(
|
198
|
+
'(\\' + specials.join('|\\') + ')', 'g'
|
199
|
+
);
|
200
|
+
}
|
201
|
+
return text.replace(arguments.callee.sRE, '\\$1');
|
202
|
+
},
|
203
|
+
|
204
|
+
/*
|
205
|
+
find `name` in current `context`. That is find me a value
|
206
|
+
from the view object
|
207
|
+
*/
|
208
|
+
find: function(name, context) {
|
209
|
+
name = this.trim(name);
|
210
|
+
if(typeof context[name] === "function") {
|
211
|
+
return context[name].apply(context);
|
212
|
+
}
|
213
|
+
if(context[name] !== undefined) {
|
214
|
+
return context[name];
|
215
|
+
}
|
216
|
+
// silently ignore unkown variables
|
217
|
+
return "";
|
218
|
+
},
|
219
|
+
|
220
|
+
// Utility methods
|
221
|
+
|
222
|
+
/* includes tag */
|
223
|
+
includes: function(needle, haystack) {
|
224
|
+
return haystack.indexOf(this.otag + needle) != -1;
|
225
|
+
},
|
226
|
+
|
227
|
+
/*
|
228
|
+
Does away with nasty characters
|
229
|
+
*/
|
230
|
+
escape: function(s) {
|
231
|
+
return ((s == null) ? "" : s).toString().replace(/&(?!\w+;)|["<>\\]/g, function(s) {
|
232
|
+
switch(s) {
|
233
|
+
case "&": return "&";
|
234
|
+
case "\\": return "\\\\";;
|
235
|
+
case '"': return '\"';;
|
236
|
+
case "<": return "<";
|
237
|
+
case ">": return ">";
|
238
|
+
default: return s;
|
239
|
+
}
|
240
|
+
});
|
241
|
+
},
|
242
|
+
|
243
|
+
/*
|
244
|
+
Merges all properties of object `b` into object `a`.
|
245
|
+
`b.property` overwrites a.property`
|
246
|
+
*/
|
247
|
+
merge: function(a, b) {
|
248
|
+
var _new = {};
|
249
|
+
for(var name in a) {
|
250
|
+
if(a.hasOwnProperty(name)) {
|
251
|
+
_new[name] = a[name];
|
252
|
+
}
|
253
|
+
};
|
254
|
+
for(var name in b) {
|
255
|
+
if(b.hasOwnProperty(name)) {
|
256
|
+
_new[name] = b[name];
|
257
|
+
}
|
258
|
+
};
|
259
|
+
return _new;
|
260
|
+
},
|
261
|
+
|
262
|
+
// by @langalex, support for arrays of strings
|
263
|
+
create_context: function(_context) {
|
264
|
+
if(this.is_object(_context)) {
|
265
|
+
return _context;
|
266
|
+
} else if(this.pragmas["IMPLICIT-ITERATOR"]) {
|
267
|
+
var iterator = this.pragmas["IMPLICIT-ITERATOR"].iterator || ".";
|
268
|
+
var ctx = {};
|
269
|
+
ctx[iterator] = _context;
|
270
|
+
return ctx;
|
271
|
+
}
|
272
|
+
},
|
273
|
+
|
274
|
+
is_object: function(a) {
|
275
|
+
return a && typeof a == "object";
|
276
|
+
},
|
277
|
+
|
278
|
+
is_array: function(a) {
|
279
|
+
return Object.prototype.toString.call(a) === '[object Array]';
|
280
|
+
},
|
281
|
+
|
282
|
+
/*
|
283
|
+
Gets rid of leading and trailing whitespace
|
284
|
+
*/
|
285
|
+
trim: function(s) {
|
286
|
+
return s.replace(/^\s*|\s*$/g, "");
|
287
|
+
},
|
288
|
+
|
289
|
+
/*
|
290
|
+
Why, why, why? Because IE. Cry, cry cry.
|
291
|
+
*/
|
292
|
+
map: function(array, fn) {
|
293
|
+
if (typeof array.map == "function") {
|
294
|
+
return array.map(fn);
|
295
|
+
} else {
|
296
|
+
var r = [];
|
297
|
+
var l = array.length;
|
298
|
+
for(var i=0;i<l;i++) {
|
299
|
+
r.push(fn(array[i]));
|
300
|
+
}
|
301
|
+
return r;
|
302
|
+
}
|
303
|
+
}
|
304
|
+
};
|
305
|
+
|
306
|
+
return({
|
307
|
+
name: "mustache.js",
|
308
|
+
version: "0.3.0-dev",
|
309
|
+
|
310
|
+
/*
|
311
|
+
Turns a template and view into HTML
|
312
|
+
*/
|
313
|
+
to_html: function(template, view, partials, send_fun) {
|
314
|
+
var renderer = new Renderer();
|
315
|
+
if(send_fun) {
|
316
|
+
renderer.send = send_fun;
|
317
|
+
}
|
318
|
+
renderer.render(template, view, partials);
|
319
|
+
if(!send_fun) {
|
320
|
+
return renderer.buffer.join("\n");
|
321
|
+
}
|
322
|
+
}
|
323
|
+
});
|
324
|
+
}();
|