1 if(!dojo._hasResource["dojox.dtl.tag.misc"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
2 dojo._hasResource["dojox.dtl.tag.misc"] = true;
3 dojo.provide("dojox.dtl.tag.misc");
4 dojo.require("dojox.dtl._base");
8 var ddtm = dd.tag.misc;
10 ddtm.DebugNode = dojo.extend(function(TextNode){
11 this._TextNode = TextNode;
14 render: function(context, buffer){
15 var keys = context.getKeys();
17 for(var i = 0, key; key = keys[i]; i++){
18 console.debug("DEBUG", key, ":", context[key]);
19 debug += key + ": " + dojo.toJson(context[key]) + "\n\n";
21 return new this._TextNode(debug).render(context, buffer, this);
23 unrender: function(context, buffer){
26 clone: function(buffer){
27 return new this.constructor(this._TextNode);
29 toString: function(){ return "ddtm.DebugNode"; }
32 ddtm.FilterNode = dojo.extend(function(varnode, nodelist){
33 this._varnode = varnode;
34 this._nodelist = nodelist;
37 render: function(context, buffer){
38 // Doing this in HTML requires a different buffer with a fake root node
39 var output = this._nodelist.render(context, new dojox.string.Builder());
40 context.update({ "var": output.toString() });
41 var filtered = this._varnode.render(context, buffer);
45 unrender: function(context, buffer){
48 clone: function(buffer){
49 return new this.constructor(this._expression, this._nodelist.clone(buffer));
53 ddtm.FirstOfNode = dojo.extend(function(vars, TextNode){
55 this.vars = dojo.map(vars, function(item){
56 return new dojox.dtl._Filter(item);
58 this.contents = new TextNode("");
61 render: function(context, buffer){
62 for(var i = 0, item; item = this.vars[i]; i++){
63 var resolved = item.resolve(context);
64 if(typeof resolved != "undefined"){
65 if(resolved === null){
68 this.contents.set(resolved);
69 return this.contents.render(context, buffer);
72 return this.contents.unrender(context, buffer);
74 unrender: function(context, buffer){
75 return this.contents.unrender(context, buffer);
77 clone: function(buffer){
78 return new this.constructor(this._vars, this.contents.constructor);
82 ddtm.SpacelessNode = dojo.extend(function(nodelist, TextNode){
83 this.nodelist = nodelist;
84 this.TextNode = TextNode;
87 render: function(context, buffer){
88 if(buffer.onAddNodeComplete){
89 // Unfortunately, we have to branch here
91 dojo.connect(buffer, "onAddNodeComplete", this, "_watch"),
92 dojo.connect(buffer, "onSetParent", this, "_watchParent")
94 buffer = this.nodelist.render(context, buffer);
95 dojo.disconnect(watch[0]);
96 dojo.disconnect(watch[1]);
99 this.contents = new this.TextNode("");
101 var value = this.nodelist.dummyRender(context);
102 this.contents.set(value.replace(/>\s+</g, '><'));
103 buffer = this.contents.render(context, buffer);
107 unrender: function(context, buffer){
108 return this.nodelist.unrender(context, buffer);
110 clone: function(buffer){
111 return new this.constructor(this.nodelist.clone(buffer));
113 _isEmpty: function(node){
114 return (node.nodeType == 3 && !node.data.match(/[^\s\n]/));
116 _watch: function(node){
117 if(this._isEmpty(node)){
119 if(node.parentNode.firstChild == node){
120 node.parentNode.removeChild(node);
123 var children = node.parentNode.childNodes;
124 if(node.nodeType == 1 && children.length > 2){
125 for(var i = 2, child; child = children[i]; i++){
126 if(children[i - 2].nodeType == 1 && this._isEmpty(children[i - 1])){
127 node.parentNode.removeChild(children[i - 1]);
134 _watchParent: function(node){
135 var children = node.childNodes;
137 while(node.childNodes.length){
138 var last = node.childNodes[node.childNodes.length - 1];
139 if(!this._isEmpty(last)){
142 node.removeChild(last);
148 ddtm.TemplateTagNode = dojo.extend(function(tag, TextNode){
150 this.contents = new TextNode("");
163 render: function(context, buffer){
164 this.contents.set(this.mapping[this.tag]);
165 return this.contents.render(context, buffer);
167 unrender: function(context, buffer){
168 return this.contents.unrender(context, buffer);
170 clone: function(buffer){
171 return new this.constructor(this.tag, this.contents.constructor);
175 ddtm.WidthRatioNode = dojo.extend(function(current, max, width, TextNode){
176 this.current = new dd._Filter(current);
177 this.max = new dd._Filter(max);
179 this.contents = new TextNode("");
182 render: function(context, buffer){
183 var current = +this.current.resolve(context);
184 var max = +this.max.resolve(context);
185 if(typeof current != "number" || typeof max != "number" || !max){
186 this.contents.set("");
188 this.contents.set("" + Math.round((current / max) * this.width));
190 return this.contents.render(context, buffer);
192 unrender: function(context, buffer){
193 return this.contents.unrender(context, buffer);
195 clone: function(buffer){
196 return new this.constructor(this.current.getExpression(), this.max.getExpression(), this.width, this.contents.constructor);
200 ddtm.WithNode = dojo.extend(function(target, alias, nodelist){
201 this.target = new dd._Filter(target);
203 this.nodelist = nodelist;
206 render: function(context, buffer){
207 var target = this.target.resolve(context);
209 context[this.alias] = target;
210 buffer = this.nodelist.render(context, buffer);
214 unrender: function(context, buffer){
217 clone: function(buffer){
218 return new this.constructor(this.target.getExpression(), this.alias, this.nodelist.clone(buffer));
223 comment: function(parser, text){
224 // summary: Ignore everything between {% comment %} and {% endcomment %}
225 parser.skipPast("endcomment");
228 debug: function(parser, text){
229 // summary: Output the current context, maybe add more stuff later.
230 return new ddtm.DebugNode(parser.getTextNodeConstructor());
232 filter: function(parser, text){
233 // summary: Filter the contents of the blog through variable filters.
234 var parts = text.split(" ", 2);
235 var varnode = new (parser.getVarNodeConstructor())("var|" + parts[1]);
236 var nodelist = parser.parse(["endfilter"]);
238 return new ddtm.FilterNode(varnode, nodelist);
240 firstof: function(parser, text){
241 var parts = dojox.dtl.text.pySplit(text).slice(1);
243 throw new Error("'firstof' statement requires at least one argument");
245 return new ddtm.FirstOfNode(parts, parser.getTextNodeConstructor());
247 spaceless: function(parser, text){
248 var nodelist = parser.parse(["endspaceless"]);
250 return new ddtm.SpacelessNode(nodelist, parser.getTextNodeConstructor());
252 templatetag: function(parser, text){
253 var parts = dd.text.pySplit(text);
254 if(parts.length != 2){
255 throw new Error("'templatetag' statement takes one argument");
258 var mapping = ddtm.TemplateTagNode.prototype.mapping;
261 for(var key in mapping){
264 throw new Error("Invalid templatetag argument: '" + tag + "'. Must be one of: " + keys.join(", "));
266 return new ddtm.TemplateTagNode(tag, parser.getTextNodeConstructor());
268 widthratio: function(parser, text){
269 var parts = dd.text.pySplit(text);
270 if(parts.length != 4){
271 throw new Error("widthratio takes three arguments");
273 var width = +parts[3];
274 if(typeof width != "number"){
275 throw new Error("widthratio final argument must be an integer");
277 return new ddtm.WidthRatioNode(parts[1], parts[2], width, parser.getTextNodeConstructor());
279 with_: function(parser, text){
280 var parts = dd.text.pySplit(text);
281 if(parts.length != 4 || parts[2] != "as"){
282 throw new Error("do_width expected format as 'with value as name'");
284 var nodelist = parser.parse(["endwith"]);
286 return new ddtm.WithNode(parts[1], parts[3], nodelist);