source: trunk/prototype/app/plugins/ejs/ejs.js @ 5283

Revision 5283, 13.0 KB checked in by douglasz, 12 years ago (diff)

Ticket #2402 - Inconsistencia ao anexar mensagens ao e-mail

  • Property svn:executable set to *
Line 
1(function(){
2   
3
4var 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},
25chop =  function(string){
26    return string.substr(0, string.length - 1);
27},
28extend = function(d, s){
29    for(var n in s){
30        if(s.hasOwnProperty(n))  d[n] = s[n]
31    }
32}
33
34
35EJS = 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*/
84EJS.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};
137EJS.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*/
147EJS.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
164EJS.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
174EJS.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
204EJS.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};
214EJS.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
240EJS.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};
273EJS.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 */
402EJS.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};
422EJS.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 */
433EJS.Helpers = function(data, extras){
434        this._data = data;
435    this._extras = extras;
436    extend(this, extras );
437};
438/* @prototype*/
439EJS.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})();
Note: See TracBrowser for help on using the repository browser.