[ADD] web: Add extra condition branching (t-elif, t-else)
A new preprocess method is added to the template engine in order to do preprocessing/sanitization of the templates before compilation. This method can be overloaded in order to add new features such as translation, ...
This commit is contained in:
@@ -16,16 +16,27 @@
|
||||
</t>
|
||||
<result id="boolean-value-condition-missing"/>
|
||||
|
||||
<!-- TODO: activate this test when qweb.py implements t-elif
|
||||
<t t-name="boolean-value-condition-elif">
|
||||
<t t-if="color == 'black'">black pearl</t>
|
||||
<t t-elif="color == 'yellow'">yellow submarine</t>
|
||||
<t t-elif="color == 'red'">red is dead</t>
|
||||
<t t-else="">beer</t>
|
||||
</t>
|
||||
<params id="boolean-value-condition-elif">{"color": "red"}</params>
|
||||
<result id="boolean-value-condition-elif">red is dead</result>
|
||||
-->
|
||||
|
||||
<t t-name="boolean-value-condition-else">
|
||||
<div><span>begin</span><t t-if="condition">ok</t>
|
||||
<t t-else="t-else">ok-else</t><span>end</span></div>
|
||||
<t t-else="">ok-else</t><span>end</span></div>
|
||||
</t>
|
||||
<params id="boolean-value-condition-else">{"condition": true}</params>
|
||||
<result id="boolean-value-condition-else"><![CDATA[<div><span>begin</span>ok<span>end</span></div>]]></result>
|
||||
|
||||
<t t-name="boolean-value-condition-false-else">
|
||||
<div><span>begin</span><t t-if="condition">fail</t>
|
||||
<t t-else="t-else">fail-else</t><span>end</span></div>
|
||||
<t t-else="">fail-else</t><span>end</span></div>
|
||||
</t>
|
||||
<params id="boolean-value-condition-false-else">{"condition": false}</params>
|
||||
<result id="boolean-value-condition-false-else"><![CDATA[<div><span>begin</span>fail-else<span>end</span></div>]]></result>
|
||||
|
||||
@@ -28,7 +28,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
var QWeb2 = {
|
||||
expressions_cache: { },
|
||||
RESERVED_WORDS: 'true,false,NaN,null,undefined,debugger,console,window,in,instanceof,new,function,return,this,typeof,eval,void,Math,RegExp,Array,Object,Date'.split(','),
|
||||
ACTIONS_PRECEDENCE: 'foreach,if,call,set,esc,raw,js,debug,log'.split(','),
|
||||
ACTIONS_PRECEDENCE: 'foreach,if,elif,else,call,set,esc,raw,js,debug,log'.split(','),
|
||||
WORD_REPLACEMENT: {
|
||||
'and': '&&',
|
||||
'or': '||',
|
||||
@@ -112,6 +112,15 @@ var QWeb2 = {
|
||||
}
|
||||
return -1;
|
||||
},
|
||||
get_element_sibling: function(node, dom_attr) {
|
||||
// This helper keeps support for IE8 which does not
|
||||
// implement DOMNode.(previous|next)ElementSibling
|
||||
var sibling = node[dom_attr];
|
||||
while (sibling && sibling.nodeType !== 1) {
|
||||
sibling = sibling[dom_attr];
|
||||
}
|
||||
return sibling;
|
||||
},
|
||||
xml_node_to_string : function(node, childs_only) {
|
||||
if (childs_only) {
|
||||
var childs = node.childNodes, r = [];
|
||||
@@ -242,13 +251,11 @@ QWeb2.Engine = (function() {
|
||||
self.add_template(xDoc, callback);
|
||||
});
|
||||
}
|
||||
template = this.preprocess(template);
|
||||
var ec = (template.documentElement && template.documentElement.childNodes) || template.childNodes || [];
|
||||
for (var i = 0; i < ec.length; i++) {
|
||||
var node = ec[i];
|
||||
if (node.nodeType === 1) {
|
||||
if (node.nodeName == 'parsererror') {
|
||||
return this.tools.exception(node.innerText);
|
||||
}
|
||||
var name = node.getAttribute(this.prefix + '-name');
|
||||
var extend = node.getAttribute(this.prefix + '-extend');
|
||||
if (name && extend) {
|
||||
@@ -278,6 +285,56 @@ QWeb2.Engine = (function() {
|
||||
}
|
||||
return true;
|
||||
},
|
||||
preprocess: function(doc) {
|
||||
/**
|
||||
* Preprocess a template's document at load time.
|
||||
* This method is mostly used for template sanitization but could
|
||||
* also be overloaded for extended features such as translations, ...
|
||||
* Throws an exception if a template is invalid.
|
||||
*
|
||||
* @param {Document} doc Document containg the loaded templates
|
||||
* @return {Document} Returns the pre-processed/sanitized template
|
||||
*/
|
||||
var self = this;
|
||||
var childs = (doc.documentElement && doc.documentElement.childNodes) || doc.childNodes || [];
|
||||
|
||||
// Check for load errors
|
||||
for (var i = 0; i < childs.length; i++) {
|
||||
var node = childs[i];
|
||||
if (node.nodeType === 1 && node.nodeName == 'parsererror') {
|
||||
return this.tools.exception(node.innerText);
|
||||
}
|
||||
}
|
||||
|
||||
// Sanitize t-elif and t-else directives
|
||||
var tbranch = doc.querySelectorAll('[t-elif], [t-else]');
|
||||
for (var i = 0, ilen = tbranch.length; i < ilen; i++) {
|
||||
var node = tbranch[i];
|
||||
var prev_elem = self.tools.get_element_sibling(node, 'previousSibling');
|
||||
var pattr = function(name) { return prev_elem.getAttribute(name); }
|
||||
var nattr = function(name) { return +!!node.getAttribute(name); }
|
||||
if (prev_elem && (pattr('t-if') || pattr('t-elif'))) {
|
||||
if (pattr('t-foreach')) {
|
||||
return self.tools.exception("Error: t-if cannot stay at the same level as t-foreach when using t-elif or t-else");
|
||||
}
|
||||
if (['t-if', 't-elif', 't-else'].map(nattr).reduce(function(a, b) { return a + b; }) > 1) {
|
||||
return self.tools.exception("Error: only one conditional branching directive is allowed per node");
|
||||
}
|
||||
// All text nodes between branch nodes are removed
|
||||
var text_node;
|
||||
while ((text_node = node.previousSibling) !== prev_elem) {
|
||||
if (self.tools.trim(text_node.nodeValue)) {
|
||||
return self.tools.exception("Error: text is not allowed between branching directives");
|
||||
}
|
||||
text_node.remove();
|
||||
}
|
||||
} else {
|
||||
return self.tools.exception("Error: t-elif and t-else directives must be preceded by a t-if or t-elif directive");
|
||||
}
|
||||
}
|
||||
|
||||
return doc;
|
||||
},
|
||||
load_xml : function(s, callback) {
|
||||
var self = this;
|
||||
var async = !!callback;
|
||||
@@ -704,6 +761,16 @@ QWeb2.Element = (function() {
|
||||
this.bottom("}");
|
||||
this.indent();
|
||||
},
|
||||
compile_action_elif : function(value) {
|
||||
this.top("else if (" + (this.format_expression(value)) + ") {");
|
||||
this.bottom("}");
|
||||
this.indent();
|
||||
},
|
||||
compile_action_else : function(value) {
|
||||
this.top("else {");
|
||||
this.bottom("}");
|
||||
this.indent();
|
||||
},
|
||||
compile_action_foreach : function(value) {
|
||||
var as = this.actions['as'] || value.replace(/[^a-zA-Z0-9]/g, '_');
|
||||
//TODO: exception if t-as not valid
|
||||
|
||||
@@ -95,6 +95,16 @@ not have to be ``<t>``::
|
||||
|
||||
will give the same results as the previous example.
|
||||
|
||||
Extra conditional branching directives ``t-elif`` and ``t-else`` are also
|
||||
available::
|
||||
|
||||
<div>
|
||||
<p t-if="user.birthday == today()">Happy bithday!</p>
|
||||
<p t-elif="user.login == 'root'">Welcome master!</p>
|
||||
<p t-else="">Welcome!</p>
|
||||
</div>
|
||||
|
||||
|
||||
.. _reference/qweb/loops:
|
||||
|
||||
loops
|
||||
|
||||
Reference in New Issue
Block a user