Subversion Repositories Applications.papyrus

Compare Revisions

Regard whitespace Rev 2149 → Rev 2150

/trunk/api/js/dojo1.0/dojox/dtl/tag/html.js
New file
0,0 → 1,136
if(!dojo._hasResource["dojox.dtl.tag.html"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
dojo._hasResource["dojox.dtl.tag.html"] = true;
dojo.provide("dojox.dtl.tag.html");
 
dojo.require("dojox.dtl._base");
 
dojox.dtl.tag.html.HtmlNode = function(name){
this.contents = new dojox.dtl.Filter(name);
this._div = document.createElement("div");
this._lasts = [];
}
dojo.extend(dojox.dtl.tag.html.HtmlNode, {
render: function(context, buffer){
var text = this.contents.resolve(context);
text = text.replace(/<(\/?script)/ig, '&lt;$1').replace(/\bon[a-z]+\s*=/ig, '');
if(this._rendered && this._last != text){
buffer = this.unrender(context, buffer);
}
this._last = text;
 
// This can get reset in the above tag
if(!this._rendered){
this._rendered = true;
var div = this._div;
div.innerHTML = text;
var children = div.childNodes;
while(children.length){
var removed = div.removeChild(children[0]);
this._lasts.push(removed);
buffer = buffer.concat(removed);
}
}
 
return buffer;
},
unrender: function(context, buffer){
if(this._rendered){
this._rendered = false;
this._last = "";
for(var i = 0, node; node = this._lasts[i++];){
buffer = buffer.remove(node);
dojo._destroyElement(node);
}
this._lasts = [];
}
return buffer;
},
clone: function(buffer){
return new dojox.dtl.tag.html.HtmlNode(this.contents.contents);
},
toString: function(){ return "dojox.dtl.tag.html.HtmlNode"; }
});
 
dojox.dtl.tag.html.StyleNode = function(styles){
this.contents = {};
this._styles = styles;
for(var key in styles){
this.contents[key] = new dojox.dtl.Template(styles[key]);
}
}
dojo.extend(dojox.dtl.tag.html.StyleNode, {
render: function(context, buffer){
for(var key in this.contents){
dojo.style(buffer.getParent(), key, this.contents[key].render(context));
}
return buffer;
},
unrender: function(context, buffer){
return buffer;
},
clone: function(buffer){
return new dojox.dtl.tag.html.HtmlNode(this._styles);
},
toString: function(){ return "dojox.dtl.tag.html.StyleNode"; }
});
 
dojox.dtl.tag.html.AttachNode = function(key){
this.contents = key;
}
dojo.extend(dojox.dtl.tag.html.AttachNode, {
render: function(context, buffer){
if(!this._rendered){
this._rendered = true;
context.getThis()[this.contents] = buffer.getParent();
}
return buffer;
},
unrender: function(context, buffer){
if(this._rendered){
this._rendered = false;
if(context.getThis()[this.contents] === buffer.getParent()){
delete context.getThis()[this.contents];
}
}
return buffer;
},
clone: function(buffer){
return new dojox.dtl.tag.html.HtmlNode(this._styles);
},
toString: function(){ return "dojox.dtl.tag.html.AttachNode"; }
});
 
dojox.dtl.tag.html.html = function(parser, text){
var parts = text.split(" ", 2);
return new dojox.dtl.tag.html.HtmlNode(parts[1]);
}
 
dojox.dtl.tag.html.tstyle = function(parser, text){
var styles = {};
text = text.replace(dojox.dtl.tag.html.tstyle._re, "");
var rules = text.split(dojox.dtl.tag.html.tstyle._re1);
for(var i = 0, rule; rule = rules[i]; i++){
var parts = rule.split(dojox.dtl.tag.html.tstyle._re2);
var key = parts[0];
var value = parts[1];
if(value.indexOf("{{") == 0){
styles[key] = value;
}
}
return new dojox.dtl.tag.html.StyleNode(styles);
}
dojo.mixin(dojox.dtl.tag.html.tstyle, {
_re: /^tstyle\s+/,
_re1: /\s*;\s*/g,
_re2: /\s*:\s*/g
});
 
dojox.dtl.tag.html.attach = function(parser, text){
var parts = text.split(dojox.dtl.tag.html.attach._re);
return new dojox.dtl.tag.html.AttachNode(parts[1]);
}
dojo.mixin(dojox.dtl.tag.html.attach, {
_re: /\s+/g
})
 
}
/trunk/api/js/dojo1.0/dojox/dtl/tag/loader.js
New file
0,0 → 1,146
if(!dojo._hasResource["dojox.dtl.tag.loader"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
dojo._hasResource["dojox.dtl.tag.loader"] = true;
dojo.provide("dojox.dtl.tag.loader");
 
dojo.require("dojox.dtl._base");
 
dojox.dtl.tag.loader.BlockNode = function(name, nodelist){
this.name = name;
this.nodelist = nodelist; // Can be overridden
}
dojo.extend(dojox.dtl.tag.loader.BlockNode, {
render: function(context, buffer){
if(this.override){
buffer = this.override.render(context, buffer, this);
this.rendered = this.override;
}else{
buffer = this.nodelist.render(context, buffer, this);
this.rendered = this.nodelist;
}
this.override = null;
return buffer;
},
unrender: function(context, buffer){
return this.rendered.unrender(context, buffer);
},
setOverride: function(nodelist){
// summary: In a shared parent, we override, not overwrite
if(!this.override){
this.override = nodelist;
}
},
toString: function(){ return "dojox.dtl.tag.loader.BlockNode"; }
});
dojox.dtl.tag.loader.block = function(parser, text){
var parts = text.split(" ");
var name = parts[1];
parser._blocks = parser._blocks || {};
parser._blocks[name] = parser._blocks[name] || [];
parser._blocks[name].push(name);
var nodelist = parser.parse(["endblock", "endblock " + name]);
parser.next();
return new dojox.dtl.tag.loader.BlockNode(name, nodelist);
}
 
dojox.dtl.tag.loader.ExtendsNode = function(getTemplate, nodelist, shared, parent, key){
this.getTemplate = getTemplate;
this.nodelist = nodelist;
this.shared = shared;
this.parent = parent;
this.key = key;
}
dojo.extend(dojox.dtl.tag.loader.ExtendsNode, {
parents: {},
getParent: function(context){
if(!this.parent){
this.parent = context.get(this.key, false);
if(!this.parent){
throw new Error("extends tag used a variable that did not resolve");
}
if(typeof this.parent == "object"){
if(this.parent.url){
if(this.parent.shared){
this.shared = true;
}
this.parent = this.parent.url.toString();
}else{
this.parent = this.parent.toString();
}
}
if(this.parent && this.parent.indexOf("shared:") == 0){
this.shared = true;
this.parent = this.parent.substring(7, parent.length);
}
}
var parent = this.parent;
if(!parent){
throw new Error("Invalid template name in 'extends' tag.");
}
if(parent.render){
return parent;
}
if(this.parents[parent]){
return this.parents[parent];
}
this.parent = this.getTemplate(dojox.dtl.text.getTemplateString(parent));
if(this.shared){
this.parents[parent] = this.parent;
}
return this.parent;
},
render: function(context, buffer){
var st = dojox.dtl;
var stbl = dojox.dtl.tag.loader;
var parent = this.getParent(context);
var isChild = parent.nodelist[0] instanceof this.constructor;
var parentBlocks = {};
for(var i = 0, node; node = parent.nodelist.contents[i]; i++){
if(node instanceof stbl.BlockNode){
parentBlocks[node.name] = node;
}
}
for(var i = 0, node; node = this.nodelist.contents[i]; i++){
if(node instanceof stbl.BlockNode){
var block = parentBlocks[node.name];
if(!block){
if(isChild){
parent.nodelist[0].nodelist.append(node);
}
}else{
if(this.shared){
block.setOverride(node.nodelist);
}else{
block.nodelist = node.nodelist;
}
}
}
}
this.rendered = parent;
return parent.render(context, buffer, this);
},
unrender: function(context, buffer){
return this.rendered.unrender(context, buffer, this);
},
toString: function(){ return "dojox.dtl.block.ExtendsNode"; }
});
dojox.dtl.tag.loader.extends_ = function(parser, text){
var parts = text.split(" ");
var shared = false;
var parent = null;
var key = null;
if(parts[1].charAt(0) == '"' || parts[1].charAt(0) == "'"){
parent = parts[1].substring(1, parts[1].length - 1);
}else{
key = parts[1];
}
if(parent && parent.indexOf("shared:") == 0){
shared = true;
parent = parent.substring(7, parent.length);
}
var nodelist = parser.parse();
return new dojox.dtl.tag.loader.ExtendsNode(parser.getTemplate, nodelist, shared, parent, key);
}
 
}
/trunk/api/js/dojo1.0/dojox/dtl/tag/loop.js
New file
0,0 → 1,89
if(!dojo._hasResource["dojox.dtl.tag.loop"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
dojo._hasResource["dojox.dtl.tag.loop"] = true;
dojo.provide("dojox.dtl.tag.loop");
 
dojo.require("dojox.dtl._base");
 
dojox.dtl.tag.loop.CycleNode = function(cyclevars, name, VarNode){
this._cyclevars = cyclevars;
this._counter = -1
this._name = name;
this._map = {};
this._VarNode = VarNode;
}
dojo.extend(dojox.dtl.tag.loop.CycleNode, {
render: function(context, buffer){
if(context.forloop && !context.forloop.counter0){
this._counter = -1;
}
 
++this._counter;
var value = this._cyclevars[this._counter % this._cyclevars.length];
if(this._name){
context[this._name] = value;
}
if(!this._map[value]){
this._map[value] = {};
}
var node = this._map[value][this._counter] = new this._VarNode(value);
 
return node.render(context, buffer, this);
},
unrender: function(context, buffer){
return buffer;
},
clone: function(){
return new this.constructor(this._cyclevars, this._name);
},
_onEnd: function(){
this._counter = -1;
},
toString: function(){ return "dojox.dtl.tag.loop.CycleNode"; }
});
 
dojox.dtl.tag.loop.cycle = function(parser, text){
// summary: Cycle among the given strings each time this tag is encountered
var args = text.split(" ");
 
if(args.length < 2){
throw new Error("'cycle' tag requires at least two arguments");
}
 
if(args[1].indexOf(",") != -1){
var vars = args[1].split(",");
args = [args[0]];
for(var i = 0; i < vars.length; i++){
args.push('"' + vars[i] + '"');
}
}
 
if(args.length == 2){
var name = args[args.length - 1];
 
if(!parser._namedCycleNodes){
throw new Error("No named cycles in template: '" + name + "' is not defined");
}
if(!parser._namedCycleNodes[name]){
throw new Error("Named cycle '" + name + "' does not exist");
}
 
return parser._namedCycleNodes[name];
}
 
if(args.length > 4 && args[args.length - 2] == "as"){
var name = args[args.length - 1];
 
var node = new dojox.dtl.tag.loop.CycleNode(args.slice(1, args.length - 2), name, parser.getVarNode());
 
if(!parser._namedCycleNodes){
parser._namedCycleNodes = {};
}
parser._namedCycleNodes[name] = node;
}else{
node = new dojox.dtl.tag.loop.CycleNode(args.slice(1), null, parser.getVarNode());
}
 
return node;
}
 
}
/trunk/api/js/dojo1.0/dojox/dtl/tag/misc.js
New file
0,0 → 1,76
if(!dojo._hasResource["dojox.dtl.tag.misc"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
dojo._hasResource["dojox.dtl.tag.misc"] = true;
dojo.provide("dojox.dtl.tag.misc");
 
dojo.require("dojox.dtl._base");
 
dojox.dtl.tag.misc.commentNode = new function(){
this.render = this.unrender = function(context, buffer){ return buffer; };
this.clone = function(){ return this; };
this.toString = function(){ return "dojox.dtl.tag.misc.CommentNode"; };
}
 
dojox.dtl.tag.misc.DebugNode = function(TextNode){
this._TextNode = TextNode;
}
dojo.extend(dojox.dtl.tag.misc.DebugNode, {
render: function(context, buffer){
var keys = context.getKeys();
var debug = "";
for(var i = 0, key; key = keys[i]; i++){
console.debug("DEBUG", key, ":", context[key]);
debug += key + ": " + dojo.toJson(context[key]) + "\n\n";
}
return new this._TextNode(debug).render(context, buffer, this);
},
unrender: function(context, buffer){
return buffer;
},
clone: function(buffer){
return new this.constructor(this._TextNode);
},
toString: function(){ return "dojox.dtl.tag.misc.DebugNode"; }
});
 
dojox.dtl.tag.misc.FilterNode = function(varnode, nodelist){
this._varnode = varnode;
this._nodelist = nodelist;
}
dojo.extend(dojox.dtl.tag.misc.FilterNode, {
render: function(context, buffer){
// Doing this in HTML requires a different buffer with a fake root node
var output = this._nodelist.render(context, new dojox.string.Builder());
context.update({ "var": output.toString() });
var filtered = this._varnode.render(context, buffer);
context.pop();
return buffer;
},
unrender: function(context, buffer){
return buffer;
},
clone: function(buffer){
return new this.constructor(this._expression, this._nodelist.clone(buffer));
}
});
 
dojox.dtl.tag.misc.comment = function(parser, text){
// summary: Ignore everything between {% comment %} and {% endcomment %}
parser.skipPast("endcomment");
return dojox.dtl.tag.misc.commentNode;
}
 
dojox.dtl.tag.misc.debug = function(parser, text){
// summary: Output the current context, maybe add more stuff later.
return new dojox.dtl.tag.misc.DebugNode(parser.getTextNode());
}
 
dojox.dtl.tag.misc.filter = function(parser, text){
// summary: Filter the contents of the blog through variable filters.
var parts = text.split(" ", 2);
var varnode = new (parser.getVarNode())("var|" + parts[1]);
var nodelist = parser.parse(["endfilter"]);
parser.next();
return new dojox.dtl.tag.misc.FilterNode(varnode, nodelist);
}
 
}
/trunk/api/js/dojo1.0/dojox/dtl/tag/logic.js
New file
0,0 → 1,164
if(!dojo._hasResource["dojox.dtl.tag.logic"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
dojo._hasResource["dojox.dtl.tag.logic"] = true;
dojo.provide("dojox.dtl.tag.logic");
 
dojo.require("dojox.dtl._base");
 
dojox.dtl.tag.logic.IfNode = function(bools, trues, falses, type){
this.bools = bools;
this.trues = trues;
this.falses = falses;
this.type = type;
}
dojo.extend(dojox.dtl.tag.logic.IfNode, {
render: function(context, buffer){
if(this.type == "or"){
for(var i = 0, bool; bool = this.bools[i]; i++){
var ifnot = bool[0];
var filter = bool[1];
var value = filter.resolve(context);
if((value && !ifnot) || (ifnot && !value)){
if(this.falses){
buffer = this.falses.unrender(context, buffer);
}
return this.trues.render(context, buffer, this);
}
buffer = this.trues.unrender(context, buffer);
if(this.falses) return this.falses.render(context, buffer, this);
}
}else{
for(var i = 0, bool; bool = this.bools[i]; i++){
var ifnot = bool[0];
var filter = bool[1];
var value = filter.resolve(context);
if(!((value && !ifnot) || (ifnot && !value))){
if(this.trues){
buffer = this.trues.unrender(context, buffer);
}
return this.falses.render(context, buffer, this);
}
buffer = this.falses.unrender(context, buffer);
if(this.falses) return this.trues.render(context, buffer, this);
}
}
return buffer;
},
unrender: function(context, buffer){
if(this.trues) buffer = this.trues.unrender(context, buffer);
if(this.falses) buffer = this.falses.unrender(context, buffer);
return buffer;
},
clone: function(buffer){
var trues = this.trues;
var falses = this.falses;
if(trues){
trues = trues.clone(buffer);
}
if(falses){
falses = falses.clone(buffer);
}
return new this.constructor(this.bools, trues, falses, this.type);
},
toString: function(){ return "dojox.dtl.tag.logic.IfNode"; }
});
 
dojox.dtl.tag.logic.ForNode = function(assign, loop, reversed, nodelist){
this.assign = assign;
this.loop = loop;
this.reversed = reversed;
this.nodelist = nodelist;
this.pool = [];
}
dojo.extend(dojox.dtl.tag.logic.ForNode, {
render: function(context, buffer){
var parentloop = {};
if(context.forloop){
parentloop = context.forloop;
}
var items = dojox.dtl.resolveVariable(this.loop, context);
context.push();
for(var i = items.length; i < this.pool.length; i++){
this.pool[i].unrender(context, buffer);
}
if(this.reversed){
items = items.reversed();
}
var j = 0;
for(var i in items){
var item = items[i];
context.forloop = {
key: i,
counter0: j,
counter: j + 1,
revcounter0: items.length - j - 1,
revcounter: items.length - j,
first: j == 0,
parentloop: parentloop
};
context[this.assign] = item;
if(j + 1 > this.pool.length){
this.pool.push(this.nodelist.clone(buffer));
}
buffer = this.pool[j].render(context, buffer, this);
++j;
}
context.pop();
return buffer;
},
unrender: function(context, buffer){
for(var i = 0, pool; pool = this.pool[i]; i++){
buffer = pool.unrender(context, buffer);
}
return buffer;
},
clone: function(buffer){
return new this.constructor(this.assign, this.loop, this.reversed, this.nodelist.clone(buffer));
},
toString: function(){ return "dojox.dtl.tag.logic.ForNode"; }
});
 
dojox.dtl.tag.logic.if_ = function(parser, text){
var parts = text.split(/\s+/g);
var type;
var bools = [];
parts.shift();
text = parts.join(" ");
parts = text.split(" and ");
if(parts.length == 1){
type = "or";
parts = text.split(" or ");
}else{
type = "and";
for(var i = 0; i < parts.length; i++){
if(parts[i] == "or"){
throw new Error("'if' tags can't mix 'and' and 'or'");
}
}
}
for(var i = 0, part; part = parts[i]; i++){
var not = false;
if(part.indexOf("not ") == 0){
part = part.substring(4);
not = true;
}
bools.push([not, new dojox.dtl.Filter(part)]);
}
var trues = parser.parse(["else", "endif"]);
var falses = false;
var token = parser.next();
if(token.text == "else"){
var falses = parser.parse(["endif"]);
parser.next();
}
return new dojox.dtl.tag.logic.IfNode(bools, trues, falses, type);
}
 
dojox.dtl.tag.logic.for_ = function(parser, text){
var parts = text.split(/\s+/g);
var reversed = parts.length == 5;
var nodelist = parser.parse(["endfor"]);
parser.next();
return new dojox.dtl.tag.logic.ForNode(parts[1], parts[3], reversed, nodelist);
}
 
}
/trunk/api/js/dojo1.0/dojox/dtl/tag/event.js
New file
0,0 → 1,42
if(!dojo._hasResource["dojox.dtl.tag.event"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
dojo._hasResource["dojox.dtl.tag.event"] = true;
dojo.provide("dojox.dtl.tag.event");
 
dojo.require("dojox.dtl._base");
 
dojox.dtl.tag.event.EventNode = function(type, fn){
this._type = type;
this.contents = fn;
}
dojo.extend(dojox.dtl.tag.event.EventNode, {
render: function(context, buffer){
if(!this._clear){
buffer.getParent()[this._type] = null;
this._clear = true;
}
if(this.contents && !this._rendered){
if(!context.getThis()) throw new Error("You must use Context.setObject(instance)");
this._rendered = dojo.connect(buffer.getParent(), this._type, context.getThis(), this.contents);
}
return buffer;
},
unrender: function(context, buffer){
if(this._rendered){
dojo.disconnect(this._rendered);
this._rendered = false;
}
return buffer;
},
clone: function(){
return new dojox.dtl.tag.event.EventNode(this._type, this.contents);
},
toString: function(){ return "dojox.dtl.tag.event." + this._type; }
});
 
dojox.dtl.tag.event.on = function(parser, text){
// summary: Associates an event type to a function (on the current widget) by name
var parts = text.split(" ");
return new dojox.dtl.tag.event.EventNode(parts[0], parts[1]);
}
 
}
/trunk/api/js/dojo1.0/dojox/dtl/README
New file
0,0 → 1,203
-------------------------------------------------------------------------------
DojoX Django Template Language
-------------------------------------------------------------------------------
Version 0.0
Release date: 09/20/2007
-------------------------------------------------------------------------------
Project state: experimental/feature incomplete
-------------------------------------------------------------------------------
Project authors
Neil Roberts (pottedmeat@dojotoolkit.org)
-------------------------------------------------------------------------------
Project description
 
The Django Template language uses a system of templates that can be compiled
once and rendered indefinitely afterwards. It uses a simple system of tags
and filters.
 
This aims to be a 1:1 match with the Django Template Language as outlined in
http://www.djangoproject.com/documentation/templates/. Many common tags and
filters have been implemented (see below), along with new filters and tags as
necessary (see below).
 
The Django Template Language is intended within Django to only handle text.
Our implementation is able to handle HTML in addition to text. Actually, the
text and HTML portions of dojox.dtl are two separate layers, the HTML layer
sits on top of the text layer (base). It's also been implemented in such a way
that you have little to fear when moving your code from Django to dojox.dtl.
Your existing templates should work, and will benefit from the massive
performance gain of being able to manipulate nodes, rather than having to do
clunky innerHTML swaps you would have to do with a text-only system. It also
allows for new HTML-centric abilities, outlined below.
 
Despite having two levels of complexity, if you write your tags correctly, they
will work in both environments.
-------------------------------------------------------------------------------
Dependencies
 
Base:
dojox.string.Builder
 
Date filters and tags:
dojox.date.php
 
Widget:
dijit._Widget
dijit._Container
-------------------------------------------------------------------------------
Installation instructions
 
Grab the following from the Dojo SVN Repository:
http://svn.dojotoolkit.org/var/src/dojo/dojox/trunk/dtl.js
http://svn.dojotoolkit.org/var/src/dojo/dojox/trunk/dtl/*
 
Install into the following directory structure:
/dojox/dtl/
 
...which should be at the same level as your Dojo checkout.
-------------------------------------------------------------------------------
What's Been Done
 
| Implemented | Tag | Text Unit Test | HTML Unit Test |
| X | block | X | |
| X | comment | X | |
| X | cycle | X | |
| X | debug | X | |
| X | extends | X | |
| X | filter | X | |
| | firstof | | |
| X | for | | |
| X | if | | |
| | ifchanged | | |
| | ifequal | | |
| | ifnotequal | | |
| | include | | |
| | load | | |
| | now | | |
| | regroup | | |
| | spaceless | | |
| | ssi | | |
| | templatetag | | |
| | url | | |
| | widthratio | | |
| | with | | |
 
| Implemented | Filter | Text Unit Test | HTML Unit Test |
| X | add | X | |
| X | addslashes | X | |
| X | capfirst | X | |
| X | center | X | |
| X | cut | X | |
| X | date | X | |
| X | default | X | |
| X | default_if_none | X | |
| X | dictsort | X | |
| X | dictsort_reversed | X | |
| X | divisibleby | X | |
| X | escape | X | |
| X | filesizeformat | X | |
| X | first | X | |
| X | fix_ampersands | X | |
| X | floatformat | X | |
| X | get_digit | X | |
| X | iriencode | X | |
| X | join | X | |
| X | length | X | |
| X | length_is | X | |
| X | linebreaks | X | |
| X | linebreaksbr | X | |
| X | linenumbers | X | |
| X | ljust | X | |
| X | lower | X | |
| X | make_list | X | |
| X | phone2numeric | X | |
| X | pluralize | X | |
| X | pprint | X | |
| X | random | X | |
| X | removetags | X | |
| X | rjust | X | |
| X | slice | X | |
| X | slugify | X | |
| X | stringformat | X | |
| X | striptags | X | |
| X | time | X | |
| X | timesince | X | |
| X | timeuntil | X | |
| X | title | X | |
| X | truncatewords | X | |
| X | truncatewords_html | X | |
| X | unordered_list | X | |
| X | upper | X | |
| X | urlencode | X | |
| X | urlize | X | |
| X | urlizetrunc | X | |
| X | wordcount | X | |
| X | wordwrap | X | |
| X | yesno | X | |
-------------------------------------------------------------------------------
HTML-Specific Additions
-------------------------------------------------------------------------------
{%extends "shared:templates/template.html" %}
 
When using the {% extends %} tag, we don't always want to replace the parent
node in DOM. For example, if we have a list view and a detail view, but both
share the same base template, we want it to share the parent template. This
basically means that the same nodes will be used in the parent for both views.
 
To use this, simply add "shared:" to the beginning of the specified template.
-------------------------------------------------------------------------------
<!--{% commented markup %}-->
 
Some browsers treat comment nodes as full fledged nodes. If performance is
important to you, you can wrap your markup in comments. The comments will be
automatically stripped for browsers that cannot support this.
-------------------------------------------------------------------------------
Attribute Tags
 
If a tag name begins with "attr:" then it will be able to inject an object
into the parsed template. (See dojox.dtl.tag.event.EventNode)
 
onclick/onmouseover/etc attributes work by attaching to the rendering object.
 
tstyle attribute allows for styles to be changed dynamically. Use them just
like a "style" attribute.
 
attach attribute attaches the node to the rendering object.
-------------------------------------------------------------------------------
New Context Functions
 
setThis() and getThis() returns the object "in charge" of the current rendering.
This is used so that we can attach events.
 
mixin() and filter() clone the current context, and either add to or reduce
the keys in the context.
-------------------------------------------------------------------------------
Buffers
 
Both the base and HTML versions of dojox.dtl use buffers. The base version uses
dojox.string.Builder and the HTML version uses dojox.dtl.HtmlBuffer.
 
The HTML buffer has several calls important to rendering:
 
setParent/getParent/concat/remove:
 
setParent and concat are used in order to render our HTML. As we move through
the parsed template, different nodes change the parent or add on to the
current parent. getParent is useful in things like the attribute tags, since
they can use getParent to find the node that they're an attribute on. remove is
used during unrendering.
 
setAttribute:
 
Sets an attribute on the current parent
-------------------------------------------------------------------------------
Tags Need clone/unrender Functions.
 
One of the biggest challenges of getting dojox.dtl to work in an HTML
environment was logic blocks. Nodes and objects inside a for loop need to be
cloned, they can't simply be re-rendered, especially if they involve a Node.
Also, in the case of an if/else block, we need to be able to not just render
one of the blocks, but also unrender the second.
 
This is really simple code, a good example is the dojox.dtl.HtmlNode
object. Each function in this object is only one line long.
/trunk/api/js/dojo1.0/dojox/dtl/widget.js
New file
0,0 → 1,48
if(!dojo._hasResource["dojox.dtl.widget"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
dojo._hasResource["dojox.dtl.widget"] = true;
dojo.provide("dojox.dtl.widget");
 
dojo.require("dijit._Widget");
dojo.require("dijit._Container")
dojo.require("dojox.dtl.html");
dojo.require("dojox.dtl.render.html");
 
dojo.declare("dojox.dtl._Widget", [dijit._Widget, dijit._Contained],
{
buffer: 0,
buildRendering: function(){
this.domNode = this.srcNodeRef;
 
if(this.domNode){
var parent = this.getParent();
if(parent){
this.setAttachPoint(parent);
}
}
},
setAttachPoint: function(/*dojox.dtl.AttachPoint*/ attach){
this._attach = attach;
},
render: function(/*dojox.dtl.HtmlTemplate*/ tpl, /*dojox.dtl.Context*/ context){
if(!this._attach){
throw new Error("You must use an attach point with dojox.dtl.TemplatedWidget");
}
 
context.setThis(this);
this._attach.render(tpl, context);
}
}
);
 
dojo.declare("dojox.dtl.AttachPoint", [dijit._Widget, dijit._Container],
{
constructor: function(props, node){
this._render = new dojox.dtl.render.html.Render(node);
},
render: function(/*dojox.dtl.HtmlTemplate*/ tpl, /*dojox.dtl.Context*/ context){
this._render.render(tpl, context);
}
}
);
 
}
/trunk/api/js/dojo1.0/dojox/dtl/html.js
New file
0,0 → 1,658
if(!dojo._hasResource["dojox.dtl.html"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
dojo._hasResource["dojox.dtl.html"] = true;
dojo.provide("dojox.dtl.html");
 
dojo.require("dojox.dtl._base");
 
dojox.dtl.ObjectMap = function(){
this.contents = [];
}
dojo.extend(dojox.dtl.ObjectMap, {
get: function(key){
var contents = this.contents;
for(var i = 0, content; content = contents[i]; i++){
if(content[0] === key){
return content[1];
}
}
},
put: function(key, value){
var contents = this.contents;
for(var i = 0, content; content = contents[i]; i++){
if(content[0] === key){
if(arguments.length == 1){
contents.splice(i, 1);
return;
}
content[1] = value;
return;
}
}
contents.push([key, value]);
},
toString: function(){ return "dojox.dtl.ObjectMap"; }
});
 
dojox.dtl.html = {
types: dojo.mixin({change: -11, attr: -12, elem: 1, text: 3}, dojox.dtl.text.types),
_attributes: {},
_re: /(^\s+|\s+$)/g,
_re2: /\b([a-zA-Z]+)="/g,
_re3: /<!--({({|%).*?(%|})})-->/g,
_re4: /^function anonymous\(\)\s*{\s*(.*)\s*}$/,
_trim: function(/*String*/ str){
return str.replace(this._re, "");
},
getTemplate: function(text){
if(typeof this._commentable == "undefined"){
// Check to see if the browser can handle comments
this._commentable = false;
var div = document.createElement("div");
div.innerHTML = "<!--Test comment handling, and long comments, using comments whenever possible.-->";
if(div.childNodes.length && div.childNodes[0].nodeType == 8 && div.childNodes[0].data == "comment"){
this._commentable = true;
}
}
 
if(!this._commentable){
// Strip comments
text = text.replace(this._re3, "$1");
}
 
var match;
while(match = this._re2.exec(text)){
this._attributes[match[1]] = true;
}
var div = document.createElement("div");
div.innerHTML = text;
var output = { pres: [], posts: []}
while(div.childNodes.length){
if(!output.node && div.childNodes[0].nodeType == 1){
output.node = div.removeChild(div.childNodes[0]);
}else if(!output.node){
output.pres.push(div.removeChild(div.childNodes[0]));
}else{
output.posts.push(div.removeChild(div.childNodes[0]));
}
}
 
if(!output.node){
throw new Error("Template did not provide any content");
}
 
return output;
},
tokenize: function(/*Node*/ node, /*Array?*/ tokens, /*Array?*/ preNodes, /*Array?*/ postNodes){
tokens = tokens || [];
var first = !tokens.length;
var types = this.types;
 
var children = [];
for(var i = 0, child; child = node.childNodes[i]; i++){
children.push(child);
}
 
if(preNodes){
for(var i = 0, child; child = preNodes[i]; i++){
this._tokenize(node, child, tokens);
}
}
 
tokens.push([types.elem, node]);
tokens.push([types.change, node]);
 
for(var key in this._attributes){
var value = "";
if(key == "class"){
value = node.className || value;
}else if(key == "for"){
value = node.htmlFor || value;
}else if(node.getAttribute){
value = node.getAttribute(key, 2) || value;
if(key == "href" || key == "src"){
if(dojo.isIE){
var hash = location.href.lastIndexOf(location.hash);
var href = location.href.substring(0, hash).split("/");
href.pop();
href = href.join("/") + "/";
if(value.indexOf(href) == 0){
value = value.replace(href, "");
}
value = value.replace(/%20/g, " ").replace(/%7B/g, "{").replace(/%7D/g, "}").replace(/%25/g, "%");
}
if(value.indexOf("{%") != -1 || value.indexOf("{{") != -1){
node.setAttribute(key, "");
}
}
}
if(typeof value == "function"){
value = value.toString().replace(this._re4, "$1");
}
if(typeof value == "string" && (value.indexOf("{%") != -1 || value.indexOf("{{") != -1 || (value && dojox.dtl.text.getTag("attr:" + key, true)))){
tokens.push([types.attr, node, key, value]);
}
}
 
if(!children.length){
tokens.push([types.change, node.parentNode, true]);
if(postNodes){
for(var i = 0, child; child = postNodes[i]; i++){
this._tokenize(node, child, tokens);
}
}
return tokens;
}
 
for(var i = 0, child; child = children[i]; i++){
this._tokenize(node, child, tokens);
}
 
if(node.parentNode && node.parentNode.tagName){
tokens.push([types.change, node.parentNode, true]);
node.parentNode.removeChild(node);
}
if(postNodes){
for(var i = 0, child; child = postNodes[i]; i++){
this._tokenize(node, child, tokens);
}
}
 
if(first){
tokens.push([types.change, node, true]);
}
 
return tokens;
},
_tokenize: function(parent, child, tokens){
var types = this.types;
var data = child.data;
switch(child.nodeType){
case 1:
this.tokenize(child, tokens);
break;
case 3:
if(data.match(/[^\s\n]/)){
if(data.indexOf("{{") != -1 || data.indexOf("{%") != -1){
var texts = dojox.dtl.text.tokenize(data);
for(var j = 0, text; text = texts[j]; j++){
if(typeof text == "string"){
tokens.push([types.text, text]);
}else{
tokens.push(text);
}
}
}else{
tokens.push([child.nodeType, child]);
}
}
if(child.parentNode) child.parentNode.removeChild(child);
break;
case 8:
if(data.indexOf("{%") == 0){
tokens.push([types.tag, this._trim(data.substring(2, data.length - 3))]);
}
if(data.indexOf("{{") == 0){
tokens.push([types.varr, this._trim(data.substring(2, data.length - 3))]);
}
if(child.parentNode) child.parentNode.removeChild(child);
break;
}
}
}
 
dojox.dtl.HtmlTemplate = function(/*String|dojo._Url*/ obj){
// summary: Use this object for HTML templating
var dd = dojox.dtl;
var ddh = dd.html;
 
if(!obj.node){
if(typeof obj == "object"){
obj = dojox.dtl.text.getTemplateString(obj);
}
obj = ddh.getTemplate(obj);
}
 
var tokens = ddh.tokenize(obj.node, [], obj.pres, obj.posts);
var parser = new dd.HtmlParser(tokens);
this.nodelist = parser.parse();
}
dojo.extend(dojox.dtl.HtmlTemplate, {
_count: 0,
_re: /\bdojo:([a-zA-Z0-9_]+)\b/g,
setClass: function(str){
this.getRootNode().className = str;
},
getRootNode: function(){
return this.rootNode;
},
getBuffer: function(){
return new dojox.dtl.HtmlBuffer();
},
render: function(context, buffer){
buffer = buffer || this.getBuffer();
this.rootNode = null;
var onSetParent = dojo.connect(buffer, "onSetParent", this, function(node){
if(!this.rootNode){
this.rootNode = node || true;
}
});
var output = this.nodelist.render(context || new dojox.dtl.Context({}), buffer);
dojo.disconnect(onSetParent);
buffer._flushCache();
return output;
},
unrender: function(context, buffer){
return this.nodelist.unrender(context, buffer);
},
toString: function(){ return "dojox.dtl.HtmlTemplate"; }
});
 
dojox.dtl.HtmlBuffer = function(/*Node*/ parent){
// summary: Allows the manipulation of DOM
// description:
// Use this to append a child, change the parent, or
// change the attribute of the current node.
this._parent = parent;
this._cache = [];
}
dojo.extend(dojox.dtl.HtmlBuffer, {
concat: function(/*DOMNode*/ node){
if(!this._parent) return this;
if(node.nodeType){
var caches = this._getCache(this._parent);
if(node.parentNode === this._parent){
// If we reach a node that already existed, fill in the cache for this same parent
var i = 0;
for(var i = 0, cache; cache = caches[i]; i++){
this.onAddNode(node);
this._parent.insertBefore(cache, node);
}
caches.length = 0;
}
if(!node.parentNode || !node.parentNode.tagName){
if(!this._parent.childNodes.length){
this.onAddNode(node);
this._parent.appendChild(node);
}else{
caches.push(node);
}
}
}
return this;
},
remove: function(obj){
if(typeof obj == "string"){
this._parent.removeAttribute(obj);
}else{
if(obj.parentNode === this._parent){
this.onRemoveNode();
this._parent.removeChild(obj);
}
}
return this;
},
setAttribute: function(key, value){
if(key == "class"){
this._parent.className = value;
}else if(key == "for"){
this._parent.htmlFor = value;
}else if(this._parent.setAttribute){
this._parent.setAttribute(key, value);
}
return this;
},
setParent: function(node, /*Boolean?*/ up){
if(!this._parent) this._parent = node;
var caches = this._getCache(this._parent);
if(caches && caches.length && up){
for(var i = 0, cache; cache = caches[i]; i++){
if(cache !== this._parent && (!cache.parentNode || !cache.parentNode.tagName)){
this.onAddNode(cache);
this._parent.appendChild(cache);
}
}
caches.length = 0;
}
 
this.onSetParent(node, up);
this._parent = node;
return this;
},
getParent: function(){
return this._parent;
},
onSetParent: function(){
// summary: Stub called when setParent is used.
},
onAddNode: function(){
// summary: Stub called when new nodes are added
},
onRemoveNode: function(){
// summary: Stub called when nodes are removed
},
_getCache: function(node){
for(var i = 0, cache; cache = this._cache[i]; i++){
if(cache[0] === node){
return cache[1];
}
}
var arr = [];
this._cache.push([node, arr]);
return arr;
},
_flushCache: function(node){
for(var i = 0, cache; cache = this._cache[i]; i++){
if(!cache[1].length){
this._cache.splice(i--, 1);
}
}
},
toString: function(){ return "dojox.dtl.HtmlBuffer"; }
});
 
dojox.dtl.HtmlNode = function(node){
// summary: Places a node into DOM
this.contents = node;
}
dojo.extend(dojox.dtl.HtmlNode, {
render: function(context, buffer){
return buffer.concat(this.contents);
},
unrender: function(context, buffer){
return buffer.remove(this.contents);
},
clone: function(buffer){
return new dojox.dtl.HtmlNode(this.contents);
},
toString: function(){ return "dojox.dtl.HtmlNode"; }
});
 
dojox.dtl.HtmlNodeList = function(/*Node[]*/ nodes){
// summary: A list of any HTML-specific node object
// description:
// Any object that's used in the constructor or added
// through the push function much implement the
// render, unrender, and clone functions.
this.contents = nodes || [];
}
dojo.extend(dojox.dtl.HtmlNodeList, {
parents: new dojox.dtl.ObjectMap(),
push: function(node){
this.contents.push(node);
},
unshift: function(node){
this.contents.unshift(node);
},
render: function(context, buffer, /*Node*/ instance){
if(instance){
var parent = buffer.getParent();
}
for(var i = 0; i < this.contents.length; i++){
buffer = this.contents[i].render(context, buffer);
if(!buffer) throw new Error("Template node render functions must return their buffer");
}
if(parent){
buffer.setParent(parent, true);
}
return buffer;
},
unrender: function(context, buffer){
for(var i = 0; i < this.contents.length; i++){
buffer = this.contents[i].unrender(context, buffer);
if(!buffer) throw new Error("Template node render functions must return their buffer");
}
return buffer;
},
clone: function(buffer){
// summary:
// Used to create an identical copy of a NodeList, useful for things like the for tag.
var dd = dojox.dtl;
var ddh = dd.html;
var parent = buffer.getParent();
var contents = this.contents;
var nodelist = new dd.HtmlNodeList();
var cloned = [];
for(var i = 0; i < contents.length; i++){
var clone = contents[i].clone(buffer);
if(clone instanceof dd.ChangeNode || clone instanceof dd.HtmlNode){
var item = this.parents.get(clone.contents);
if(item){
clone.contents = item;
}else if(parent !== clone.contents && clone instanceof dd.HtmlNode){
var node = clone.contents;
clone.contents = clone.contents.cloneNode(false);
cloned.push(node);
this.parents.put(node, clone.contents);
}
}
nodelist.push(clone);
}
 
for(var i = 0, clone; clone = cloned[i]; i++){
this.parents.put(clone);
}
 
return nodelist;
},
toString: function(){ return "dojox.dtl.HtmlNodeList"; }
});
 
dojox.dtl.HtmlVarNode = function(str){
// summary: A node to be processed as a variable
// description:
// Will render an object that supports the render function
// and the getRootNode function
this.contents = new dojox.dtl.Filter(str);
this._lists = {};
}
dojo.extend(dojox.dtl.HtmlVarNode, {
render: function(context, buffer){
this._rendered = true;
var dd = dojox.dtl;
var ddh = dd.html;
var str = this.contents.resolve(context);
if(str && str.render && str.getRootNode){
var root = this._curr = str.getRootNode();
var lists = this._lists;
var list = lists[root];
if(!list){
list = lists[root] = new dd.HtmlNodeList();
list.push(new dd.ChangeNode(buffer.getParent()));
list.push(new dd.HtmlNode(root));
list.push(str);
list.push(new dd.ChangeNode(buffer.getParent(), true));
}
return list.render(context, buffer);
}else{
if(!this._txt) this._txt = document.createTextNode(str);
if(this._txt.data != str) this._txt.data = str;
return buffer.concat(this._txt);
}
return buffer;
},
unrender: function(context, buffer){
if(this._rendered){
this._rendered = false;
if(this._curr){
return this._lists[this._curr].unrender(context, buffer);
}else if(this._txt){
return buffer.remove(this._txt);
}
}
return buffer;
},
clone: function(){
return new dojox.dtl.HtmlVarNode(this.contents.contents);
},
toString: function(){ return "dojox.dtl.HtmlVarNode"; }
});
 
dojox.dtl.ChangeNode = function(node, /*Boolean?*/ up){
// summary: Changes the parent during render/unrender
this.contents = node;
this._up = up;
}
dojo.extend(dojox.dtl.ChangeNode, {
render: function(context, buffer){
return buffer.setParent(this.contents, this._up);
},
unrender: function(context, buffer){
return buffer.setParent(this.contents);
},
clone: function(buffer){
return new dojox.dtl.ChangeNode(this.contents, this._up);
},
toString: function(){ return "dojox.dtl.ChangeNode"; }
});
 
dojox.dtl.AttributeNode = function(key, value){
// summary: Works on attributes
this._key = key;
this._value = value;
this._tpl = new dojox.dtl.Template(value);
this.contents = "";
}
dojo.extend(dojox.dtl.AttributeNode, {
render: function(context, buffer){
var key = this._key;
var value = this._tpl.render(context);
if(this._rendered){
if(value != this.contents){
this.contents = value;
return buffer.setAttribute(key, value);
}
}else{
this._rendered = true;
this.contents = value;
return buffer.setAttribute(key, value);
}
return buffer;
},
unrender: function(context, buffer){
if(this._rendered){
this._rendered = false;
this.contents = "";
return buffer.remove(this.contents);
}
return buffer;
},
clone: function(){
return new dojox.dtl.AttributeNode(this._key, this._value);
},
toString: function(){ return "dojox.dtl.AttributeNode"; }
});
 
dojox.dtl.HtmlTextNode = function(str){
// summary: Adds a straight text node without any processing
this.contents = document.createTextNode(str);
}
dojo.extend(dojox.dtl.HtmlTextNode, {
render: function(context, buffer){
return buffer.concat(this.contents);
},
unrender: function(context, buffer){
return buffer.remove(this.contents);
},
clone: function(){
return new dojox.dtl.HtmlTextNode(this.contents.data);
},
toString: function(){ return "dojox.dtl.HtmlTextNode"; }
});
 
dojox.dtl.HtmlParser = function(tokens){
// summary: Turn a simple array into a set of objects
// description:
// This is also used by all tags to move through
// the list of nodes.
this.contents = tokens;
}
dojo.extend(dojox.dtl.HtmlParser, {
parse: function(/*Array?*/ stop_at){
var dd = dojox.dtl;
var ddh = dd.html;
var types = ddh.types;
var terminators = {};
var tokens = this.contents;
if(!stop_at){
stop_at = [];
}
for(var i = 0; i < stop_at.length; i++){
terminators[stop_at[i]] = true;
}
var nodelist = new dd.HtmlNodeList();
while(tokens.length){
var token = tokens.shift();
var type = token[0];
var value = token[1];
if(type == types.change){
nodelist.push(new dd.ChangeNode(value, token[2]));
}else if(type == types.attr){
var fn = dojox.dtl.text.getTag("attr:" + token[2], true);
if(fn){
nodelist.push(fn(null, token[2] + " " + token[3]));
}else{
nodelist.push(new dd.AttributeNode(token[2], token[3]));
}
}else if(type == types.elem){
var fn = dojox.dtl.text.getTag("node:" + value.tagName.toLowerCase(), true);
if(fn){
// TODO: We need to move this to tokenization so that it's before the
// node and the parser can be passed here instead of null
nodelist.push(fn(null, value, value.tagName.toLowerCase()));
}
nodelist.push(new dd.HtmlNode(value));
}else if(type == types.varr){
nodelist.push(new dd.HtmlVarNode(value));
}else if(type == types.text){
nodelist.push(new dd.HtmlTextNode(value.data || value));
}else if(type == types.tag){
if(terminators[value]){
tokens.unshift(token);
return nodelist;
}
var cmd = value.split(/\s+/g);
if(cmd.length){
cmd = cmd[0];
var fn = dojox.dtl.text.getTag(cmd);
if(typeof fn != "function"){
throw new Error("Function not found for ", cmd);
}
var tpl = fn(this, value);
if(tpl){
nodelist.push(tpl);
}
}
}
}
 
if(stop_at.length){
throw new Error("Could not find closing tag(s): " + stop_at.toString());
}
 
return nodelist;
},
next: function(){
// summary: Used by tags to discover what token was found
var token = this.contents.shift();
return {type: token[0], text: token[1]};
},
skipPast: function(endtag){
return dojox.dtl.Parser.prototype.skipPast.call(this, endtag);
},
getVarNode: function(){
return dojox.dtl.HtmlVarNode;
},
getTextNode: function(){
return dojox.dtl.HtmlTextNode;
},
getTemplate: function(/*String*/ loc){
return new dojox.dtl.HtmlTemplate(dojox.dtl.html.getTemplate(loc));
},
toString: function(){ return "dojox.dtl.HtmlParser"; }
});
 
dojox.dtl.register.tag("dojox.dtl.tag.event", "dojox.dtl.tag.event", [[/(attr:)?on(click|key(up))/i, "on"]]);
dojox.dtl.register.tag("dojox.dtl.tag.html", "dojox.dtl.tag.html", ["html", "attr:attach", "attr:tstyle"]);
 
}
/trunk/api/js/dojo1.0/dojox/dtl/render/html.js
New file
0,0 → 1,70
if(!dojo._hasResource["dojox.dtl.render.html"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
dojo._hasResource["dojox.dtl.render.html"] = true;
dojo.provide("dojox.dtl.render.html");
 
dojox.dtl.render.html.sensitivity = {
// summary:
// Set conditions under which to buffer changes
// description:
// Necessary if you make a lot of changes to your template.
// What happens is that the entire node, from the attached DOM Node
// down gets swapped with a clone, and until the entire rendering
// is complete, we don't replace the clone again. In this way, renders are
// "batched".
//
// But, if we're only changing a small number of nodes, we might no want to buffer at all.
// The higher numbers mean that even small changes will result in buffering.
// Each higher level includes the lower levels.
NODE: 1, // If a node changes, implement buffering
ATTRIBUTE: 2, // If an attribute or node changes, implement buffering
TEXT: 3 // If any text at all changes, implement buffering
}
dojox.dtl.render.html.Render = function(/*DOMNode?*/ attachPoint, /*dojox.dtl.HtmlTemplate?*/ tpl){
this._tpl = tpl;
this._node = attachPoint;
this._swap = dojo.hitch(this, function(){
// summary: Swaps the node out the first time the DOM is changed
// description: Gets swapped back it at end of render
if(this._node === this._tpl.getRootNode()){
var frag = this._node;
this._node = this._node.cloneNode(true);
frag.parentNode.replaceChild(this._node, frag);
}
});
}
dojo.extend(dojox.dtl.render.html.Render, {
sensitivity: dojox.dtl.render.html.sensitivity,
setAttachPoint: function(/*Node*/ node){
this._node = node;
},
render: function(/*dojox.dtl.HtmlTemplate*/ tpl, /*Object*/ context, /*dojox.dtl.HtmlBuffer?*/ buffer){
if(!this._node){
throw new Error("You cannot use the Render object without specifying where you want to render it");
}
 
buffer = buffer || tpl.getBuffer();
 
if(context.getThis() && context.getThis().buffer == this.sensitivity.NODE){
var onAddNode = dojo.connect(buffer, "onAddNode", this, "_swap");
var onRemoveNode = dojo.connect(buffer, "onRemoveNode", this, "_swap");
}
 
if(this._tpl && this._tpl !== tpl){
this._tpl.unrender(context, buffer);
}
this._tpl = tpl;
 
var frag = tpl.render(context, buffer).getParent();
 
dojo.disconnect(onAddNode);
dojo.disconnect(onRemoveNode);
 
if(this._node !== frag){
this._node.parentNode.replaceChild(frag, this._node);
dojo._destroyElement(this._node);
this._node = frag;
}
}
});
 
}
/trunk/api/js/dojo1.0/dojox/dtl/utils/date.js
New file
0,0 → 1,67
if(!dojo._hasResource["dojox.dtl.utils.date"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
dojo._hasResource["dojox.dtl.utils.date"] = true;
dojo.provide("dojox.dtl.utils.date");
 
dojo.require("dojox.date.php");
 
dojo.mixin(dojox.dtl.utils.date, {
format: function(/*Date*/ date, /*String*/ format){
return dojox.date.php.format(date, format, dojox.dtl.utils.date._overrides);
},
timesince: function(d, now){
// summary:
// Takes two datetime objects and returns the time between then and now
// as a nicely formatted string, e.g "10 minutes"
// description:
// Adapted from http://blog.natbat.co.uk/archive/2003/Jun/14/time_since
if(!(d instanceof Date)){
d = new Date(d.year, d.month, d.day);
}
if(!now){
now = new Date();
}
 
var delta = Math.abs(now.getTime() - d.getTime());
for(var i = 0, chunk; chunk = dojox.dtl.utils.date._chunks[i]; i++){
var count = Math.floor(delta / chunk[0]);
if(count) break;
}
return count + " " + chunk[1](count);
},
_chunks: [
[60 * 60 * 24 * 365 * 1000, function(n){ return (n == 1) ? 'year' : 'years'; }],
[60 * 60 * 24 * 30 * 1000, function(n){ return (n == 1) ? 'month' : 'months'; }],
[60 * 60 * 24 * 7 * 1000, function(n){ return (n == 1) ? 'week' : 'weeks'; }],
[60 * 60 * 24 * 1000, function(n){ return (n == 1) ? 'day' : 'days'; }],
[60 * 60 * 1000, function(n){ return (n == 1) ? 'hour' : 'hours'; }],
[60 * 1000, function(n){ return (n == 1) ? 'minute' : 'minutes'; }]
],
_months_ap: ["Jan.", "Feb.", "March", "April", "May", "June", "July", "Aug.", "Sept.", "Oct.", "Nov.", "Dec."],
_overrides: {
f: function(){
// summary:
// Time, in 12-hour hours and minutes, with minutes left off if they're zero.
// description:
// Examples: '1', '1:30', '2:05', '2'
// Proprietary extension.
if(!this.date.getMinutes()) return this.g();
},
N: function(){
// summary: Month abbreviation in Associated Press style. Proprietary extension.
return dojox.dtl.utils.date._months_ap[this.date.getMonth()];
},
P: function(){
// summary:
// Time, in 12-hour hours, minutes and 'a.m.'/'p.m.', with minutes left off
// if they're zero and the strings 'midnight' and 'noon' if appropriate.
// description:
// Examples: '1 a.m.', '1:30 p.m.', 'midnight', 'noon', '12:30 p.m.'
// Proprietary extension.
if(!this.date.getMinutes() && !this.date.getHours()) return 'midnight';
if(!this.date.getMinutes() && this.date.getHours() == 12) return 'noon';
return self.f() + " " + self.a();
}
}
});
 
}
/trunk/api/js/dojo1.0/dojox/dtl/tests/context.js
New file
0,0 → 1,78
if(!dojo._hasResource["dojox.dtl.tests.context"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
dojo._hasResource["dojox.dtl.tests.context"] = true;
dojo.provide("dojox.dtl.tests.context");
 
dojo.require("dojox.dtl");
 
doh.register("dojox.dtl.context",
[
function test_context_creation(t){
var context = new dojox.dtl.Context({ foo: "foo", bar: "bar" });
t.is("foo", context.foo);
t.is("bar", context.bar);
},
function test_context_push(t){
var context = new dojox.dtl.Context({ foo: "foo", bar: "bar" });
context.push();
for(var key in context._dicts[0]){
t.t(key == "foo" || key == "bar");
}
},
function test_context_pop(t){
var context = new dojox.dtl.Context({ foo: "foo", bar: "bar" });
context.push();
t.is("undefined", typeof context.foo);
t.is("undefined", typeof context.bar);
context.pop();
t.is("foo", context.foo);
t.is("bar", context.bar);
},
function test_context_overpop(t){
var context = new dojox.dtl.Context();
try{
context.pop();
t.t(false);
}catch(e){
t.is("pop() has been called more times than push() on the Context", e.message);
}
},
function test_context_filter(t){
var context = new dojox.dtl.Context({ foo: "one", bar: "two", baz: "three" });
var filtered = context.filter("foo", "bar");
t.is(filtered.foo, "one");
t.is(filtered.bar, "two");
t.f(filtered.baz);
 
filtered = context.filter({ bar: true, baz: true });
t.f(filtered.foo);
t.is(filtered.bar, "two");
t.is(filtered.baz, "three");
 
filtered = context.filter(new dojox.dtl.Context({ foo: true, baz: true }));
t.is(filtered.foo, "one");
t.f(filtered.bar);
t.is(filtered.baz, "three");
},
function test_context_extend(t){
var context = new dojox.dtl.Context({ foo: "one" });
var extended = context.extend({ bar: "two", baz: "three" });
t.is(extended.foo, "one");
t.is(extended.bar, "two");
t.is(extended.baz, "three");
 
extended = context.extend({ barr: "two", bazz: "three" });
t.is(extended.foo, "one");
t.f(extended.bar);
t.f(extended.baz);
t.is(extended.barr, "two");
t.is(extended.bazz, "three");
 
t.f(context.bar)
t.f(context.baz);
t.f(context.barr);
t.f(context.bazz);
}
]
);
 
}
/trunk/api/js/dojo1.0/dojox/dtl/tests/module.js
New file
0,0 → 1,13
if(!dojo._hasResource["dojox.dtl.tests.module"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
dojo._hasResource["dojox.dtl.tests.module"] = true;
dojo.provide("dojox.dtl.tests.module");
 
try{
dojo.require("dojox.dtl.tests.text.filter");
dojo.require("dojox.dtl.tests.text.tag");
dojo.require("dojox.dtl.tests.context");
}catch(e){
doh.debug(e);
}
 
}
/trunk/api/js/dojo1.0/dojox/dtl/tests/text/filter.js
New file
0,0 → 1,717
if(!dojo._hasResource["dojox.dtl.tests.text.filter"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
dojo._hasResource["dojox.dtl.tests.text.filter"] = true;
dojo.provide("dojox.dtl.tests.text.filter");
 
dojo.require("dojox.dtl");
dojo.require("dojox.date.php");
dojo.require("dojox.string.sprintf");
 
doh.register("dojox.dtl.text.filter",
[
function test_filter_add(t){
var dd = dojox.dtl;
 
var context = new dd.Context({ four: 4 });
tpl = new dd.Template('{{ four|add:"6" }}');
t.is("10", tpl.render(context));
context.four = "4";
t.is("10", tpl.render(context));
tpl = new dd.Template('{{ four|add:"six" }}');
t.is("4", tpl.render(context));
tpl = new dd.Template('{{ four|add:"6.6" }}');
t.is("10", tpl.render(context));
},
function test_filter_addslashes(t){
var dd = dojox.dtl;
 
var context = new dd.Context({ unslashed: "Test back slashes \\, double quotes \" and single quotes '" })
var tpl = new dd.Template('{{ unslashed|addslashes }}');
t.is("Test back slashes \\\\, double quotes \\\" and single quotes \\'", tpl.render(context));
},
function test_filter_capfirst(t){
var dd = dojox.dtl;
 
var tpl = new dd.Template('{{ uncapped|capfirst }}');
t.is("Cap", tpl.render(new dd.Context({ uncapped: "cap" })));
},
function test_filter_center(t){
var dd = dojox.dtl;
 
var context = new dd.Context();
var tpl = new dd.Template('{{ narrow|center }}');
context.narrow = "even";
t.is("even", tpl.render(context));
context.narrow = "odd";
t.is("odd", tpl.render(context));
tpl = new dd.Template('{{ narrow|center:"5" }}');
context.narrow = "even";
t.is("even ", tpl.render(context));
context.narrow = "odd";
t.is(" odd ", tpl.render(context));
tpl = new dd.Template('{{ narrow|center:"6" }}');
context.narrow = "even";
t.is(" even ", tpl.render(context));
context.narrow = "odd";
t.is(" odd ", tpl.render(context));
tpl = new dd.Template('{{ narrow|center:"12" }}');
context.narrow = "even";
t.is(" even ", tpl.render(context));
context.narrow = "odd";
t.is(" odd ", tpl.render(context));
},
function test_filter_cut(t){
var dd = dojox.dtl;
 
var context = new dd.Context({ uncut: "Apples and oranges" });
var tpl = new dd.Template('{{ uncut|cut }}');
t.is("Apples and oranges", tpl.render(context));
tpl = new dd.Template('{{ uncut|cut:"A" }}');
t.is("pples and oranges", tpl.render(context));
tpl = new dd.Template('{{ uncut|cut:" " }}');
t.is("Applesandoranges", tpl.render(context));
tpl = new dd.Template('{{ uncut|cut:"e" }}');
t.is("Appls and orangs", tpl.render(context));
},
function test_filter_date(t){
var dd = dojox.dtl;
var context = new dd.Context({ now: new Date(2007, 0, 1), then: new Date(2007, 1, 1) });
 
var tpl = new dd.Template('{{ now|date }}');
t.is(dojox.date.php.format(context.now, "N j, Y", dd.utils.date._overrides), tpl.render(context));
 
context.then = new Date(2007, 0, 1);
tpl = new dd.Template('{{ now|date:"d" }}');
t.is("01", tpl.render(context));
 
tpl = new dd.Template('{{ now|date:"D" }}');
t.is("Mon", tpl.render(context));
 
tpl = new dd.Template('{{ now|date:"j" }}');
t.is("1", tpl.render(context));
 
tpl = new dd.Template('{{ now|date:"l" }}');
t.is("Monday", tpl.render(context));
 
tpl = new dd.Template('{{ now|date:"N" }}');
t.is("Jan.", tpl.render(context));
 
tpl = new dd.Template('{{ now|date:"S" }}');
t.is("st", tpl.render(context));
context.now.setDate(2);
t.is("nd", tpl.render(context));
context.now.setDate(3);
t.is("rd", tpl.render(context));
context.now.setDate(4);
t.is("th", tpl.render(context));
context.now.setDate(5);
t.is("th", tpl.render(context));
context.now.setDate(6);
t.is("th", tpl.render(context));
context.now.setDate(7);
t.is("th", tpl.render(context));
context.now.setDate(8);
t.is("th", tpl.render(context));
context.now.setDate(9);
t.is("th", tpl.render(context));
context.now.setDate(10);
t.is("th", tpl.render(context));
context.now.setDate(11);
t.is("th", tpl.render(context));
context.now.setDate(12);
t.is("th", tpl.render(context));
context.now.setDate(13);
t.is("th", tpl.render(context));
context.now.setDate(14);
t.is("th", tpl.render(context));
context.now.setDate(15);
t.is("th", tpl.render(context));
context.now.setDate(16);
t.is("th", tpl.render(context));
context.now.setDate(17);
t.is("th", tpl.render(context));
context.now.setDate(18);
t.is("th", tpl.render(context));
context.now.setDate(19);
t.is("th", tpl.render(context));
context.now.setDate(20);
t.is("th", tpl.render(context));
context.now.setDate(21);
t.is("st", tpl.render(context));
context.now.setDate(22);
t.is("nd", tpl.render(context));
context.now.setDate(23);
t.is("rd", tpl.render(context));
context.now.setDate(24);
t.is("th", tpl.render(context));
context.now.setDate(25);
t.is("th", tpl.render(context));
context.now.setDate(26);
t.is("th", tpl.render(context));
context.now.setDate(27);
t.is("th", tpl.render(context));
context.now.setDate(28);
t.is("th", tpl.render(context));
context.now.setDate(29);
t.is("th", tpl.render(context));
context.now.setDate(30);
t.is("th", tpl.render(context));
context.now.setDate(31);
t.is("st", tpl.render(context));
context.now.setDate(1);
 
tpl = new dd.Template('{{ now|date:"w" }}');
t.is("1", tpl.render(context));
 
tpl = new dd.Template('{{ now|date:"z" }}');
t.is("0", tpl.render(context));
tpl = new dd.Template('{{ now|date:"W" }}');
t.is("1", tpl.render(context));
},
function test_filter_default(t){
var dd = dojox.dtl;
 
var context = new dd.Context();
tpl = new dd.Template('{{ empty|default }}');
t.is("", tpl.render(context));
tpl = new dd.Template('{{ empty|default:"full" }}');
t.is("full", tpl.render(context));
context.empty = "not empty";
t.is("not empty", tpl.render(context));
},
function test_filter_default_if_none(t){
var dd = dojox.dtl;
 
var context = new dd.Context();
tpl = new dd.Template('{{ empty|default_if_none }}');
t.is("", tpl.render(context));
tpl = new dd.Template('{{ empty|default_if_none:"full" }}');
t.is("", tpl.render(context));
context.empty = null;
t.is("full", tpl.render(context));
context.empty = "not empty";
t.is("not empty", tpl.render(context));
},
function test_filter_dictsort(t){
var dd = dojox.dtl;
 
var context = new dd.Context({
fruit: [
{ name: "lemons", toString: function(){ return this.name; } },
{ name: "apples", toString: function(){ return this.name; } },
{ name: "grapes", toString: function(){ return this.name; } }
]
});
tpl = new dd.Template('{{ fruit|dictsort|join:"|" }}');
t.is("lemons|apples|grapes", tpl.render(context));
tpl = new dd.Template('{{ fruit|dictsort:"name"|join:"|" }}');
t.is("apples|grapes|lemons", tpl.render(context));
},
function test_filter_dictsort_reversed(t){
var dd = dojox.dtl;
 
context = new dd.Context({
fruit: [
{ name: "lemons", toString: function(){ return this.name; } },
{ name: "apples", toString: function(){ return this.name; } },
{ name: "grapes", toString: function(){ return this.name; } }
]
});
tpl = new dd.Template('{{ fruit|dictsortreversed:"name"|join:"|" }}');
t.is("lemons|grapes|apples", tpl.render(context));
},
function test_filter_divisibleby(t){
var dd = dojox.dtl;
 
context = new dd.Context();
tpl = new dd.Template('{{ 4|divisibleby:"2" }}');
t.is("true", tpl.render(context));
context = new dd.Context({ number: 4 });
tpl = new dd.Template('{{ number|divisibleby:3 }}');
t.is("false", tpl.render(context));
},
function test_filter_escape(t){
var dd = dojox.dtl;
 
var context = new dd.Context({ unescaped: "Try & cover <all> the \"major\" 'situations' at once" });
tpl = new dd.Template('{{ unescaped|escape }}');
t.is("Try &amp; cover &lt;all&gt; the &quot;major&quot; &#39;situations&#39; at once", tpl.render(context));
},
function test_filter_filesizeformat(t){
var dd = dojox.dtl;
 
var tpl = new dd.Template('{{ 1|filesizeformat }}');
t.is("1 byte", tpl.render());
tpl = new dd.Template('{{ 512|filesizeformat }}');
t.is("512 bytes", tpl.render());
tpl = new dd.Template('{{ 1024|filesizeformat }}');
t.is("1.0 KB", tpl.render());
tpl = new dd.Template('{{ 2048|filesizeformat }}');
t.is("2.0 KB", tpl.render());
tpl = new dd.Template('{{ 1048576|filesizeformat }}');
t.is("1.0 MB", tpl.render());
tpl = new dd.Template('{{ 1073741824|filesizeformat }}');
t.is("1.0 GB", tpl.render());
},
function test_filter_first(t){
var dd = dojox.dtl;
 
var context = new dd.Context({
fruit: [
{ name: "lemons", toString: function(){ return this.name; } },
{ name: "apples", toString: function(){ return this.name; } },
{ name: "grapes", toString: function(){ return this.name; } }
]
});
tpl = new dd.Template('{{ fruit|first }}');
t.is("lemons", tpl.render(context));
},
function test_filter_fix_ampersands(t){
var dd = dojox.dtl;
 
var tpl = new dd.Template('{{ "One & Two"|fix_ampersands }}');
t.is("One &amp; Two", tpl.render());
},
function test_filter_floatformat(t){
var dd = dojox.dtl;
 
var context = new dd.Context({ num1: 34.23234, num2: 34.00000 });
var tpl = new dd.Template('{{ num1|floatformat }}');
t.is("34.2", tpl.render(context));
tpl = new dd.Template('{{ num2|floatformat }}');
t.is("34", tpl.render(context));
tpl = new dd.Template('{{ num1|floatformat:3 }}');
t.is("34.232", tpl.render(context));
tpl = new dd.Template('{{ num2|floatformat:3 }}');
t.is("34.000", tpl.render(context));
tpl = new dd.Template('{{ num1|floatformat:-3 }}');
t.is("34.2", tpl.render(context));
tpl = new dd.Template('{{ num2|floatformat:-3 }}');
t.is("34", tpl.render(context));
},
function test_filter_get_digit(t){
var dd = dojox.dtl;
 
var context = new dd.Context({ pi: 314159265 });
var tpl = new dd.Template('{{ pi|get_digit:1 }}');
t.is("3", tpl.render(context));
tpl = new dd.Template('{{ pi|get_digit:"2" }}');
t.is("1", tpl.render(context));
tpl = new dd.Template('{{ pi|get_digit:0 }}');
t.is("314159265", tpl.render(context));
tpl = new dd.Template('{{ "nada"|get_digit:1 }}');
t.is("0", tpl.render(context));
},
function test_filter_iriencode(t){
var dd = dojox.dtl;
 
var tpl = new dd.Template('{{ "http://homepage.com/~user"|urlencode|iriencode }}');
t.is("http%3A//homepage.com/%7Euser", tpl.render());
tpl = new dd.Template('{{ "pottedmeat@dojotoolkit.org"|iriencode }}');
t.is("pottedmeat%40dojotoolkit.org", tpl.render());
},
function test_filter_join(t){
var dd = dojox.dtl;
 
var context = new dd.Context({ items: ["foo", "bar", "baz" ]});
var tpl = new dd.Template("{{ items|join }}");
t.is("foo,bar,baz", tpl.render(context));
 
tpl = new dd.Template('{{ items|join:"mustard" }}');
t.is("foomustardbarmustardbaz", tpl.render(context));
},
function test_filter_length(t){
var dd = dojox.dtl;
 
var context = new dd.Context({
fruit: [
{ name: "lemons", toString: function(){ return this.name; } },
{ name: "apples", toString: function(){ return this.name; } },
{ name: "grapes", toString: function(){ return this.name; } }
]
});
tpl = new dd.Template('{{ fruit|length }}');
t.is("3", tpl.render(context));
tpl = new dd.Template('{{ fruit|first|length }}');
t.is("6", tpl.render(context));
},
function test_filter_length_is(t){
var dd = dojox.dtl;
 
var context = new dd.Context({
fruit: [
{ name: "lemons", toString: function(){ return this.name; } },
{ name: "apples", toString: function(){ return this.name; } },
{ name: "grapes", toString: function(){ return this.name; } }
]
});
tpl = new dd.Template('{{ fruit|length_is:"3" }}');
t.is("true", tpl.render(context));
tpl = new dd.Template('{{ fruit|length_is:"4" }}');
t.is("false", tpl.render(context));
},
function test_filter_linebreaks(t){
var dd = dojox.dtl;
 
var context = new dd.Context({ unbroken: "This is just\r\n\n\ra bunch\nof text\n\n\nand such" });
tpl = new dd.Template('{{ unbroken|linebreaks }}');
t.is("<p>This is just</p>\n\n<p>a bunch<br />of text</p>\n\n<p>and such</p>", tpl.render(context));
},
function test_filter_linebreaksbr(t){
var dd = dojox.dtl;
 
var context = new dd.Context({ unbroken: "This is just\r\n\n\ra bunch\nof text\n\n\nand such" });
tpl = new dd.Template('{{ unbroken|linebreaksbr }}');
t.is("This is just<br /><br />a bunch<br />of text<br /><br /><br />and such", tpl.render(context));
},
function test_filter_linenumbers(t){
var dd = dojox.dtl;
 
var context = new dd.Context({ lines: "One\nTwo\nThree\nFour\n" });
var tpl = new dd.Template('{{ lines|linenumbers }}');
t.is("1. One\n2. Two\n3. Three\n4. Four\n5. ", tpl.render(context));
},
function test_filter_ljust(t){
var dd = dojox.dtl;
 
var context = new dd.Context();
var tpl = new dd.Template('{{ narrow|ljust }}');
context.narrow = "even";
t.is("even", tpl.render(context));
context.narrow = "odd";
t.is("odd", tpl.render(context));
tpl = new dd.Template('{{ narrow|ljust:"5" }}');
context.narrow = "even";
t.is("even ", tpl.render(context));
context.narrow = "odd";
t.is("odd ", tpl.render(context));
tpl = new dd.Template('{{ narrow|ljust:"6" }}');
context.narrow = "even";
t.is("even ", tpl.render(context));
context.narrow = "odd";
t.is("odd ", tpl.render(context));
tpl = new dd.Template('{{ narrow|ljust:"12" }}');
context.narrow = "even";
t.is("even ", tpl.render(context));
context.narrow = "odd";
t.is("odd ", tpl.render(context));
},
function test_filter_lower(t){
var dd = dojox.dtl;
 
var context = new dd.Context({ mixed: "MiXeD" });
var tpl = new dd.Template('{{ mixed|lower }}');
t.is("mixed", tpl.render(context));
},
function test_filter_make_list(t){
var dd = dojox.dtl;
 
var context = new dd.Context({ word: "foo", number: 314159265, arr: ["first", "second"], obj: {first: "first", second: "second"} });
var tpl = new dd.Template('{{ word|make_list|join:"|" }} {{ number|make_list|join:"|" }} {{ arr|make_list|join:"|" }} {{ obj|make_list|join:"|" }}');
t.is("f|o|o 3|1|4|1|5|9|2|6|5 first|second first|second", tpl.render(context));
},
function test_filter_phone2numeric(t){
var dd = dojox.dtl;
 
tpl = new dd.Template('{{ "1-800-pottedmeat"|phone2numeric }}');
t.is("1-800-7688336328", tpl.render());
},
function test_filter_pluralize(t){
var dd = dojox.dtl;
 
var context = new dd.Context({ animals: ["bear", "cougar", "aardvark"] });
var tpl = new dd.Template('{{ animals|length }} animal{{ animals|length|pluralize }}');
t.is("3 animals", tpl.render(context));
context.animals = ["bear"];
t.is("1 animal", tpl.render(context));
context = new dd.Context({ fairies: ["tinkerbell", "Andy Dick" ]});
tpl = new dd.Template('{{ fairies|length }} fair{{ fairies|length|pluralize:"y,ies" }}');
t.is("2 fairies", tpl.render(context));
context.fairies.pop();
t.is("1 fairy", tpl.render(context));
},
function test_filter_pprint(t){
var dd = dojox.dtl;
 
var context = new dd.Context({ animals: ["bear", "cougar", "aardvark"] });
tpl = new dd.Template("{{ animals|pprint }}");
t.is('["bear", "cougar", "aardvark"]', tpl.render(context));
},
function test_filter_random(t){
var dd = dojox.dtl;
 
var context = new dd.Context({
fruit: [
{ name: "lemons", toString: function(){ return this.name; } },
{ name: "apples", toString: function(){ return this.name; } },
{ name: "grapes", toString: function(){ return this.name; } }
]
});
tpl = new dd.Template('{{ fruit|random }}');
result = tpl.render(context);
t.t(result == "lemons" || result == "apples" || result == "grapes");
var different = false;
for(var i = 0; i < 10; i++){
// Check to see if it changes
if(result != tpl.render(context) && result == "lemons" || result == "apples" || result == "grapes"){
different = true;
break;
}
}
t.t(different);
},
function test_filter_removetags(t){
var dd = dojox.dtl;
 
var context = new dd.Context({ tagged: "I'm gonna do something <script>evil</script> with the <html>filter" });
tpl = new dd.Template('{{ tagged|removetags:"script <html>" }}');
t.is("I'm gonna do something evil with the filter", tpl.render(context));
},
function test_filter_rjust(t){
var dd = dojox.dtl;
 
var context = new dd.Context();
var tpl = new dd.Template('{{ narrow|rjust }}');
context.narrow = "even";
t.is("even", tpl.render(context));
context.narrow = "odd";
t.is("odd", tpl.render(context));
tpl = new dd.Template('{{ narrow|rjust:"5" }}');
context.narrow = "even";
t.is(" even", tpl.render(context));
context.narrow = "odd";
t.is(" odd", tpl.render(context));
tpl = new dd.Template('{{ narrow|rjust:"6" }}');
context.narrow = "even";
t.is(" even", tpl.render(context));
context.narrow = "odd";
t.is(" odd", tpl.render(context));
tpl = new dd.Template('{{ narrow|rjust:"12" }}');
context.narrow = "even";
t.is(" even", tpl.render(context));
context.narrow = "odd";
t.is(" odd", tpl.render(context));
},
function test_filter_slice(t){
var dd = dojox.dtl;
 
var context = new dd.Context({
fruit: [
{ name: "lemons", toString: function(){ return this.name; } },
{ name: "apples", toString: function(){ return this.name; } },
{ name: "grapes", toString: function(){ return this.name; } }
]
});
tpl = new dd.Template('{{ fruit|slice:":1"|join:"|" }}');
t.is("lemons", tpl.render(context));
tpl = new dd.Template('{{ fruit|slice:"1"|join:"|" }}');
t.is("apples|grapes", tpl.render(context));
tpl = new dd.Template('{{ fruit|slice:"1:3"|join:"|" }}');
t.is("apples|grapes", tpl.render(context));
tpl = new dd.Template('{{ fruit|slice:""|join:"|" }}');
t.is("lemons|apples|grapes", tpl.render(context));
tpl = new dd.Template('{{ fruit|slice:"-1"|join:"|" }}');
t.is("grapes", tpl.render(context));
tpl = new dd.Template('{{ fruit|slice:":-1"|join:"|" }}');
t.is("lemons|apples", tpl.render(context));
tpl = new dd.Template('{{ fruit|slice:"-2:-1"|join:"|" }}');
t.is("apples", tpl.render(context));
},
function test_filter_slugify(t){
var dd = dojox.dtl;
 
var context = new dd.Context({ unslugged: "Apples and oranges()"});
tpl = new dd.Template('{{ unslugged|slugify }}');
t.is("apples-and-oranges", tpl.render(context));
},
function test_filter_stringformat(t){
var dd = dojox.dtl;
 
var tpl = new dd.Template('{{ 42|stringformat:"7.3f" }}');
t.is(" 42.000", tpl.render());
},
function test_filter_striptags(t){
var dd = dojox.dtl;
 
var context = new dd.Context({ tagged: "I'm gonna do something <script>evil</script> with the <html>filter" });
tpl = new dd.Template('{{ tagged|striptags }}');
t.is("I'm gonna do something evil with the filter", tpl.render(context));
},
function test_filter_time(t){
var dd = dojox.dtl;
var context = new dd.Context({ now: new Date(2007, 0, 1) });
 
tpl = new dd.Template('{{ now|time }}');
t.is(dojox.date.php.format(context.now, "P", dd.utils.date._overrides), tpl.render(context));
},
function test_filter_timesince(t){
var dd = dojox.dtl;
var context = new dd.Context({ now: new Date(2007, 0, 1), then: new Date(2007, 1, 1) });
 
tpl = new dd.Template('{{ now|timesince:then }}');
t.is("1 month", tpl.render(context));
context.then = new Date(2007, 0, 5);
t.is("4 days", tpl.render(context));
context.then = new Date(2007, 0, 17);
t.is("2 weeks", tpl.render(context));
context.then = new Date(2008, 1, 1);
t.is("1 year", tpl.render(context));
},
function test_filter_timeuntil(t){
var dd = dojox.dtl;
 
var context = new dd.Context({ now: new Date(2007, 0, 1), then: new Date(2007, 1, 1) });
var tpl = new dd.Template('{{ now|timeuntil:then }}');
t.is("1 month", tpl.render(context));
context.then = new Date(2007, 0, 5);
t.is("4 days", tpl.render(context));
context.then = new Date(2007, 0, 17);
t.is("2 weeks", tpl.render(context));
context.then = new Date(2008, 1, 1);
t.is("1 year", tpl.render(context));
},
function test_filter_title(t){
var dd = dojox.dtl;
 
var context = new dd.Context({ name: "potted meat" });
var tpl = new dd.Template("{{ name|title }}");
t.is("Potted Meat", tpl.render(context));
 
context.name = "What's going on?";
t.is("What's Going On?", tpl.render(context));
 
context.name = "use\nline\nbREAKs\tand tabs";
t.is("Use\nLine\nBreaks\tAnd Tabs", tpl.render(context));
},
function test_filter_truncatewords(t){
var dd = dojox.dtl;
 
var context = new dd.Context({ word: "potted meat writes a lot of tests" });
var tpl = new dd.Template("{{ word|truncatewords }}");
t.is(context.word, tpl.render(context));
 
tpl = new dd.Template('{{ word|truncatewords:"1" }}');
t.is("potted", tpl.render(context));
 
tpl = new dd.Template('{{ word|truncatewords:"2" }}');
t.is("potted meat", tpl.render(context));
 
tpl = new dd.Template('{{ word|truncatewords:20" }}');
t.is(context.word, tpl.render(context));
 
context.word = "potted \nmeat \nwrites a lot of tests";
tpl = new dd.Template('{{ word|truncatewords:"3" }}');
t.is("potted \nmeat \nwrites", tpl.render(context));
},
function test_filter_truncatewords_html(t){
var dd = dojox.dtl;
 
var context = new dd.Context({
body: "Test a string <em>that ends <i>inside a</i> tag</em> with different args",
size: 2
})
var tpl = new dd.Template('{{ body|truncatewords_html:size }}');
t.is("Test a ...", tpl.render(context));
context.size = 4;
t.is("Test a string <em>that ...</em>", tpl.render(context));
context.size = 6;
t.is("Test a string <em>that ends <i>inside ...</i></em>", tpl.render(context));
},
function test_filter_unordered_list(t){
var dd = dojox.dtl;
 
var context = new dd.Context({ states: ["States", [["Kansas", [["Lawrence", []], ["Topeka", []]]], ["Illinois", []]]] });
tpl = new dd.Template('{{ states|unordered_list }}');
t.is("\t<li>States\n\t<ul>\n\t\t<li>Kansas\n\t\t<ul>\n\t\t\t<li>Lawrence</li>\n\t\t\t<li>Topeka</li>\n\t\t</ul>\n\t\t</li>\n\t\t<li>Illinois</li>\n\t</ul>\n\t</li>", tpl.render(context));
},
function test_filter_upper(t){
var dd = dojox.dtl;
 
var context = new dd.Context({ mixed: "MiXeD" });
var tpl = new dd.Template('{{ mixed|upper }}');
t.is("MIXED", tpl.render(context));
},
function test_filter_urlencode(t){
var dd = dojox.dtl;
 
var tpl = new dd.Template('{{ "http://homepage.com/~user"|urlencode }}');
t.is("http%3A//homepage.com/%7Euser", tpl.render());
},
function test_filter_urlize(t){
var dd = dojox.dtl;
 
var context = new dd.Context({
body: "My favorite websites are www.televisionwithoutpity.com, http://daringfireball.net and you can email me at pottedmeat@sitepen.com"
});
var tpl = new dd.Template("{{ body|urlize }}");
t.is('My favorite websites are <a href="http://www.televisionwithoutpity.com" rel="nofollow">www.televisionwithoutpity.com</a> <a href="http://daringfireball.net" rel="nofollow">http://daringfireball.net</a> and you can email me at <a href="mailto:pottedmeat@sitepen.com">pottedmeat@sitepen.com</a>', tpl.render(context));
},
function test_filter_urlizetrunc(t){
var dd = dojox.dtl;
 
var context = new dd.Context({
body: "My favorite websites are www.televisionwithoutpity.com, http://daringfireball.net and you can email me at pottedmeat@sitepen.com"
});
var tpl = new dd.Template("{{ body|urlizetrunc }}");
t.is('My favorite websites are <a href="http://www.televisionwithoutpity.com" rel="nofollow">www.televisionwithoutpity.com</a> <a href="http://daringfireball.net" rel="nofollow">http://daringfireball.net</a> and you can email me at <a href="mailto:pottedmeat@sitepen.com">pottedmeat@sitepen.com</a>', tpl.render(context));
tpl = new dd.Template('{{ body|urlizetrunc:"2" }}');
t.is('My favorite websites are <a href="http://www.televisionwithoutpity.com" rel="nofollow">www.televisionwithoutpity.com</a> <a href="http://daringfireball.net" rel="nofollow">http://daringfireball.net</a> and you can email me at <a href="mailto:pottedmeat@sitepen.com">pottedmeat@sitepen.com</a>', tpl.render(context));
tpl = new dd.Template('{{ body|urlizetrunc:"10" }}');
t.is('My favorite websites are <a href="http://www.televisionwithoutpity.com" rel="nofollow">www.tel...</a> <a href="http://daringfireball.net" rel="nofollow">http://...</a> and you can email me at <a href="mailto:pottedmeat@sitepen.com">pottedmeat@sitepen.com</a>', tpl.render(context));
},
function test_filter_wordcount(t){
var dd = dojox.dtl;
 
var context = new dd.Context({
food: "Hot Pocket"
});
var tpl = new dd.Template("{{ food|wordcount }}");
t.is("2", tpl.render(context));
context.food = "";
t.is("0", tpl.render(context));
context.food = "A nice barbecue, maybe a little grilled veggies, some cole slaw.";
t.is("11", tpl.render(context));
},
function test_filter_wordwrap(t){
var dd = dojox.dtl;
 
var context = new dd.Context({
body: "shrimp gumbo, shrimp pie, shrimp scampi, shrimp stew, fried shrimp, baked shrimp, shrimp o grotten, grilled shrimp, shrimp on a stick, shrimp salad, shrimp pop overs, shrimp cake, shrimp legs, shrimp stuffed eggs, shrimp cre oll, shrimp soup, creamed shrimp on toast, shrimp crapes, shrimply good crescent rolls, shrimp pizza, scalloped shrimp, boiled shrimp, shrimp cocktail"
});
var tpl = new dd.Template("{{ body|wordwrap }}");
t.is(context.body, tpl.render(context));
tpl = new dd.Template("{{ body|wordwrap:width }}");
context.width = 10;
t.is("shrimp\ngumbo,\nshrimp\npie,\nshrimp\nscampi,\nshrimp\nstew,\nfried\nshrimp,\nbaked\nshrimp,\nshrimp o\ngrotten,\ngrilled\nshrimp,\nshrimp on\na stick,\nshrimp\nsalad,\nshrimp pop\novers,\nshrimp\ncake,\nshrimp\nlegs,\nshrimp\nstuffed\neggs,\nshrimp cre\noll,\nshrimp\nsoup,\ncreamed\nshrimp on\ntoast,\nshrimp\ncrapes,\nshrimply\ngood\ncrescent\nrolls,\nshrimp\npizza,\nscalloped\nshrimp,\nboiled\nshrimp,\nshrimp\ncocktail", tpl.render(context));
tpl = new dd.Template('{{ body|wordwrap:"80" }}');
t.is("shrimp gumbo, shrimp pie, shrimp scampi, shrimp stew, fried shrimp, baked\nshrimp, shrimp o grotten, grilled shrimp, shrimp on a stick, shrimp salad,\nshrimp pop overs, shrimp cake, shrimp legs, shrimp stuffed eggs, shrimp cre oll,\nshrimp soup, creamed shrimp on toast, shrimp crapes, shrimply good crescent\nrolls, shrimp pizza, scalloped shrimp, boiled shrimp, shrimp cocktail", tpl.render(context));
},
function test_filter_yesno(t){
var dd = dojox.dtl;
 
var context = new dd.Context();
tpl = new dd.Template('{{ true|yesno }}');
t.is("yes", tpl.render(context));
context = new dd.Context({ test: "value" });
tpl = new dd.Template('{{ test|yesno }}');
t.is("yes", tpl.render(context));
tpl = new dd.Template('{{ false|yesno }}');
t.is("no", tpl.render(context));
tpl = new dd.Template('{{ null|yesno }}');
t.is("maybe", tpl.render(context));
tpl = new dd.Template('{{ true|yesno:"bling,whack,soso" }}');
t.is("bling", tpl.render(context));
context = new dd.Context({ test: "value" });
tpl = new dd.Template('{{ test|yesno:"bling,whack,soso" }}');
t.is("bling", tpl.render(context));
tpl = new dd.Template('{{ false|yesno:"bling,whack,soso" }}');
t.is("whack", tpl.render(context));
tpl = new dd.Template('{{ null|yesno:"bling,whack,soso" }}');
t.is("soso", tpl.render(context));
tpl = new dd.Template('{{ null|yesno:"bling,whack" }}');
t.is("whack", tpl.render(context));
}
]
);
 
}
/trunk/api/js/dojo1.0/dojox/dtl/tests/text/tag.js
New file
0,0 → 1,164
if(!dojo._hasResource["dojox.dtl.tests.text.tag"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
dojo._hasResource["dojox.dtl.tests.text.tag"] = true;
dojo.provide("dojox.dtl.tests.text.tag");
 
dojo.require("dojox.dtl");
 
doh.register("dojox.dtl.text.tag",
[
function test_tag_block_and_extends(t){
var dd = dojox.dtl;
 
// Simple (messy) string-based extension
var template = new dd.Template('{% extends "../../dojox/dtl/tests/text/templates/pocket.html" %}{% block pocket %}Simple{% endblock %}');
t.is("Simple Pocket", template.render());
 
// Variable replacement
var context = new dd.Context({
parent: "../../dojox/dtl/tests/text/templates/pocket.html"
})
template = new dd.Template('{% extends parent %}{% block pocket %}Variabled{% endblock %}');
t.is("Variabled Pocket", template.render(context));
 
// Nicer dojo.moduleUrl and variable based extension
context.parent = dojo.moduleUrl("dojox.dtl.tests.text.templates", "pocket.html");
template = new dd.Template('{% extends parent %}{% block pocket %}Slightly More Advanced{% endblock %}');
t.is("Slightly More Advanced Pocket", template.render(context));
 
// dojo.moduleUrl with support for more variables.
// This is important for HTML templates where the "shared" flag will be important.
context.parent = {
url: dojo.moduleUrl("dojox.dtl.tests.text.templates", "pocket.html")
}
template = new dd.Template('{% extends parent %}{% block pocket %}Super{% endblock %}');
t.is("Super Pocket", template.render(context));
},
function test_tag_comment(t){
var dd = dojox.dtl;
 
var template = new dd.Template('Hot{% comment %}<strong>Make me disappear</strong>{% endcomment %} Pocket');
t.is("Hot Pocket", template.render());
 
var found = false;
try {
template = new dd.Template('Hot{% comment %}<strong>Make me disappear</strong> Pocket');
}catch(e){
t.is("Unclosed tag found when looking for endcomment", e.message);
found = true;
}
t.t(found);
},
function test_tag_cycle(t){
var dd = dojox.dtl;
 
var context = new dd.Context({
items: ["apple", "banana", "lemon"],
unplugged: "Torrey"
});
var template = new dd.Template("{% for item in items %}{% cycle 'Hot' 'Diarrhea' unplugged 'Extra' %} Pocket. {% endfor %}");
t.is("Hot Pocket. Diarrhea Pocket. Torrey Pocket. ", template.render(context));
// Make sure that it doesn't break on re-render
t.is("Hot Pocket. Diarrhea Pocket. Torrey Pocket. ", template.render(context));
 
// Test repeating the loop
context.items.push("guava", "mango", "pineapple");
t.is("Hot Pocket. Diarrhea Pocket. Torrey Pocket. Extra Pocket. Hot Pocket. Diarrhea Pocket. ", template.render(context));
 
// Repeat the above tests for the old style
// ========================================
context.items = context.items.slice(0, 3);
template = new dd.Template("{% for item in items %}{% cycle Hot,Diarrhea,Torrey,Extra %} Pocket. {% endfor %}");
t.is("Hot Pocket. Diarrhea Pocket. Torrey Pocket. ", template.render(context));
// Make sure that it doesn't break on re-render
t.is("Hot Pocket. Diarrhea Pocket. Torrey Pocket. ", template.render(context));
 
// Test repeating the loop
context.items.push("guava", "mango", "pineapple");
t.is("Hot Pocket. Diarrhea Pocket. Torrey Pocket. Extra Pocket. Hot Pocket. Diarrhea Pocket. ", template.render(context));
 
// Now test outside of the for loop
// ================================
context = new dojox.dtl.Context({ unplugged: "Torrey" });
template = new dd.Template("{% cycle 'Hot' 'Diarrhea' unplugged 'Extra' as steakum %} Pocket. {% cycle steakum %} Pocket. {% cycle steakum %} Pocket.");
t.is("Hot Pocket. Diarrhea Pocket. Torrey Pocket.", template.render(context));
 
template = new dd.Template("{% cycle 'Hot' 'Diarrhea' unplugged 'Extra' as steakum %} Pocket. {% cycle steakum %} Pocket. {% cycle steakum %} Pocket. {% cycle steakum %} Pocket. {% cycle steakum %} Pocket. {% cycle steakum %} Pocket.");
t.is("Hot Pocket. Diarrhea Pocket. Torrey Pocket. Extra Pocket. Hot Pocket. Diarrhea Pocket.", template.render(context));
 
// Test for nested objects
context.items = {
list: ["apple", "banana", "lemon"]
};
template = new dd.Template("{% for item in items.list %}{% cycle 'Hot' 'Diarrhea' unplugged 'Extra' %} Pocket. {% endfor %}");
t.is("Hot Pocket. Diarrhea Pocket. Torrey Pocket. ", template.render(context));
// Make sure that it doesn't break on re-render
t.is("Hot Pocket. Diarrhea Pocket. Torrey Pocket. ", template.render(context));
},
function test_tag_debug(t){
var dd = dojox.dtl;
 
var context = new dd.Context({
items: ["apple", "banana", "lemon"],
unplugged: "Torrey"
});
var template = new dd.Template("{% debug %}");
t.is('items: ["apple", "banana", "lemon"]\n\nunplugged: "Torrey"\n\n', template.render(context));
},
function test_tag_filter(t){
var dd = dojox.dtl;
 
var template = new dd.Template('{% filter lower|center:"15" %}Hot Pocket{% endfilter %}');
t.is(" hot pocket ", template.render());
},
function test_tag_firstof(t){
t.t(false);
},
function test_tag_for(t){
t.t(false);
},
function test_tag_if(t){
t.t(false);
},
function test_tag_ifchanged(t){
t.t(false);
},
function test_tag_ifequal(t){
t.t(false);
},
function test_tag_ifnotequal(t){
t.t(false);
},
function test_tag_include(t){
t.t(false);
},
function test_tag_load(t){
t.t(false);
},
function test_tag_now(t){
t.t(false);
},
function test_tag_regroup(t){
t.t(false);
},
function test_tag_spaceless(t){
t.t(false);
},
function test_tag_ssi(t){
t.t(false);
},
function test_tag_templatetag(t){
t.t(false);
},
function test_tag_url(t){
t.t(false);
},
function test_tag_widthratio(t){
t.t(false);
},
function test_tag_with(t){
t.t(false);
}
]
);
 
}
/trunk/api/js/dojo1.0/dojox/dtl/tests/text/templates/pocket.html
New file
0,0 → 1,0
{% block pocket %}Hot{% endblock %} Pocket
/trunk/api/js/dojo1.0/dojox/dtl/tests/runTests.html
New file
0,0 → 1,9
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<title>Dojox Djanto Template Language D.O.H. Unit Test Runner</title>
<meta http-equiv="REFRESH" content="0;url=../../../util/doh/runner.html?testModule=dojox.dtl.tests.module"></HEAD>
<BODY>
Redirecting to D.O.H runner.
</BODY>
</HTML>
/trunk/api/js/dojo1.0/dojox/dtl/_base.js
New file
0,0 → 1,632
if(!dojo._hasResource["dojox.dtl._base"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
dojo._hasResource["dojox.dtl._base"] = true;
dojo.provide("dojox.dtl._base");
 
dojo.require("dojox.string.Builder");
dojo.require("dojox.string.tokenize");
 
dojox.dtl.Context = function(dict){
dojo.mixin(this, dict || {});
this._dicts = [];
this._this = {};
}
dojo.extend(dojox.dtl.Context, {
_dicts: [],
_this: {},
extend: function(/*dojox.dtl.Context|Object*/ obj){
// summary: Returns a clone of this context object, with the items from the
// passed objecct mixed in.
var context = new dojox.dtl.Context();
var keys = this.getKeys();
for(var i = 0, key; key = keys[i]; i++){
if(typeof obj[key] != "undefined"){
context[key] = obj[key];
}else{
context[key] = this[key];
}
}
 
if(obj instanceof dojox.dtl.Context){
keys = obj.getKeys();
}else if(typeof obj == "object"){
keys = [];
for(var key in obj){
keys.push(key);
}
}
 
for(var i = 0, key; key = keys[i]; i++){
context[key] = obj[key];
}
 
return context;
},
filter: function(/*dojox.dtl.Context|Object|String...*/ filter){
// summary: Returns a clone of this context, only containing the items
// defined in the filter.
var context = new dojox.dtl.Context();
var keys = [];
if(filter instanceof dojox.dtl.Context){
keys = filter.getKeys();
}else if(typeof filter == "object"){
for(var key in filter){
keys.push(key);
}
}else{
for(var i = 0, arg; arg = arguments[i]; i++){
if(typeof arg == "string"){
keys.push(arg);
}
}
}
 
for(var i = 0, key; key = keys[i]; i++){
context[key] = this[key];
}
 
return context;
},
setThis: function(/*Object*/ _this){
this._this = _this;
},
getThis: function(){
return this._this;
},
push: function(){
var dict = {};
var keys = this.getKeys();
for(var i = 0, key; key = keys[i]; i++){
dict[key] = this[key];
delete this[key];
}
this._dicts.unshift(dict);
},
pop: function(){
if(!this._dicts.length){
throw new Error("pop() has been called more times than push() on the Context");
}
var dict = this._dicts.shift();
dojo.mixin(this, dict);
},
hasKey: function(key){
if(typeof this[key] != "undefined"){
return true;
}
 
for(var i = 0, dict; dict = this._dicts[i]; i++){
if(typeof dict[key] != "undefined"){
return true;
}
}
 
return false;
},
getKeys: function(){
var keys = [];
for(var key in this){
if(isNaN(key)){
var found = false;
for(var protoKey in dojox.dtl.Context.prototype){
if(key == protoKey){
found = true;
break;
}
}
if(!found){
keys.push(key);
}
}
}
return keys;
},
get: function(key, otherwise){
if(typeof this[key] != "undefined"){
return this[key];
}
 
for(var i = 0, dict; dict = this._dicts[i]; i++){
if(typeof dict[key] != "undefined"){
return dict[key];
}
}
 
return otherwise;
},
update: function(dict){
this.push();
if(dict){
dojo.mixin(this, dict);
}
},
toString: function(){ return "dojox.dtl.Context"; }
});
 
dojox.dtl.text = {
types: {tag: -1, varr: -2, text: 3},
pySplit: function(str){
// summary: Split a string according to Python's split function
str = str.replace(/^\s+|\s+$/, "");
if(!str.length){
return [];
}
return str.split(/\s+/g);
},
urlquote: function(/*String*/ url, /*String?*/ safe){
if(!safe){
safe = "/";
}
return dojox.string.tokenize(url, /([^\w-_.])/g, function(token){
if(safe.indexOf(token) == -1){
if(token == " "){
return "+";
}else{
return "%" + token.charCodeAt(0).toString(16).toUpperCase();
}
}
return token;
}).join("");
},
_get: function(module, name, errorless){
// summary: Used to find both tags and filters
var params = dojox.dtl.register.get(module, name, errorless);
if(!params) return;
 
var require = params.getRequire();
var obj = params.getObj();
var fn = params.getFn();
 
if(fn.indexOf(":") != -1){
var parts = fn.split(":");
fn = parts.pop();
}
 
dojo.requireIf(true, require);
 
var parent = window;
var parts = obj.split(".");
for(var i = 0, part; part = parts[i]; i++){
if(!parent[part]) return;
parent = parent[part];
}
return parent[fn || name] || parent[name + "_"];
},
getTag: function(name, errorless){
return dojox.dtl.text._get("tag", name, errorless);
},
getFilter: function(name, errorless){
return dojox.dtl.text._get("filter", name, errorless);
},
getTemplate: function(file){
return new dojox.dtl.Template(dojox.dtl.getTemplateString(file));
},
getTemplateString: function(file){
return dojo._getText(file.toString()) || "";
},
_re: /(?:\{\{\s*(.+?)\s*\}\}|\{%\s*(.+?)\s*%\})/g,
tokenize: function(str){
return dojox.string.tokenize(str, dojox.dtl.text._re, dojox.dtl.text._parseDelims);
},
_parseDelims: function(varr, tag){
var types = dojox.dtl.text.types;
if(varr){
return [types.varr, varr];
}else{
return [types.tag, tag];
}
}
}
 
dojox.dtl.Template = function(str){
var st = dojox.dtl;
var tokens = st.text.tokenize(str);
var parser = new st.Parser(tokens);
this.nodelist = parser.parse();
}
dojo.extend(dojox.dtl.Template, {
render: function(context, /*concatenatable?*/ buffer){
context = context || new dojox.dtl.Context({});
if(!buffer){
dojo.require("dojox.string.Builder");
buffer = new dojox.string.Builder();
}
return this.nodelist.render(context, buffer) + "";
},
toString: function(){ return "dojox.dtl.Template"; }
});
 
dojox.dtl.Filter = function(token){
// summary: Uses a string to find (and manipulate) a variable
if(!token) throw new Error("Filter must be called with variable name");
this.contents = token;
var key = null;
var re = this._re;
var matches, filter, arg, fn;
var filters = [];
while(matches = re.exec(token)){
if(key === null){
if(this._exists(matches, 3)){
// variable
key = matches[3];
}else if(this._exists(matches, 1)){
// _("text")
key = '"' + matches[1] + '"';
}else if(this._exists(matches, 2)){
// "text"
key = '"' + matches[2] + '"';
}else if(this._exists(matches, 9)){
// 'text'
key = '"' + matches[9] + '"';
}
}else{
if(this._exists(matches, 7)){
// :variable
arg = [true, matches[7]];
}else if(this._exists(matches, 5)){
// :_("text")
arg = [false, dojox.dtl.replace(matches[5], '\\"', '"')];
}else if(this._exists(matches, 6)){
// :"text"
arg = [false, dojox.dtl.replace(matches[6], '\\"', '"')];
}else if(this._exists(matches, 8)){
// :"text"
arg = [false, dojox.dtl.replace(matches[8], "\\'", "'")];
}
// Get a named filter
fn = dojox.dtl.text.getFilter(matches[4]);
if(typeof fn != "function") throw new Error(matches[4] + " is not registered as a filter");
filters.push([fn, arg]);
}
}
 
this.key = key;
this.filters = filters;
}
dojo.extend(dojox.dtl.Filter, {
_re: /(?:^_\("([^\\"]*(?:\\.[^\\"])*)"\)|^"([^\\"]*(?:\\.[^\\"]*)*)"|^([a-zA-Z0-9_.]+)|\|(\w+)(?::(?:_\("([^\\"]*(?:\\.[^\\"])*)"\)|"([^\\"]*(?:\\.[^\\"]*)*)"|([a-zA-Z0-9_.]+)|'([^\\']*(?:\\.[^\\']*)*)'))?|^'([^\\']*(?:\\.[^\\']*)*)')/g,
_exists: function(arr, index){
if(typeof arr[index] != "undefined" && arr[index] !== ""){
return true;
}
return false;
},
resolve: function(context){
var str = this.resolvePath(this.key, context);
for(var i = 0, filter; filter = this.filters[i]; i++){
// Each filter has the function in [0], a boolean in [1][0] of whether it's a variable or a string
// and [1][1] is either the variable name of the string content.
if(filter[1]){
if(filter[1][0]){
str = filter[0](str, this.resolvePath(filter[1][1], context));
}else{
str = filter[0](str, filter[1][1]);
}
}else{
str = filter[0](str);
}
}
return str;
},
resolvePath: function(path, context){
var current, parts;
var first = path.charAt(0);
var last = path.charAt(path.length - 1);
if(!isNaN(parseInt(first))){
current = (path.indexOf(".") == -1) ? parseInt(path) : parseFloat(path);
}else if(first == '"' && first == last){
current = path.substring(1, path.length - 1);
}else{;
if(path == "true") return true;
if(path == "false") return false;
if(path == "null" || path == "None") return null;
parts = path.split(".");
current = context.get(parts.shift());
while(parts.length){
if(current && typeof current[parts[0]] != "undefined"){
current = current[parts[0]];
if(typeof current == "function"){
if(current.alters_data){
current = "";
}else{
current = current();
}
}
}else{
return "";
}
parts.shift();
}
}
return current;
},
toString: function(){ return "dojox.dtl.Filter"; }
});
 
dojox.dtl.Node = function(/*Object*/ obj){
// summary: Basic catch-all node
this.contents = obj;
}
dojo.extend(dojox.dtl.Node, {
render: function(context, buffer){
// summary: Adds content onto the buffer
return buffer.concat(this.contents);
},
toString: function(){ return "dojox.dtl.Node"; }
});
 
dojox.dtl.NodeList = function(/*Node[]*/ nodes){
// summary: Allows us to render a group of nodes
this.contents = nodes || [];
}
dojo.extend(dojox.dtl.NodeList, {
push: function(node){
// summary: Add a new node to the list
this.contents.push(node);
},
render: function(context, buffer){
// summary: Adds all content onto the buffer
for(var i = 0; i < this.contents.length; i++){
buffer = this.contents[i].render(context, buffer);
if(!buffer) throw new Error("Template node render functions must return their buffer");
}
return buffer;
},
unrender: function(context, buffer){ return buffer; },
clone: function(){ return this; },
toString: function(){ return "dojox.dtl.NodeList"; }
});
 
dojox.dtl.TextNode = dojox.dtl.Node;
 
dojox.dtl.VarNode = function(str){
// summary: A node to be processed as a variable
this.contents = new dojox.dtl.Filter(str);
}
dojo.extend(dojox.dtl.VarNode, {
render: function(context, buffer){
var str = this.contents.resolve(context);
return buffer.concat(str);
},
toString: function(){ return "dojox.dtl.VarNode"; }
});
 
dojox.dtl.Parser = function(tokens){
// summary: Parser used during initialization and for tag groups.
this.contents = tokens;
}
dojo.extend(dojox.dtl.Parser, {
parse: function(/*Array?*/ stop_at){
// summary: Turns tokens into nodes
// description: Steps into tags are they're found. Blocks use the parse object
// to find their closing tag (the stop_at array). stop_at is inclusive, it
// returns the node that matched.
var st = dojox.dtl;
var types = st.text.types;
var terminators = {};
var tokens = this.contents;
stop_at = stop_at || [];
for(var i = 0; i < stop_at.length; i++){
terminators[stop_at[i]] = true;
}
 
var nodelist = new st.NodeList();
while(tokens.length){
token = tokens.shift();
if(typeof token == "string"){
nodelist.push(new st.TextNode(token));
}else{
var type = token[0];
var text = token[1];
if(type == types.varr){
nodelist.push(new st.VarNode(text));
}else if(type == types.tag){
if(terminators[text]){
tokens.unshift(token);
return nodelist;
}
var cmd = text.split(/\s+/g);
if(cmd.length){
cmd = cmd[0];
var fn = dojox.dtl.text.getTag(cmd);
if(fn){
nodelist.push(fn(this, text));
}
}
}
}
}
 
if(stop_at.length){
throw new Error("Could not find closing tag(s): " + stop_at.toString());
}
 
return nodelist;
},
next: function(){
// summary: Returns the next token in the list.
var token = this.contents.shift();
return {type: token[0], text: token[1]};
},
skipPast: function(endtag){
var types = dojox.dtl.text.types;
while(this.contents.length){
var token = this.contents.shift();
if(token[0] == types.tag && token[1] == endtag){
return;
}
}
throw new Error("Unclosed tag found when looking for " + endtag);
},
getVarNode: function(){
return dojox.dtl.VarNode;
},
getTextNode: function(){
return dojox.dtl.TextNode;
},
getTemplate: function(file){
return new dojox.dtl.Template(file);
},
toString: function(){ return "dojox.dtl.Parser"; }
});
 
dojox.dtl.register = function(module, cols, args, /*Function*/ normalize){
// summary: Used to create dojox.dtl.register[module] function, and as a namespace
// expand: Used if the call structure is reformatted for a more compact view.
// Should return an array of normalized arguments.
// description: The function produced will accept a "name"
// as the first parameter and all other parameters will
// be associated with the parameter names listed in cols.
var ddr = dojox.dtl.register;
var registry = ddr._mod[module] = {
params: [],
Getter: function(params){
ddr._params = params || {};
}
};
 
cols.unshift("name");
for(var i = 0, col; col = cols[i]; i++){
registry.Getter.prototype["get" + col.substring(0, 1).toUpperCase() + col.substring(1, col.length)] = ddr._ret(i);
}
 
ddr[module] = function(/*String*/ name, /*mixed...*/ parameters){
if(normalize){
var normalized = normalize(arguments);
}else{
var normalized = [arguments];
}
 
for(var i = 0, args; args = normalized[i]; i++){
var params = [];
for(var j = 0; j < cols.length; j++){
params.push(args[j] || null);
}
if(typeof args[0] == "string"){
// Strings before regexes for speed
registry.params.unshift(params);
}else{
// break
// module RegExp
registry.params.push(params);
}
}
}
 
ddr[module].apply(null, args);
}
dojo.mixin(dojox.dtl.register, {
_mod: {},
_ret: function(i){
// summary: Just lets use i and _params within a closure
return function(){
return dojox.dtl.register._params[i] || "";
}
},
get: function(/*String*/ module, /*String*/ name, /*Boolean*/ errorless){
// summary: Returns a "Getter", based on the registry
// description: The getter functions correspond with the registered cols
// used in dojo.register
var registry = this._mod[module] || {};
if(registry.params){
for(var i = 0, param; param = registry.params[i]; i++){
var search = param[0];
if(typeof search == "string"){
if(search == name){
return new registry.Getter(param);
}
}else if(name.match(search)){
var matches = search.exec(name);
var mixin = [];
dojo.mixin(mixin, param);
mixin[0] = matches[1];
return new registry.Getter(param);
}
}
}
if(!errorless) throw new Error("'" + module + "' of name '" + name + "' does not exist");
},
_normalize: function(args){
// summary:
// Translates to the signature (/*String*/ name, /*String*/ require, /*String*/ obj, /*String*/ fn)
var items = args[2];
var output = [];
for(var i = 0, item; item = items[i]; i++){
if(typeof item == "string"){
output.push([item, args[0], args[1], item]);
}else{
output.push([item[0], args[0], args[1], item[1]]);
}
}
return output;
},
tag: function(/*String*/ require, /*String*/ obj, /*String[]|[RegExp, String][]*/ fns){
// summary:
// Specify the location of a given tag function.
// require:
// The file this function is in
// obj:
// The base object to use for lookups
// fn:
// List of functions within obj to use
// description:
// When we are looking up a tag as specified in a template, we either use a
// string in the fns array, or the RegExp item of the [RegExp, String] pair.
// When that string is found, it requires the file specified in the require
// parameter, uses the base object as a starting point and checks for obj.fn
// or obj.fn_ in case fn is a reserved word.
this("tag", ["require", "obj", "fn"], arguments, this._normalize);
},
filter: function(/*String*/ require, /*String*/ obj, /*String[]|[RegExp, String][]*/ fns){
// summary:
// Specify the location of a given filter function.
// require:
// The file this function is in
// obj:
// The base object to use for lookups
// fn:
// List of functions within obj to use
// description:
// When we are looking up a tag as specified in a template, we either use a
// string in the fns array, or the RegExp item of the [RegExp, String] pair.
// When that string is found, it requires the file specified in the require
// parameter, uses the base object as a starting point and checks for obj.fn
// or obj.fn_ in case fn is a reserved word.
this("filter", ["require", "obj", "fn"], arguments, this._normalize);
}
});
 
(function(){
var register = dojox.dtl.register;
var dtt = "dojox.dtl.tag";
register.tag(dtt + ".logic", dtt + ".logic", ["if", "for"]);
register.tag(dtt + ".loader", dtt + ".loader", ["extends", "block"]);
register.tag(dtt + ".misc", dtt + ".misc", ["comment", "debug", "filter"]);
register.tag(dtt + ".loop", dtt + ".loop", ["cycle"]);
 
var dtf = "dojox.dtl.filter";
register.filter(dtf + ".dates", dtf + ".dates", ["date", "time", "timesince", "timeuntil"]);
register.filter(dtf + ".htmlstrings", dtf + ".htmlstrings", ["escape", "linebreaks", "linebreaksbr", "removetags", "striptags"]);
register.filter(dtf + ".integers", dtf + ".integers", ["add", "get_digit"]);
register.filter(dtf + ".lists", dtf + ".lists", ["dictsort", "dictsortreversed", "first", "join", "length", "length_is", "random", "slice", "unordered_list"]);
register.filter(dtf + ".logic", dtf + ".logic", ["default", "default_if_none", "divisibleby", "yesno"]);
register.filter(dtf + ".misc", dtf + ".misc", ["filesizeformat", "pluralize", "phone2numeric", "pprint"]);
register.filter(dtf + ".strings", dtf + ".strings", ["addslashes", "capfirst", "center", "cut", "fix_ampersands", "floatformat", "iriencode", "linenumbers", "ljust", "lower", "make_list", "rjust", "slugify", "stringformat", "title", "truncatewords", "truncatewords_html", "upper", "urlencode", "urlize", "urlizetrunc", "wordcount", "wordwrap"]);
})();
 
dojox.dtl.replace = function(str, token, repl){
repl = repl || "";
var pos, len = token.length;
while(1){
pos = str.indexOf(token);
if(pos == -1) break;
str = str.substring(0, pos) + repl + str.substring(pos + len);
}
return str;
}
 
dojox.dtl.resolveVariable = function(token, context){
// summary: Quickly resolve a variables
var filter = new dojox.dtl.Filter(token);
return filter.resolve(context);
}
 
}
/trunk/api/js/dojo1.0/dojox/dtl/filter/logic.js
New file
0,0 → 1,34
if(!dojo._hasResource["dojox.dtl.filter.logic"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
dojo._hasResource["dojox.dtl.filter.logic"] = true;
dojo.provide("dojox.dtl.filter.logic");
 
dojo.mixin(dojox.dtl.filter.logic, {
default_: function(value, arg){
// summary: If value is unavailable, use given default
return value || arg || "";
},
default_if_none: function(value, arg){
// summary: If value is null, use given default
return (value === null) ? arg || "" : value || "";
},
divisibleby: function(value, arg){
// summary: Returns true if the value is devisible by the argument"
return (parseInt(value) % parseInt(arg)) == 0;
},
_yesno: /\s*,\s*/g,
yesno: function(value, arg){
// summary:
// arg being a comma-delimited string, value of true/false/none
// chooses the appropriate item from the string
if(!arg) arg = 'yes,no,maybe';
var parts = arg.split(dojox.dtl.filter.logic._yesno);
if(parts.length < 2){
return value;
}
if(value) return parts[0];
if((!value && value !== null) || parts.length < 3) return parts[1];
return parts[2];
}
});
 
}
/trunk/api/js/dojo1.0/dojox/dtl/filter/htmlstrings.js
New file
0,0 → 1,59
if(!dojo._hasResource["dojox.dtl.filter.htmlstrings"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
dojo._hasResource["dojox.dtl.filter.htmlstrings"] = true;
dojo.provide("dojox.dtl.filter.htmlstrings");
 
dojo.require("dojox.dtl._base");
 
dojo.mixin(dojox.dtl.filter.htmlstrings, {
_escapeamp: /&/g,
_escapelt: /</g,
_escapegt: />/g,
_escapeqt: /'/g,
_escapedblqt: /"/g,
_linebreaksrn: /(\r\n|\n\r)/g,
_linebreaksn: /\n{2,}/g,
_linebreakss: /(^\s+|\s+$)/g,
_linebreaksbr: /\n/g,
_removetagsfind: /[a-z0-9]+/g,
_striptags: /<[^>]*?>/g,
escape: function(value){
// summary: Escapes a string's HTML
var dh = dojox.dtl.filter.htmlstrings;
return value.replace(dh._escapeamp, '&amp;').replace(dh._escapelt, '&lt;').replace(dh._escapegt, '&gt;').replace(dh._escapedblqt, '&quot;').replace(dh._escapeqt, '&#39;');
},
linebreaks: function(value){
// summary: Converts newlines into <p> and <br />s
var output = [];
var dh = dojox.dtl.filter.htmlstrings;
value = value.replace(dh._linebreaksrn, "\n");
var parts = value.split(dh._linebreaksn);
for(var i = 0; i < parts.length; i++){
var part = parts[i].replace(dh._linebreakss, "").replace(dh._linebreaksbr, "<br />")
output.push("<p>" + part + "</p>");
}
 
return output.join("\n\n");
},
linebreaksbr: function(value){
// summary: Converts newlines into <br />s
var dh = dojox.dtl.filter.htmlstrings;
return value.replace(dh._linebreaksrn, "\n").replace(dh._linebreaksbr, "<br />");
},
removetags: function(value, arg){
// summary: Removes a space separated list of [X]HTML tags from the output"
var dh = dojox.dtl.filter.htmlstrings;
var tags = [];
var group;
while(group = dh._removetagsfind.exec(arg)){
tags.push(group[0]);
}
tags = "(" + tags.join("|") + ")";
return value.replace(new RegExp("</?\s*" + tags + "\s*[^>]*>", "gi"), "");
},
striptags: function(value){
// summary: Strips all [X]HTML tags
return value.replace(dojox.dtl.filter.htmlstrings._striptags, "");
}
});
 
}
/trunk/api/js/dojo1.0/dojox/dtl/filter/lists.js
New file
0,0 → 1,131
if(!dojo._hasResource["dojox.dtl.filter.lists"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
dojo._hasResource["dojox.dtl.filter.lists"] = true;
dojo.provide("dojox.dtl.filter.lists")
 
dojo.require("dojox.dtl._base");
 
dojo.mixin(dojox.dtl.filter.lists, {
_dictsort: function(a, b){
if(a[0] == b[0]) return 0;
return (a[0] < b[0]) ? -1 : 1;
},
dictsort: function(value, arg){
// summary: Takes a list of dicts, returns that list sorted by the property given in the argument.
if(!arg) return value;
 
var items = [];
for(var key in value){
items.push([dojox.dtl.resolveVariable('var.' + arg, new dojox.dtl.Context({ 'var' : value[key]})), value[key]]);
}
items.sort(dojox.dtl.filter.lists._dictsort);
var output = [];
for(var i = 0, item; item = items[i]; i++){
output.push(item[1]);
}
return output;
},
dictsortreversed: function(value, arg){
// summary: Takes a list of dicts, returns that list sorted in reverse order by the property given in the argument.
if(!arg) return value;
 
var dictsort = dojox.dtl.filter.lists.dictsort(value, arg);
return dictsort.reverse();
},
first: function(value){
// summary: Returns the first item in a list
return (value.length) ? value[0] : "";
},
join: function(value, arg){
// summary: Joins a list with a string, like Python's ``str.join(list)``
// description:
// Django throws a compile error, but JS can't do arg checks
// so we're left with run time errors, which aren't wise for something
// as trivial here as an empty arg.
return value.join(arg || ",");
},
length: function(value){
// summary: Returns the length of the value - useful for lists
return (isNaN(value.length)) ? (value + "").length : value.length;
},
length_is: function(value, arg){
// summary: Returns a boolean of whether the value's length is the argument
return value.length == parseInt(arg);
},
random: function(value){
// summary: Returns a random item from the list
return value[Math.floor(Math.random() * value.length)];
},
slice: function(value, arg){
// summary: Returns a slice of the list.
// description:
// Uses the same syntax as Python's list slicing; see
// http://diveintopython.org/native_data_types/lists.html#odbchelper.list.slice
// for an introduction.
// Also uses the optional third value to denote every X item.
arg = arg || "";
var parts = arg.split(":");
var bits = [];
for(var i = 0; i < parts.length; i++){
if(!parts[i].length){
bits.push(null);
}else{
bits.push(parseInt(parts[i]));
}
}
 
if(bits[0] === null){
bits[0] = 0;
}
if(bits[0] < 0){
bits[0] = value.length + bits[0];
}
if(bits.length < 2 || bits[1] === null){
bits[1] = value.length;
}
if(bits[1] < 0){
bits[1] = value.length + bits[1];
}
return value.slice(bits[0], bits[1]);
},
_unordered_list: function(value, tabs){
var ddl = dojox.dtl.filter.lists;
var indent = "";
for(var i = 0; i < tabs; i++){
indent += "\t";
}
if(value[1] && value[1].length){
var recurse = [];
for(var i = 0; i < value[1].length; i++){
recurse.push(ddl._unordered_list(value[1][i], tabs + 1))
}
return indent + "<li>" + value[0] + "\n" + indent + "<ul>\n" + recurse.join("\n") + "\n" + indent + "</ul>\n" + indent + "</li>";
}else{
return indent + "<li>" + value[0] + "</li>";
}
},
unordered_list: function(value){
// summary:
// Recursively takes a self-nested list and returns an HTML unordered list --
// WITHOUT opening and closing <ul> tags.
// description:
// The list is assumed to be in the proper format. For example, if ``var`` contains
// ``['States', [['Kansas', [['Lawrence', []], ['Topeka', []]]], ['Illinois', []]]]``,
// then ``{{ var|unordered_list }}`` would return::
//
// <li>States
// <ul>
// <li>Kansas
// <ul>
// <li>Lawrence</li>
// <li>Topeka</li>
// </ul>
// </li>
// <li>Illinois</li>
// </ul>
// </li>
return dojox.dtl.filter.lists._unordered_list(value, 1);
}
});
 
}
/trunk/api/js/dojo1.0/dojox/dtl/filter/dates.js
New file
0,0 → 1,36
if(!dojo._hasResource["dojox.dtl.filter.dates"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
dojo._hasResource["dojox.dtl.filter.dates"] = true;
dojo.provide("dojox.dtl.filter.dates");
 
dojo.require("dojox.dtl.utils.date");
 
dojo.mixin(dojox.dtl.filter.dates, {
date: function(value, arg){
// summary: Formats a date according to the given format
if(!value || !(value instanceof Date)) return "";
arg = arg || "N j, Y";
return dojox.dtl.utils.date.format(value, arg);
},
time: function(value, arg){
// summary: Formats a time according to the given format
if(!value || !(value instanceof Date)) return "";
arg = arg || "P";
return dojox.dtl.utils.date.format(value, arg);
},
timesince: function(value, arg){
// summary: Formats a date as the time since that date (i.e. "4 days, 6 hours")
var timesince = dojox.dtl.utils.date.timesince;
if(!value) return "";
if(arg) return timesince(arg, value);
return timesince(value);
},
timeuntil: function(value, arg){
// summary: Formats a date as the time until that date (i.e. "4 days, 6 hours")
var timesince = dojox.dtl.utils.date.timesince;
if(!value) return "";
if(arg) return timesince(arg, value);
return timesince(new Date(), value);
}
});
 
}
/trunk/api/js/dojo1.0/dojox/dtl/filter/integers.js
New file
0,0 → 1,32
if(!dojo._hasResource["dojox.dtl.filter.integers"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
dojo._hasResource["dojox.dtl.filter.integers"] = true;
dojo.provide("dojox.dtl.filter.integers");
 
dojo.mixin(dojox.dtl.filter.integers, {
add: function(value, arg){
value = parseInt(value);
arg = parseInt(arg);
return isNaN(arg) ? value : value + arg;
},
get_digit: function(value, arg){
// summary:
// Given a whole number, returns the 1-based requested digit of it
// desciprtion:
// 1 is the right-most digit, 2 is the second-right-most digit, etc. Returns the
// original value for invalid input (if input or argument is not an integer,
// or if argument is less than 1). Otherwise, output is always an integer.
value = parseInt(value);
arg = parseInt(arg) - 1;
if(arg >= 0){
value += "";
if(arg < value.length){
value = parseInt(value.charAt(arg));
}else{
value = 0;
}
}
return (isNaN(value) ? 0 : value);
}
});
 
}
/trunk/api/js/dojo1.0/dojox/dtl/filter/strings.js
New file
0,0 → 1,312
if(!dojo._hasResource["dojox.dtl.filter.strings"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
dojo._hasResource["dojox.dtl.filter.strings"] = true;
dojo.provide("dojox.dtl.filter.strings");
 
dojo.require("dojox.dtl.filter.htmlstrings");
dojo.require("dojox.string.sprintf");
dojo.require("dojox.string.tokenize");
 
dojo.mixin(dojox.dtl.filter.strings, {
addslashes: function(value){
// summary: Adds slashes - useful for passing strings to JavaScript, for example.
return value.replace(/\\/g, "\\\\").replace(/"/g, '\\"').replace(/'/g, "\\'");
},
capfirst: function(value){
// summary: Capitalizes the first character of the value
value = "" + value;
return value.charAt(0).toUpperCase() + value.substring(1);
},
center: function(value, arg){
// summary: Centers the value in a field of a given width
arg = arg || value.length;
value = value + "";
var diff = arg - value.length;
if(diff % 2){
value = value + " ";
diff -= 1;
}
for(var i = 0; i < diff; i += 2){
value = " " + value + " ";
}
return value;
},
cut: function(value, arg){
// summary: Removes all values of arg from the given string
arg = arg + "" || "";
value = value + "";
return value.replace(new RegExp(arg, "g"), "");
},
_fix_ampersands: /&(?!(\w+|#\d+);)/g,
fix_ampersands: function(value){
// summary: Replaces ampersands with ``&amp;`` entities
return value.replace(dojox.dtl.filter.strings._fix_ampersands, "&amp;");
},
floatformat: function(value, arg){
// summary: Format a number according to arg
// description:
// If called without an argument, displays a floating point
// number as 34.2 -- but only if there's a point to be displayed.
// With a positive numeric argument, it displays that many decimal places
// always.
// With a negative numeric argument, it will display that many decimal
// places -- but only if there's places to be displayed.
arg = parseInt(arg || -1);
value = parseFloat(value);
var m = value - value.toFixed(0);
if(!m && arg < 0){
return value.toFixed();
}
value = value.toFixed(Math.abs(arg));
return (arg < 0) ? parseFloat(value) + "" : value;
},
iriencode: function(value){
return dojox.dtl.text.urlquote(value, "/#%[]=:;$&()+,!");
},
linenumbers: function(value){
// summary: Displays text with line numbers
var df = dojox.dtl.filter;
var lines = value.split("\n");
var output = [];
var width = (lines.length + "").length;
for(var i = 0, line; i < lines.length; i++){
line = lines[i];
output.push(df.strings.ljust(i + 1, width) + ". " + df.htmlstrings.escape(line));
}
return output.join("\n");
},
ljust: function(value, arg){
value = value + "";
arg = parseInt(arg);
while(value.length < arg){
value = value + " ";
}
return value;
},
lower: function(value){
// summary: Converts a string into all lowercase
return (value + "").toLowerCase();
},
make_list: function(value){
// summary:
// Returns the value turned into a list. For an integer, it's a list of
// digits. For a string, it's a list of characters.
var output = [];
if(typeof value == "number"){
value = value + "";
}
if(value.charAt){
for(var i = 0; i < value.length; i++){
output.push(value.charAt(i));
}
return output;
}
if(typeof value == "object"){
for(var key in value){
output.push(value[key]);
}
return output;
}
return [];
},
rjust: function(value, arg){
value = value + "";
arg = parseInt(arg);
while(value.length < arg){
value = " " + value;
}
return value;
},
slugify: function(value){
// summary: Converts to lowercase, removes
// non-alpha chars and converts spaces to hyphens
value = value.replace(/[^\w\s-]/g, "").toLowerCase();
return value.replace(/[\-\s]+/g, "-");
},
_strings: {},
stringformat: function(value, arg){
// summary:
// Formats the variable according to the argument, a string formatting specifier.
// This specifier uses Python string formating syntax, with the exception that
// the leading "%" is dropped.
arg = "" + arg;
var strings = dojox.dtl.filter.strings._strings;
if(!strings[arg]){
strings[arg] = new dojox.string.sprintf.Formatter("%" + arg);
}
return strings[arg].format(value);
},
title: function(value){
// summary: Converts a string into titlecase
var last, title = "";
for(var i = 0, current; i < value.length; i++){
current = value.charAt(i);
if(last == " " || last == "\n" || last == "\t" || !last){
title += current.toUpperCase();
}else{
title += current.toLowerCase();
}
last = current;
}
return title;
},
_truncatewords: /[ \n\r\t]/,
truncatewords: function(value, arg){
// summary: Truncates a string after a certain number of words
// arg: Integer
// Number of words to truncate after
arg = parseInt(arg);
if(!arg){
return value;
}
 
for(var i = 0, j = value.length, count = 0, current, last; i < value.length; i++){
current = value.charAt(i);
if(dojox.dtl.filter.strings._truncatewords.test(last)){
if(!dojox.dtl.filter.strings._truncatewords.test(current)){
++count;
if(count == arg){
return value.substring(0, j + 1);
}
}
}else if(!dojox.dtl.filter.strings._truncatewords.test(current)){
j = i;
}
last = current;
}
return value;
},
_truncate_words: /(&.*?;|<.*?>|(\w[\w-]*))/g,
_truncate_tag: /<(\/)?([^ ]+?)(?: (\/)| .*?)?>/,
_truncate_singlets: { br: true, col: true, link: true, base: true, img: true, param: true, area: true, hr: true, input: true },
truncatewords_html: function(value, arg){
arg = parseInt(arg);
 
if(arg <= 0){
return "";
}
 
var strings = dojox.dtl.filter.strings;
var words = 0;
var open = [];
 
var output = dojox.string.tokenize(value, strings._truncate_words, function(all, word){
if(word){
// It's an actual non-HTML word
++words;
if(words < arg){
return word;
}else if(words == arg){
return word + " ...";
}
}
// Check for tag
var tag = all.match(strings._truncate_tag);
if(!tag || words >= arg){
// Don't worry about non tags or tags after our truncate point
return;
}
var closing = tag[1];
var tagname = tag[2].toLowerCase();
var selfclosing = tag[3];
if(closing || strings._truncate_singlets[tagname]){
}else if(closing){
var i = dojo.indexOf(open, tagname);
if(i != -1){
open = open.slice(i + 1);
}
}else{
open.unshift(tagname);
}
return all;
}).join("");
 
output = output.replace(/\s+$/g, "");
 
for(var i = 0, tag; tag = open[i]; i++){
output += "</" + tag + ">";
}
 
return output;
},
upper: function(value){
return value.toUpperCase();
},
urlencode: function(value){
return dojox.dtl.text.urlquote(value);
},
_urlize: /^((?:[(>]|&lt;)*)(.*?)((?:[.,)>\n]|&gt;)*)$/,
_urlize2: /^\S+@[a-zA-Z0-9._-]+\.[a-zA-Z0-9._-]+$/,
urlize: function(value){
return dojox.dtl.filter.strings.urlizetrunc(value);
},
urlizetrunc: function(value, arg){
arg = parseInt(arg);
return dojox.string.tokenize(value, /(\S+)/g, function(word){
var matches = dojox.dtl.filter.strings._urlize.exec(word);
if(!matches){
return word;
}
var lead = matches[1];
var middle = matches[2];
var trail = matches[3];
 
var startsWww = middle.indexOf("www.") == 0;
var hasAt = middle.indexOf("@") != -1;
var hasColon = middle.indexOf(":") != -1;
var startsHttp = middle.indexOf("http://") == 0;
var startsHttps = middle.indexOf("https://") == 0;
var firstAlpha = /[a-zA-Z0-9]/.test(middle.charAt(0));
var last4 = middle.substring(middle.length - 4);
 
var trimmed = middle;
if(arg > 3){
trimmed = trimmed.substring(0, arg - 3) + "...";
}
 
if(startsWww || (!hasAt && !startsHttp && middle.length && firstAlpha && (last4 == ".org" || last4 == ".net" || last4 == ".com"))){
return '<a href="http://' + middle + '" rel="nofollow">' + trimmed + '</a>';
}else if(startsHttp || startsHttps){
return '<a href="' + middle + '" rel="nofollow">' + trimmed + '</a>';
}else if(hasAt && !startsWww && !hasColon && dojox.dtl.filter.strings._urlize2.test(middle)){
return '<a href="mailto:' + middle + '">' + middle + '</a>';
}
return word;
}).join("");
},
wordcount: function(value){
return dojox.dtl.text.pySplit(value).length;
},
wordwrap: function(value, arg){
arg = parseInt(arg);
// summary: Wraps words at specified line length
var output = [];
var parts = value.split(/ /g);
if(parts.length){
var word = parts.shift();
output.push(word);
var pos = word.length - word.lastIndexOf("\n") - 1;
for(var i = 0; i < parts.length; i++){
word = parts[i];
if(word.indexOf("\n") != -1){
var lines = word.split(/\n/g);
}else{
var lines = [word];
}
pos += lines[0].length + 1;
if(arg && pos > arg){
output.push("\n");
pos = lines[lines.length - 1].length;
}else{
output.push(" ");
if(lines.length > 1){
pos = lines[lines.length - 1].length;
}
}
output.push(word);
}
}
return output.join("");
}
});
 
}
/trunk/api/js/dojo1.0/dojox/dtl/filter/misc.js
New file
0,0 → 1,59
if(!dojo._hasResource["dojox.dtl.filter.misc"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
dojo._hasResource["dojox.dtl.filter.misc"] = true;
dojo.provide("dojox.dtl.filter.misc");
 
dojo.mixin(dojox.dtl.filter.misc, {
filesizeformat: function(value){
// summary: Format the value like a 'human-readable' file size (i.e. 13 KB, 4.1 MB, 102bytes, etc).
value = parseFloat(value);
if(value < 1024){
return (value == 1) ? value + " byte" : value + " bytes";
}else if(value < 1024 * 1024){
return (value / 1024).toFixed(1) + " KB";
}else if(value < 1024 * 1024 * 1024){
return (value / 1024 / 1024).toFixed(1) + " MB";
}
return (value / 1024 / 1024 / 1024).toFixed(1) + " GB";
},
pluralize: function(value, arg){
// summary:
// Returns a plural suffix if the value is not 1, for '1 vote' vs. '2 votes'
// description:
// By default, 's' is used as a suffix; if an argument is provided, that string
// is used instead. If the provided argument contains a comma, the text before
// the comma is used for the singular case.
arg = arg || 's';
if(arg.indexOf(",") == -1){
arg = "," + arg;
}
var parts = arg.split(",");
if(parts.length > 2){
return "";
}
var singular = parts[0];
var plural = parts[1];
 
if(parseInt(value) != 1){
return plural;
}
return singular;
},
_phone2numeric: { a: 2, b: 2, c: 2, d: 3, e: 3, f: 3, g: 4, h: 4, i: 4, j: 5, k: 5, l: 5, m: 6, n: 6, o: 6, p: 7, r: 7, s: 7, t: 8, u: 8, v: 8, w: 9, x: 9, y: 9 },
phone2numeric: function(value){
// summary: Takes a phone number and converts it in to its numerical equivalent
var dm = dojox.dtl.filter.misc;
value = value + "";
var output = "";
for(var i = 0; i < value.length; i++){
var chr = value.charAt(i).toLowerCase();
(dm._phone2numeric[chr]) ? output += dm._phone2numeric[chr] : output += value.charAt(i);
}
return output;
},
pprint: function(value){
// summary: A wrapper around toJson unless something better comes along
return dojo.toJson(value);
}
});
 
}
/trunk/api/js/dojo1.0/dojox/dtl/demos/templates/blog_base.html
New file
0,0 → 1,8
<div>
<h1><!--{{ title }}--></h1>
<ul style="float: left; width: 100px; height: 300px; margin-right: 20px; border: 1px solid #666;">
<li><a onclick="_showList" style="cursor: pointer;">Home</a></li>
<li><a onclick="_showPage" style="cursor: pointer;" class="page-about">About Jim</a></li>
</ul>
<!--{% block body %}--><!--{% endblock %}-->
</div>
/trunk/api/js/dojo1.0/dojox/dtl/demos/templates/blog_list.html
New file
0,0 → 1,8
<!--{% extends base %}-->
<!--{% block body %}-->
<ul>
<!--{% for blog in blog_list %}-->
<li onclick="_showDetail" class="blog-{{ forloop.key }}" style="cursor: pointer;">{{ blog.title }}</li>
<!--{% endfor %}-->
</ul>
<!--{% endblock %}-->
/trunk/api/js/dojo1.0/dojox/dtl/demos/templates/animation.html
New file
0,0 → 1,4
<div>
<div tstyle="top: {{ y }}px; left: {{ x }}px;" style="width: 10px; height: 10px; background: red; position: absolute;">&nbsp;</div>
<div attach="blue" style="top: 10px; left: 0; width: 10px; height: 10px; background: blue; position: absolute;">&nbsp;</div>
</div>
/trunk/api/js/dojo1.0/dojox/dtl/demos/templates/blog_page.html
New file
0,0 → 1,7
<!--{% extends "shared:templates/blog_base.html" %}-->
 
<!--{% block body %}-->
<div>
<!--{% html body %}-->
</div>
<!--{% endblock %}-->
/trunk/api/js/dojo1.0/dojox/dtl/demos/templates/blog_detail.html
New file
0,0 → 1,10
<!--{% extends base %}-->
 
<!--{% block body %}-->
<div>
<h3><!--{{ blog.title }}--></h3>
<div><small>posted on <!--{{ blog.date|date }}--> by <!--{{ blog.author }}--></small></div>
<p><!--{{ blog.teaser }}--></p>
<p><!--{{ blog.body }}--></p>
</div>
<!--{% endblock %}-->
/trunk/api/js/dojo1.0/dojox/dtl/demos/demo_Animation.html
New file
0,0 → 1,47
<html>
<head>
<title>Testing dojox.dtl using animation to change attributes</title>
<script src="../../../dojo/dojo.js" djConfig="parseOnLoad: true, usePlainJson: true"></script>
<script>
dojo.require("dojox.dtl.widget");
 
dojo.provide("demo");
 
dojo.declare("demo.Animation", dojox.dtl._Widget,
{
buffer: 0, // Note: Sensitivity is 0 by default, but this is to emphasize we're not doing any buffering
constructor: function(props, node){
this.context = new dojox.dtl.Context({ x: 0, y: 0 });
this.template = new dojox.dtl.HtmlTemplate(dojo.moduleUrl("dojox.dtl.demos.templates", "animation.html"));
},
postCreate: function(){
this.render(this.template, this.context);
var anim = new dojo._Animation({
curve: [0, 300],
rate: 10,
duration: 5000,
easing: dojo._defaultEasing
});
dojo.connect(anim, "onAnimate", this, "_reDraw");
anim.play();
},
_reDraw: function(obj){
this.context.x = obj;
this.context.y = Math.sqrt(obj) * 10;
 
dojo.style(this.blue, "left", this.context.x);
dojo.style(this.blue, "top", this.context.y + 10);
 
this.render(this.template, this.context);
}
});
 
dojo.require("dojo.parser");
</script>
</head>
<body>
<div dojoType="dojox.dtl.AttachPoint">
<div dojoType="demo.Animation" />
</div>
</body>
</html>
/trunk/api/js/dojo1.0/dojox/dtl/demos/json/blog/get_blog_1.json
New file
0,0 → 1,0
{"teaser":"I'd be able to write a lot faster.","body":"I think I wouldn't be able to think.","date":1189125242601,"author":"jim"}
/trunk/api/js/dojo1.0/dojox/dtl/demos/json/blog/get_blog_3.json
New file
0,0 → 1,0
{"teaser":"There was SO much sand","body":"I tried to walk so fast that I wouldn't leave foot prints.","date":1190245842601,"author":"jim"}
/trunk/api/js/dojo1.0/dojox/dtl/demos/json/blog/get_page_about.json
New file
0,0 → 1,0
{"title":"About Jim","body":"<p>Jim is an avid golfer, enjoys long walks on the beach, and eating hot pockets</p><p>When he's not scalding his mouth, you'll find him throwing rocks at pigeons.</p>"}
/trunk/api/js/dojo1.0/dojox/dtl/demos/json/blog/get_blog_list.json
New file
0,0 → 1,0
{"blog_list":{"3":{"title":"My Trip to the Beach"},"1":{"title":"If I Were a Robot"}}}
/trunk/api/js/dojo1.0/dojox/dtl/demos/demo_Blog.html
New file
0,0 → 1,114
<html>
<head>
<title>Testing dojox.dtl using a blog example</title>
<script src="../../../dojo/dojo.js" djConfig="parseOnLoad: true, usePlainJson: true"></script>
<script>
dojo.require("dojox.dtl.widget");
 
dojo.provide("demo");
 
dojo.declare("demo.Blog", dojox.dtl._Widget,
{
buffer: dojox.dtl.render.html.sensitivity.NODE,
constructor: function(props, node){
this.contexts = {
list: false,
blogs: {},
pages: {}
}
this.templates = {
list: new dojox.dtl.HtmlTemplate(dojo.moduleUrl("dojox.dtl.demos.templates", "blog_list.html")),
detail: new dojox.dtl.HtmlTemplate(dojo.moduleUrl("dojox.dtl.demos.templates", "blog_detail.html")),
page: new dojox.dtl.HtmlTemplate(dojo.moduleUrl("dojox.dtl.demos.templates", "blog_page.html"))
}
},
postCreate: function(){
if(this.contexts.list){
this.render(this.templates.list, this.contexts.list);
}else{
dojo.xhrGet({
url: dojo.moduleUrl("dojox.dtl.demos.json.blog", "get_blog_list.json"),
handleAs: "json"
}).addCallback(this, "_loadList");
}
},
_showList: function(obj){
this.render(this.templates.list, this.contexts.list);
},
_showDetail: function(obj){
var key = obj.target.className.substring(5);
 
if(this.contexts.blogs[key]){
this.render(this.templates.detail, this.contexts.blogs[key]);
}else{
dojo.xhrGet({
url: dojo.moduleUrl("dojox.dtl.demos.json.blog", "get_blog_" + key + ".json"),
handleAs: "json",
load: function(data){
data.key = key;
return data;
}
}).addCallback(this, "_loadDetail");
}
},
_showPage: function(obj){
var key = obj.target.className.substring(5);
 
if(this.contexts.pages[key]){
this.render(this.templates.page, this.contexts.pages[key]);
}else{
dojo.xhrGet({
url: dojo.moduleUrl("dojox.dtl.demos.json.blog", "get_page_" + key + ".json"),
handleAs: "json",
load: function(data){
data.key = key;
return data;
}
}).addCallback(this, "_loadPage");
}
},
_loadList: function(data){
this.contexts.list = new dojox.dtl.Context(data).extend({
title: "Blog Posts",
base: {
url: dojo.moduleUrl("dojox.dtl.demos.templates", "blog_base.html"),
shared: true
}
});
this.render(this.templates.list, this.contexts.list);
},
_loadDetail: function(data){
var context = {
title: "Blog Post",
blog: data
}
context.blog.date = new Date(context.blog.date);
context.blog.title = this.contexts.list.get("blog_list", {})[data.key].title;
this.contexts.blogs[data.key] = new dojox.dtl.Context(context).extend({
base: {
url: dojo.moduleUrl("dojox.dtl.demos.templates", "blog_base.html"),
shared: true
}
});
this.render(this.templates.detail, this.contexts.blogs[data.key]);
},
_loadPage: function(data){
this.contexts.pages[data.key] = new dojox.dtl.Context(data).extend({
base: {
url: dojo.moduleUrl("dojox.dtl.demos.templates", "blog_base.html"),
shared: true
}
});
this.render(this.templates.page, this.contexts.pages[data.key]);
}
});
 
dojo.require("dojo.parser");
</script>
</head>
<body>
<div dojoType="dojox.dtl.AttachPoint">
<div dojoType="demo.Blog" />
</div>
</body>
</html>