Develop and Download Open Source Software

Browse Subversion Repository

Annotation of /js/ejs.js

Parent Directory Parent Directory | Revision Log Revision Log


Revision 4 - (hide annotations) (download) (as text)
Fri Dec 4 12:17:36 2009 UTC (14 years, 5 months ago) by berupon
File MIME type: application/x-javascript
File size: 13277 byte(s)
まだ完成していないけど途中経過の記録というか…backupとしてcommit
1 berupon 4 (function(){
2    
3    
4     var rsplit = function(string, regex) {
5     var result = regex.exec(string),retArr = new Array(), first_idx, last_idx, first_bit;
6     while (result != null)
7     {
8     first_idx = result.index; last_idx = regex.lastIndex;
9     if ((first_idx) != 0)
10     {
11     first_bit = string.substring(0,first_idx);
12     retArr.push(string.substring(0,first_idx));
13     string = string.slice(first_idx);
14     }
15     retArr.push(result[0]);
16     string = string.slice(result[0].length);
17     result = regex.exec(string);
18     }
19     if (! string == '')
20     {
21     retArr.push(string);
22     }
23     return retArr;
24     },
25     chop = function(string){
26     return string.substr(0, string.length - 1);
27     },
28     extend = function(d, s){
29     for(var n in s){
30     if(s.hasOwnProperty(n)) d[n] = s[n]
31     }
32     }
33    
34    
35     EJS = function( options ){
36     options = typeof options == "string" ? {view: options} : options
37     this.set_options(options);
38     if(options.precompiled){
39     this.template = {};
40     this.template.process = options.precompiled;
41     EJS.update(this.name, this);
42     return;
43     }
44     if(options.element)
45     {
46     if(typeof options.element == 'string'){
47     var name = options.element
48     options.element = document.getElementById( options.element )
49     if(options.element == null) throw name+'does not exist!'
50     }
51     if(options.element.value){
52     this.text = options.element.value
53     }else{
54     this.text = options.element.innerHTML
55     }
56     this.name = options.element.id
57     this.type = '['
58     }else if(options.url){
59     options.url = EJS.endExt(options.url, this.extMatch);
60     this.name = this.name ? this.name : options.url;
61     var url = options.url
62     //options.view = options.absolute_url || options.view || options.;
63     var template = EJS.get(this.name /*url*/, this.cache);
64     if (template) return template;
65     if (template == EJS.INVALID_PATH) return null;
66     try{
67     this.text = EJS.request( url+(this.cache ? '' : '?'+Math.random() ));
68     }catch(e){}
69    
70     if(this.text == null){
71     throw( {type: 'EJS', message: 'There is no template at '+url} );
72     }
73     //this.name = url;
74     }
75     var template = new EJS.Compiler(this.text, this.type);
76    
77     template.compile(options, this.name);
78    
79    
80     EJS.update(this.name, this);
81     this.template = template;
82     };
83     /* @Prototype*/
84     EJS.prototype = {
85     /**
86     * Renders an object with extra view helpers attached to the view.
87     * @param {Object} object data to be rendered
88     * @param {Object} extra_helpers an object with additonal view helpers
89     * @return {String} returns the result of the string
90     */
91     render : function(object, extra_helpers){
92     object = object || {};
93     this._extra_helpers = extra_helpers;
94     var v = new EJS.Helpers(object, extra_helpers || {});
95     return this.template.process.call(object, object,v);
96     },
97     update : function(element, options){
98     if(typeof element == 'string'){
99     element = document.getElementById(element)
100     }
101     if(options == null){
102     _template = this;
103     return function(object){
104     EJS.prototype.update.call(_template, element, object)
105     }
106     }
107     if(typeof options == 'string'){
108     params = {}
109     params.url = options
110     _template = this;
111     params.onComplete = function(request){
112     var object = eval( request.responseText )
113     EJS.prototype.update.call(_template, element, object)
114     }
115     EJS.ajax_request(params)
116     }else
117     {
118     element.innerHTML = this.render(options)
119     }
120     },
121     out : function(){
122     return this.template.out;
123     },
124     /**
125     * Sets options on this view to be rendered with.
126     * @param {Object} options
127     */
128     set_options : function(options){
129     this.type = options.type || EJS.type;
130     this.cache = options.cache != null ? options.cache : EJS.cache;
131     this.text = options.text || null;
132     this.name = options.name || null;
133     this.ext = options.ext || EJS.ext;
134     this.extMatch = new RegExp(this.ext.replace(/\./, '\.'));
135     }
136     };
137     EJS.endExt = function(path, match){
138     if(!path) return null;
139     match.lastIndex = 0
140     return path+ (match.test(path) ? '' : this.ext )
141     }
142    
143    
144    
145    
146     /* @Static*/
147     EJS.Scanner = function(source, left, right) {
148    
149     extend(this,
150     {left_delimiter: left +'%',
151     right_delimiter: '%'+right,
152     double_left: left+'%%',
153     double_right: '%%'+right,
154     left_equal: left+'%=',
155     left_comment: left+'%#'})
156    
157     this.SplitRegexp = left=='[' ? /(\[%%)|(%%\])|(\[%=)|(\[%#)|(\[%)|(%\]\n)|(%\])|(\n)/ : new RegExp('('+this.double_left+')|(%%'+this.double_right+')|('+this.left_equal+')|('+this.left_comment+')|('+this.left_delimiter+')|('+this.right_delimiter+'\n)|('+this.right_delimiter+')|(\n)') ;
158    
159     this.source = source;
160     this.stag = null;
161     this.lines = 0;
162     };
163    
164     EJS.Scanner.to_text = function(input){
165     if(input == null || input === undefined)
166     return '';
167     if(input instanceof Date)
168     return input.toDateString();
169     if(input.toString)
170     return input.toString();
171     return '';
172     };
173    
174     EJS.Scanner.prototype = {
175     scan: function(block) {
176     scanline = this.scanline;
177     regex = this.SplitRegexp;
178     if (! this.source == '')
179     {
180     var source_split = rsplit(this.source, /\n/);
181     for(var i=0; i<source_split.length; i++) {
182     var item = source_split[i];
183     this.scanline(item, regex, block);
184     }
185     }
186     },
187     scanline: function(line, regex, block) {
188     this.lines++;
189     var line_split = rsplit(line, regex);
190     for(var i=0; i<line_split.length; i++) {
191     var token = line_split[i];
192     if (token != null) {
193     try{
194     block(token, this);
195     }catch(e){
196     throw {type: 'EJS.Scanner', line: this.lines};
197     }
198     }
199     }
200     }
201     };
202    
203    
204     EJS.Buffer = function(pre_cmd, post_cmd) {
205     this.line = new Array();
206     this.script = "";
207     this.pre_cmd = pre_cmd;
208     this.post_cmd = post_cmd;
209     for (var i=0; i<this.pre_cmd.length; i++)
210     {
211     this.push(pre_cmd[i]);
212     }
213     };
214     EJS.Buffer.prototype = {
215    
216     push: function(cmd) {
217     this.line.push(cmd);
218     },
219    
220     cr: function() {
221     this.script = this.script + this.line.join('; ');
222     this.line = new Array();
223     this.script = this.script + "\n";
224     },
225    
226     close: function() {
227     if (this.line.length > 0)
228     {
229     for (var i=0; i<this.post_cmd.length; i++){
230     this.push(pre_cmd[i]);
231     }
232     this.script = this.script + this.line.join('; ');
233     line = null;
234     }
235     }
236    
237     };
238    
239    
240     EJS.Compiler = function(source, left) {
241     this.pre_cmd = ['var ___ViewO = [];'];
242     this.post_cmd = new Array();
243     this.source = ' ';
244     if (source != null)
245     {
246     if (typeof source == 'string')
247     {
248     source = source.replace(/\r\n/g, "\n");
249     source = source.replace(/\r/g, "\n");
250     this.source = source;
251     }else if (source.innerHTML){
252     this.source = source.innerHTML;
253     }
254     if (typeof this.source != 'string'){
255     this.source = "";
256     }
257     }
258     left = left || '<';
259     var right = '>';
260     switch(left) {
261     case '[':
262     right = ']';
263     break;
264     case '<':
265     break;
266     default:
267     throw left+' is not a supported deliminator';
268     break;
269     }
270     this.scanner = new EJS.Scanner(this.source, left, right);
271     this.out = '';
272     };
273     EJS.Compiler.prototype = {
274     compile: function(options, name) {
275     options = options || {};
276     this.out = '';
277     var put_cmd = "___ViewO.push(";
278     var insert_cmd = put_cmd;
279     var buff = new EJS.Buffer(this.pre_cmd, this.post_cmd);
280     var content = '';
281     var clean = function(content)
282     {
283     content = content.replace(/\\/g, '\\\\');
284     content = content.replace(/\n/g, '\\n');
285     content = content.replace(/"/g, '\\"');
286     return content;
287     };
288     this.scanner.scan(function(token, scanner) {
289     if (scanner.stag == null)
290     {
291     switch(token) {
292     case '\n':
293     content = content + "\n";
294     buff.push(put_cmd + '"' + clean(content) + '");');
295     buff.cr();
296     content = '';
297     break;
298     case scanner.left_delimiter:
299     case scanner.left_equal:
300     case scanner.left_comment:
301     scanner.stag = token;
302     if (content.length > 0)
303     {
304     buff.push(put_cmd + '"' + clean(content) + '")');
305     }
306     content = '';
307     break;
308     case scanner.double_left:
309     content = content + scanner.left_delimiter;
310     break;
311     default:
312     content = content + token;
313     break;
314     }
315     }
316     else {
317     switch(token) {
318     case scanner.right_delimiter:
319     switch(scanner.stag) {
320     case scanner.left_delimiter:
321     if (content[content.length - 1] == '\n')
322     {
323     content = chop(content);
324     buff.push(content);
325     buff.cr();
326     }
327     else {
328     buff.push(content);
329     }
330     break;
331     case scanner.left_equal:
332     buff.push(insert_cmd + "(EJS.Scanner.to_text(" + content + ")))");
333     break;
334     }
335     scanner.stag = null;
336     content = '';
337     break;
338     case scanner.double_right:
339     content = content + scanner.right_delimiter;
340     break;
341     default:
342     content = content + token;
343     break;
344     }
345     }
346     });
347     if (content.length > 0)
348     {
349     // Chould be content.dump in Ruby
350     buff.push(put_cmd + '"' + clean(content) + '")');
351     }
352     buff.close();
353     this.out = buff.script + ";";
354     var to_be_evaled = '/*'+name+'*/this.process = function(_CONTEXT,_VIEW) { try { with(_VIEW) { with (_CONTEXT) {'+this.out+" return ___ViewO.join('');}}}catch(e){e.lineNumber=null;throw e;}};";
355    
356     try{
357     eval(to_be_evaled);
358     }catch(e){
359     if(typeof JSLINT != 'undefined'){
360     JSLINT(this.out);
361     for(var i = 0; i < JSLINT.errors.length; i++){
362     var error = JSLINT.errors[i];
363     if(error.reason != "Unnecessary semicolon."){
364     error.line++;
365     var e = new Error();
366     e.lineNumber = error.line;
367     e.message = error.reason;
368     if(options.view)
369     e.fileName = options.view;
370     throw e;
371     }
372     }
373     }else{
374     throw e;
375     }
376     }
377     }
378     };
379    
380    
381     //type, cache, folder
382     /**
383     * Sets default options for all views
384     * @param {Object} options Set view with the following options
385     * <table class="options">
386     <tbody><tr><th>Option</th><th>Default</th><th>Description</th></tr>
387     <tr>
388     <td>type</td>
389     <td>'<'</td>
390     <td>type of magic tags. Options are '&lt;' or '['
391     </td>
392     </tr>
393     <tr>
394     <td>cache</td>
395     <td>true in production mode, false in other modes</td>
396     <td>true to cache template.
397     </td>
398     </tr>
399     </tbody></table>
400     *
401     */
402     EJS.config = function(options){
403     EJS.cache = options.cache != null ? options.cache : EJS.cache;
404     EJS.type = options.type != null ? options.type : EJS.type;
405     EJS.ext = options.ext != null ? options.ext : EJS.ext;
406    
407     var templates_directory = EJS.templates_directory || {}; //nice and private container
408     EJS.templates_directory = templates_directory;
409     EJS.get = function(path, cache){
410     if(cache == false) return null;
411     if(templates_directory[path]) return templates_directory[path];
412     return null;
413     };
414    
415     EJS.update = function(path, template) {
416     if(path == null) return;
417     templates_directory[path] = template ;
418     };
419    
420     EJS.INVALID_PATH = -1;
421     };
422     EJS.config( {cache: true, type: '<', ext: '.ejs' } );
423    
424    
425    
426     /**
427     * @constructor
428     * By adding functions to EJS.Helpers.prototype, those functions will be available in the
429     * views.
430     * @init Creates a view helper. This function is called internally. You should never call it.
431     * @param {Object} data The data passed to the view. Helpers have access to it through this._data
432     */
433     EJS.Helpers = function(data, extras){
434     this._data = data;
435     this._extras = extras;
436     extend(this, extras );
437     };
438     /* @prototype*/
439     EJS.Helpers.prototype = {
440     /**
441     * Renders a new view. If data is passed in, uses that to render the view.
442     * @param {Object} options standard options passed to a new view.
443     * @param {optional:Object} data
444     * @return {String}
445     */
446     view: function(options, data, helpers){
447     if(!helpers) helpers = this._extras
448     if(!data) data = this._data;
449     return new EJS(options).render(data, helpers);
450     },
451     /**
452     * For a given value, tries to create a human representation.
453     * @param {Object} input the value being converted.
454     * @param {Object} null_text what text should be present if input == null or undefined, defaults to ''
455     * @return {String}
456     */
457     to_text: function(input, null_text) {
458     if(input == null || input === undefined) return null_text || '';
459     if(input instanceof Date) return input.toDateString();
460     if(input.toString) return input.toString().replace(/\n/g, '<br />').replace(/''/g, "'");
461     return '';
462     }
463     };
464     EJS.newRequest = function(){
465     var factories = [function() { return new ActiveXObject("Msxml2.XMLHTTP"); },function() { return new XMLHttpRequest(); },function() { return new ActiveXObject("Microsoft.XMLHTTP"); }];
466     for(var i = 0; i < factories.length; i++) {
467     try {
468     var request = factories[i]();
469     if (request != null) return request;
470     }
471     catch(e) { continue;}
472     }
473     }
474    
475     EJS.request = function(path){
476     var request = new EJS.newRequest()
477     request.open("GET", path, false);
478    
479     try{request.send(null);}
480     catch(e){return null;}
481    
482     if ( request.status == 404 || request.status == 2 ||(request.status == 0 && request.responseText == '') ) return null;
483    
484     return request.responseText
485     }
486     EJS.ajax_request = function(params){
487     params.method = ( params.method ? params.method : 'GET')
488    
489     var request = new EJS.newRequest();
490     request.onreadystatechange = function(){
491     if(request.readyState == 4){
492     if(request.status == 200){
493     params.onComplete(request)
494     }else
495     {
496     params.onComplete(request)
497     }
498     }
499     }
500     request.open(params.method, params.url)
501     request.send(null)
502     }
503    
504    
505     })();

Back to OSDN">Back to OSDN
ViewVC Help
Powered by ViewVC 1.1.26