1 // vim:set noet fdm=syntax fdl=0 fdc=3 fdn=2:
2 //---------------------------------------------------------
4 //---------------------------------------------------------
10 if (window.DOMParser) {
11 parser=new DOMParser();
12 xmlDoc=parser.parseFromString(text,"text/xml");
14 xmlDoc=new ActiveXObject("Msxml2.DOMDocument.4.0");
15 xmlDoc=new ActiveXObject("Microsoft.XMLDOM");
16 Which versions to try, it's confusing...
19 xmlDoc.preserveWhiteSpace=true;
21 xmlDoc.loadXML(text); ?
24 Support space in IE by reparsing the responseText
25 xmlhttp.responseXML.loadXML(xmlhttp.responseText); ?
27 Preprocess: (nice optimization)
28 preprocess by flattening all non t- element to a TEXT_NODE.
29 count the number of "\n" in text nodes to give an aproximate LINE NUMBER on elements for error reporting
30 if from IE HTMLDOM use if(a[i].specified) to avoid 88 empty attributes per element during the preprocess,
32 implement t-trim 'left' 'right' 'both', is it needed ? inner=render_trim(l_inner.join(), t_att)
34 Ruby/python: to backport from javascript to python/ruby render_node to use regexp, factorize foreach %var, t-att test for tuple(attname,value)
37 we reintroduced t-att-id, no more t-esc-id because of the new convention t-att="["id","val"]"
46 eval_object:function(e, v) {
47 // TODO: Currently this will also replace and, or, ... in strings. Try
48 // 'hi boys and girls' != '' and 1 == 1 -- will be replaced to : 'hi boys && girls' != '' && 1 == 1
49 // try to find a solution without tokenizing
50 e = e.replace(/\Wand\W/g, " && ");
51 e = e.replace(/\Wor\W/g, " and ");
52 e = e.replace(/\Wgt\W/g, " > ");
53 e = e.replace(/\Wgte\W/g, " >= ");
54 e = e.replace(/\Wlt\W/g, " < ");
55 e = e.replace(/\Wlte\W/g, " <= ");
56 if (v[e] != undefined) {
59 with (v) return eval(e);
62 eval_str:function(e, v) {
63 var r = this.eval_object(e, v);
64 r = (typeof(r) == "undefined" || r == null) ? "" : r.toString();
65 return e == "0" ? v["0"] : r;
67 eval_format:function(e, v) {
68 var i,m,r,src = e.split(/#/);
70 for (i = 1; i < src.length; i++) {
71 if (m = src[i].match(/^{(.*)}(.*)/)) {
72 r += this.eval_str(m[1], v) + m[2];
79 eval_bool:function(e, v) {
80 return this.eval_object(e, v) ? true : false;
82 trim : function(v, mode) {
83 if (!v || !mode) return v;
85 return v.replace(/^\s*|\s*$/g, "");
86 } else if (mode == "left") {
87 return v.replace(/^\s*/, "");
88 } else if (mode == "right") {
89 return v.replace(/\s*$/, "");
94 escape_text:function(s) {
95 return s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
97 escape_att:function(s) {
98 return s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
100 render_node : function(e, v, inner_trim) {
102 if (e.nodeType == 3) {
103 r = inner_trim ? this.trim(e.data, inner_trim) : e.data;
104 } else if (e.nodeType == 1) {
108 var a = e.attributes;
109 for (var i = 0; i < a.length; i++) {
110 var an = a[i].name,av = a[i].value;
112 if (m = an.match(this.reg)) {
115 n = m[2].substring(1);
116 av = this.eval_str(av, v);
118 if (f = this.att[n]) {
119 this[f](e, t_att, g_att, v, m[2], av);
120 } else if (f = this.tag[n]) {
128 if (inner_trim && !t_att["trim"]) {
129 t_att["trim"] = "inner " + inner_trim;
132 r = this[t_render](e, t_att, g_att, v);
134 r = this.render_element(e, t_att, g_att, v);
139 render_element:function(e, t_att, g_att, v) {
140 var inner = "", ec = e.childNodes, trim = t_att["trim"], inner_trim;
142 if (trim.match(/(^|\W)(inner)($|\W)/)) {
146 var tm = trim.match(/(^|\W)(both|left|right)($|\W)/);
147 if (tm) trim = tm[2];
149 for (var i = 0; i < ec.length; i++) {
150 inner += inner_trim ? this.trim(this.render_node(ec[i], v, inner_trim ? trim : null), trim) : this.render_node(ec[i], v, inner_trim ? trim : null);
152 if (trim && !inner_trim) {
153 inner = this.trim(inner, trim);
155 if (e.tagName == this.prefix) {
159 for (var an in g_att) {
161 att += " " + an + '="' + this.escape_att(av) + '"';
163 return inner.length ? "<" + e.tagName + att + ">" + inner + "</" + e.tagName + ">" : "<" + e.tagName + att + "/>";
166 render_att_att:function(e, t_att, g_att, v, ext, av) {
168 g_att[ext.substring(1)] = this.eval_str(av, v);
170 o = this.eval_object(av, v);
174 render_att_attf:function(e, t_att, g_att, v, ext, av) {
175 g_att[ext.substring(1)] = this.eval_format(av, v);
177 render_tag_raw:function(e, t_att, g_att, v) {
178 return this.eval_str(t_att["raw"], v);
180 render_tag_rawf:function(e, t_att, g_att, v) {
181 return this.eval_format(t_att["raw"], v);
183 render_tag_esc:function(e, t_att, g_att, v) {
184 return this.escape_text(this.eval_str(t_att["esc"], v));
186 render_tag_escf:function(e, t_att, g_att, v) {
187 return this.escape_text(this.eval_format(t_att["esc"], v));
189 render_tag_if:function(e, t_att, g_att, v) {
190 return this.eval_bool(t_att["if"], v) ? this.render_element(e, t_att, g_att, v) : "";
192 render_tag_set:function(e, t_att, g_att, v) {
193 var ev = t_att["value"];
194 if (ev && ev.constructor != Function) {
195 v[t_att["set"]] = this.eval_object(ev, v);
197 v[t_att["set"]] = this.render_element(e, t_att, g_att, v);
201 render_tag_call:function(e, t_att, g_att, v) {
203 if (!t_att["import"]) {
209 d["0"] = this.render_element(e, t_att, g_att, d);
210 return this.render(t_att["call"], d);
212 render_tag_js:function(e, t_att, g_att, v) {
213 var r = this.eval_str(this.render_element(e, t_att, g_att, v), v);
214 return t_att["js"] != "quiet" ? r : "";
216 render_tag_foreach:function(e, t_att, g_att, v) {
217 var expr = t_att["foreach"];
218 var enu = this.eval_object(expr, v);
221 var val = t_att['as'] || expr.replace(/[^a-zA-Z0-9]/g, '_');
226 d[val + "_all"] = enu;
227 val_value = val + "_value";
228 val_index = val + "_index";
229 val_first = val + "_first";
230 val_last = val + "_last";
231 val_parity = val + "_parity";
232 var size = enu.length;
234 d[val + "_size"] = size;
235 for (var i = 0; i < size; i++) {
239 d[val_first] = i == 0;
240 d[val_last] = i + 1 == size;
241 d[val_parity] = (i % 2 == 1 ? 'odd' : 'even');
242 if (cur.constructor == Object) {
248 var r = this.render_element(e, t_att, g_att, d);
255 d[val_index] = index;
256 d[val_first] = index == 0;
257 d[val_parity] = (index % 2 == 1 ? 'odd' : 'even');
259 ru.push(this.render_element(e, t_att, g_att, d));
265 return "qweb: foreach " + expr + " not found.";
270 for (var i in this) {
271 if (m = i.match(/render_tag_(.*)/)) {
274 } else if (m = i.match(/render_att_(.*)/)) {
279 l.sort(function(a, b) {
280 return a.length > b.length ? -1 : 1;
282 var s = "^" + this.prefix + "-(eval|" + l.join("|") + "|.*)(.*)$";
283 this.reg = new RegExp(s);
285 load_xml:function(s) {
289 manque ca pour sarrisa
290 if(window.DOMParser){
292 if(!window.DOMParser){
293 var doc = Sarissa.getDomDocument();
300 var w = window,r = w.XMLHttpRequest,j;
301 if (r)r = new r(); else for (j in{"Msxml2":1,"Microsoft":1})try {
302 r = new ActiveXObject(j + ".XMLHTTP");
307 r.open("GET", s, false);
309 //if ie r.setRequestHeader("If-Modified-Since", "Sat, 1 Jan 2000 00:00:00 GMT");
314 getdomimplmentation() for try catch
315 responseXML.getImplet
317 d.preserverWhitespace=1
320 xml.preserverWhitespace=1
321 xml.loadXML(r.reponseText)
327 add_template:function(e) {
328 // TODO: keep sources so we can implement reload()
330 if (e.constructor == String) {
331 e = this.load_xml(e);
334 if (e.documentElement) {
335 ec = e.documentElement.childNodes;
336 } else if (e.childNodes) {
339 for (var i = 0; i < ec.length; i++) {
341 if (n.nodeType == 1) {
342 var name = n.getAttribute(this.prefix + "-name");
343 this.templates[name] = n;
347 render:function(name, v) {
348 if (e = this.templates[name]) {
349 return this.render_node(e, v);
351 return "template " + name + " not found";
356 if (typeof(o) == "object") {
358 r += i + " : " + this.dump(s) + "\n";
360 r = s + "{\n" + r + "}\n";
367 var r = this.dump(s);
368 $("#debug")[0].append(this.escape_text(r) + "<br/>\n");