summaryrefslogtreecommitdiff
path: root/js/dojo/dojox/dtl
diff options
context:
space:
mode:
Diffstat (limited to 'js/dojo/dojox/dtl')
-rw-r--r--js/dojo/dojox/dtl/Context.js89
-rw-r--r--js/dojo/dojox/dtl/DomInline.js44
-rw-r--r--js/dojo/dojox/dtl/Inline.js41
-rw-r--r--js/dojo/dojox/dtl/README207
-rw-r--r--js/dojo/dojox/dtl/_DomTemplated.js100
-rw-r--r--js/dojo/dojox/dtl/_Templated.js148
-rw-r--r--js/dojo/dojox/dtl/_base.js766
-rw-r--r--js/dojo/dojox/dtl/contrib/data.js165
-rw-r--r--js/dojo/dojox/dtl/contrib/dijit.js234
-rw-r--r--js/dojo/dojox/dtl/contrib/dom.js177
-rw-r--r--js/dojo/dojox/dtl/contrib/objects.js21
-rw-r--r--js/dojo/dojox/dtl/demos/demo_Animation.html45
-rw-r--r--js/dojo/dojox/dtl/demos/demo_Animation_amd.html53
-rw-r--r--js/dojo/dojox/dtl/demos/demo_Blog.html95
-rw-r--r--js/dojo/dojox/dtl/demos/demo_Data.html59
-rw-r--r--js/dojo/dojox/dtl/demos/demo_Dijitless.html50
-rw-r--r--js/dojo/dojox/dtl/demos/demo_DomTemplated.html44
-rw-r--r--js/dojo/dojox/dtl/demos/demo_DomTemplated_amd.html50
-rw-r--r--js/dojo/dojox/dtl/demos/demo_Events.html46
-rw-r--r--js/dojo/dojox/dtl/demos/demo_Inline.html51
-rw-r--r--js/dojo/dojox/dtl/demos/demo_NodeList.html37
-rw-r--r--js/dojo/dojox/dtl/demos/demo_NodeList_amd.html42
-rw-r--r--js/dojo/dojox/dtl/demos/demo_Table.html4073
-rw-r--r--js/dojo/dojox/dtl/demos/demo_Templated.html36
-rw-r--r--js/dojo/dojox/dtl/demos/demo_Templated_amd.html42
-rw-r--r--js/dojo/dojox/dtl/demos/demo_Tree.html48
-rw-r--r--js/dojo/dojox/dtl/demos/json/blog/get_blog_1.json1
-rw-r--r--js/dojo/dojox/dtl/demos/json/blog/get_blog_3.json1
-rw-r--r--js/dojo/dojox/dtl/demos/json/blog/get_blog_list.json1
-rw-r--r--js/dojo/dojox/dtl/demos/json/blog/get_page_about.json1
-rw-r--r--js/dojo/dojox/dtl/demos/json/fruit.json1
-rw-r--r--js/dojo/dojox/dtl/demos/json/morefruit.json1
-rw-r--r--js/dojo/dojox/dtl/demos/templates/animation.html5
-rw-r--r--js/dojo/dojox/dtl/demos/templates/blog_base.html11
-rw-r--r--js/dojo/dojox/dtl/demos/templates/blog_detail.html10
-rw-r--r--js/dojo/dojox/dtl/demos/templates/blog_list.html9
-rw-r--r--js/dojo/dojox/dtl/demos/templates/blog_page.html7
-rw-r--r--js/dojo/dojox/dtl/demos/templates/gallery.html16
-rw-r--r--js/dojo/dojox/dtl/demos/templates/nodelist.html5
-rw-r--r--js/dojo/dojox/dtl/dom.js1050
-rw-r--r--js/dojo/dojox/dtl/ext-dojo/NodeList.js41
-rw-r--r--js/dojo/dojox/dtl/filter/dates.js68
-rw-r--r--js/dojo/dojox/dtl/filter/htmlstrings.js53
-rw-r--r--js/dojo/dojox/dtl/filter/integers.js38
-rw-r--r--js/dojo/dojox/dtl/filter/lists.js145
-rw-r--r--js/dojo/dojox/dtl/filter/logic.js46
-rw-r--r--js/dojo/dojox/dtl/filter/misc.js66
-rw-r--r--js/dojo/dojox/dtl/filter/strings.js337
-rw-r--r--js/dojo/dojox/dtl/render/dom.js43
-rw-r--r--js/dojo/dojox/dtl/render/html.js14
-rw-r--r--js/dojo/dojox/dtl/tag/date.js39
-rw-r--r--js/dojo/dojox/dtl/tag/loader.js304
-rw-r--r--js/dojo/dojox/dtl/tag/logic.js281
-rw-r--r--js/dojo/dojox/dtl/tag/loop.js202
-rw-r--r--js/dojo/dojox/dtl/tag/misc.js294
-rw-r--r--js/dojo/dojox/dtl/utils/date.js80
56 files changed, 9933 insertions, 0 deletions
diff --git a/js/dojo/dojox/dtl/Context.js b/js/dojo/dojox/dtl/Context.js
new file mode 100644
index 0000000..b9de03b
--- /dev/null
+++ b/js/dojo/dojox/dtl/Context.js
@@ -0,0 +1,89 @@
+//>>built
+define("dojox/dtl/Context", [
+ "dojo/_base/lang",
+ "./_base"
+], function(lang,dd){
+ /*=====
+ dd = dojox.dtl;
+ =====*/
+
+ /*=====
+ dd.Context = function(dict){
+ // summary: Represents a runtime context used by DTL templates.
+ }
+
+ =====*/
+ dd.Context = lang.extend(function(dict){
+ this._this = {};
+ dd._Context.call(this, dict);
+ }, dd._Context.prototype,
+ {
+ getKeys: function(){
+ // summary: Returns the set of keys exported by this context.
+ var keys = [];
+ for(var key in this){
+ if(this.hasOwnProperty(key) && key != "_this"){
+ keys.push(key);
+ }
+ }
+ return keys;
+ },
+ extend: function(/*dojox.dtl.Context|Object*/ obj){
+ // summary: Returns a clone of this context object, with the items from the
+ // passed objecct mixed in.
+ return lang.delegate(this, obj);
+ },
+ 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 dd.Context();
+ var keys = [];
+ var i, arg;
+ if(filter instanceof dd.Context){
+ keys = filter.getKeys();
+ }else if(typeof filter == "object"){
+ for(var key in filter){
+ keys.push(key);
+ }
+ }else{
+ for(i = 0; arg = arguments[i]; i++){
+ if(typeof arg == "string"){
+ keys.push(arg);
+ }
+ }
+ }
+
+ for(i = 0, key; key = keys[i]; i++){
+ context[key] = this[key];
+ }
+
+ return context;
+ },
+ setThis: function(/*Object*/ _this){
+ // summary: Sets the object on which to perform operations.
+ // _this: the this ref.
+ this._this = _this;
+ },
+ getThis: function(){
+ // summary: Gets the object on which to perform operations.
+ return this._this;
+ },
+ hasKey: function(/*String*/key){
+ // summary: Indicates whether the specified key is defined on this context.
+ // key: The key to look up.
+ if(this._getter){
+ var got = this._getter(key);
+ if(typeof got != "undefined"){
+ return true;
+ }
+ }
+
+ if(typeof this[key] != "undefined"){
+ return true;
+ }
+
+ return false;
+ }
+});
+return dojox.dtl.Context;
+}); \ No newline at end of file
diff --git a/js/dojo/dojox/dtl/DomInline.js b/js/dojo/dojox/dtl/DomInline.js
new file mode 100644
index 0000000..2250c81
--- /dev/null
+++ b/js/dojo/dojox/dtl/DomInline.js
@@ -0,0 +1,44 @@
+//>>built
+define("dojox/dtl/DomInline", [
+ "dojo/_base/lang",
+ "./dom",
+ "./_base",
+ "dijit/_WidgetBase"
+], function(lang,ddd,dd,Widget){
+ /*=====
+ dd = dojox.dtl;
+ Widget = dijit._WidgetBase;
+ =====*/
+ dd.DomInline = lang.extend(function(args, node){
+ this.create(args, node);
+ },
+ Widget.prototype,
+ {
+ context: null,
+ render: function(/*dojox.dtl.Context?*/ context){
+ this.context = context || this.context;
+ this.postMixInProperties();
+ var root = this.template.render(this.context).getRootNode();
+ if(root != this.containerNode){
+ this.containerNode.parentNode.replaceChild(root, this.containerNode);
+ this.containerNode = root;
+ }
+ },
+ declaredClass: "dojox.dtl.Inline",
+ buildRendering: function(){
+ var div = this.domNode = document.createElement("div");
+ this.containerNode = div.appendChild(document.createElement("div"));
+ var node = this.srcNodeRef;
+ if(node.parentNode){
+ node.parentNode.replaceChild(div, node);
+ }
+
+ this.template = new dojox.dtl.DomTemplate(lang.trim(node.text), true);
+ this.render();
+ },
+ postMixInProperties: function(){
+ this.context = (this.context.get === dojox.dtl._Context.prototype.get) ? this.context : new dojox.dtl.Context(this.context);
+ }
+ });
+ return dojox.dtl.DomInline;
+}); \ No newline at end of file
diff --git a/js/dojo/dojox/dtl/Inline.js b/js/dojo/dojox/dtl/Inline.js
new file mode 100644
index 0000000..56b1d05
--- /dev/null
+++ b/js/dojo/dojox/dtl/Inline.js
@@ -0,0 +1,41 @@
+//>>built
+define("dojox/dtl/Inline", [
+ "dojo/_base/lang",
+ "./_base",
+ "dijit/_WidgetBase",
+ "dojo/query" // dojo.query
+], function(lang,dd,Widget,Query){
+ /*=====
+ Widget = dijit._WidgetBase;
+ Query = dojo.query;
+ dd = dojox.dtl;
+ =====*/
+ dd.Inline = lang.extend(function(args, node){
+ this.create(args, node);
+ },
+ Widget.prototype,
+ {
+ context: null,
+ render: function(/*Object|dojox.dtl.Context?*/ context){
+ this.context = context || this.context;
+ this.postMixInProperties();
+ Query("*", this.domNode).orphan();
+ this.domNode.innerHTML = this.template.render(this.context);
+ },
+ declaredClass: "dojox.dtl.Inline",
+ buildRendering: function(){
+ var div = this.domNode = document.createElement("div");
+ var node = this.srcNodeRef;
+ if(node.parentNode){
+ node.parentNode.replaceChild(div, node);
+ }
+
+ this.template = new dd.Template(lang.trim(node.text), true);
+ this.render();
+ },
+ postMixInProperties: function(){
+ this.context = (this.context.get === dd._Context.prototype.get) ? this.context : new dd._Context(this.context);
+ }
+ });
+ return dojox.dtl.Inline;
+}); \ No newline at end of file
diff --git a/js/dojo/dojox/dtl/README b/js/dojo/dojox/dtl/README
new file mode 100644
index 0000000..54dd4f3
--- /dev/null
+++ b/js/dojo/dojox/dtl/README
@@ -0,0 +1,207 @@
+-------------------------------------------------------------------------------
+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 is a 1:1 match with the Django Template Language as outlined in
+http://www.djangoproject.com/documentation/templates/. All applicable 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
+
+Note: HTML Unit Tests should only be around for the oddities of HTML, tag/filter
+code is the same for each environment with minor exceptions. Cloning of all tags
+should be tested inside a for loop.
+
+| 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 | |
+| X | firstof | X | |
+| X | for | X | |
+| X | if | X | |
+| X | ifchanged | X | X |
+| X | ifequal | X | |
+| X | ifnotequal | X | |
+| X | include | X | X |
+| X | load | X | |
+| X | now | X | |
+| X | regroup | X | |
+| X | spaceless | X | X |
+| X | ssi | X | X |
+| X | templatetag | X | |
+| N/A | url | | |
+| X | widthratio | X | |
+| X | with | X | |
+
+| 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.DomBuffer.
+
+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.DomNode
+object. Each function in this object is only one line long. \ No newline at end of file
diff --git a/js/dojo/dojox/dtl/_DomTemplated.js b/js/dojo/dojox/dtl/_DomTemplated.js
new file mode 100644
index 0000000..0c952f9
--- /dev/null
+++ b/js/dojo/dojox/dtl/_DomTemplated.js
@@ -0,0 +1,100 @@
+//>>built
+define("dojox/dtl/_DomTemplated", [
+ "dojo/dom-construct",
+ ".",
+ "./contrib/dijit",
+ "./render/dom",
+ "dojo/cache",
+ "dijit/_TemplatedMixin"
+ ], function(domConstruct,dtl,ddcd,ddrd,cache,TemplatedMixin){
+ /*=====
+ dtl = dojox.dtl;
+ cache = dojo.cache;
+ TemplatedMixin = dijit._TemplatedMixin
+ =====*/
+ dtl._DomTemplated = function(){};
+ dtl._DomTemplated.prototype = {
+ _dijitTemplateCompat: false,
+ buildRendering: function(){
+ // summary:
+ // Construct the UI for this widget, setting this.domNode.
+
+ //render needs a domNode to work with
+ this.domNode = this.srcNodeRef;
+
+ if(!this._render){
+ var old = ddcd.widgetsInTemplate;
+ ddcd.widgetsInTemplate = this.widgetsInTemplate;
+ this.template = this.template || this._getCachedTemplate(this.templatePath, this.templateString);
+ this._render = new ddrd.Render(this.domNode, this.template);
+ ddcd.widgetsInTemplate = old;
+ }
+
+ var context = this._getContext();
+ if(!this._created){
+ delete context._getter;
+ }
+ this.render(context);
+
+ this.domNode = this.template.getRootNode();
+ if(this.srcNodeRef && this.srcNodeRef.parentNode){
+ domConstruct.destroy(this.srcNodeRef);
+ delete this.srcNodeRef;
+ }
+ },
+ setTemplate: function(/*String|dojo._Url*/ template, /*dojox.dtl.Context?*/ context){
+ // summary:
+ // Quickly switch between templated by location
+ // template: The new template.
+ // context:
+ // The runtime context.
+ if(dojox.dtl.text._isTemplate(template)){
+ this.template = this._getCachedTemplate(null, template);
+ }else{
+ this.template = this._getCachedTemplate(template);
+ }
+ this.render(context);
+ },
+ render: function(/*dojox.dtl.Context?*/ context, /*dojox.dtl.DomTemplate?*/ tpl){
+ // summary:
+ // Renders this template.
+ // context:
+ // The runtime context.
+ // tpl:
+ // The template to render. Optional.
+ if(tpl){
+ this.template = tpl;
+ }
+ this._render.render(this._getContext(context), this.template);
+ },
+ _getContext: function(context){
+ if(!(context instanceof dojox.dtl.Context)){
+ context = false;
+ }
+ context = context || new dojox.dtl.Context(this);
+ context.setThis(this);
+ return context;
+ },
+ _getCachedTemplate: function(templatePath, templateString){
+ if(!this._templates){
+ this._templates = {};
+ }
+ if(!templateString){
+ templateString = cache(templatePath, {sanitize: true});
+ }
+ var key = templateString;
+ var tmplts = this._templates;
+ if(tmplts[key]){
+ return tmplts[key];
+ }
+ return (tmplts[key] = new dojox.dtl.DomTemplate(
+ TemplatedMixin.getCachedTemplate(
+ templateString,
+ true
+ )
+ ));
+ }
+ };
+ return dojox.dtl._DomTemplated;
+});
+
diff --git a/js/dojo/dojox/dtl/_Templated.js b/js/dojo/dojox/dtl/_Templated.js
new file mode 100644
index 0000000..b2f4387
--- /dev/null
+++ b/js/dojo/dojox/dtl/_Templated.js
@@ -0,0 +1,148 @@
+//>>built
+define("dojox/dtl/_Templated", [
+ "dojo/_base/declare",
+ "./_base",
+ "dijit/_TemplatedMixin",
+ "dojo/dom-construct",
+ "dojo/cache",
+ "dojo/_base/array",
+ "dojo/string",
+ "dojo/parser",
+ "dijit/_base/manager"
+], function(declare,dd,TemplatedMixin, domConstruct,Cache,Array,dString,Parser,dijitMgr){
+ /*=====
+ Cache = dojo.cache;
+ dString = dojo.string;
+ Parser = dojo.parser;
+ TemplatedMixin = dijit._TemplatedMixin;
+ dd = dojox.dtl;
+ =====*/
+ return declare("dojox.dtl._Templated", TemplatedMixin, {
+ // summary: The base-class for DTL-templated widgets.
+
+ _dijitTemplateCompat: false,
+ buildRendering: function(){
+ // summary: The method overrides dijit._TemplatedMixin.startup.
+ var node;
+
+ if(this.domNode && !this._template){
+ return;
+ }
+
+ if(!this._template){
+ var t = this.getCachedTemplate(
+ this.templatePath,
+ this.templateString,
+ this._skipNodeCache
+ );
+ if(t instanceof dd.Template) {
+ this._template = t;
+ }else{
+ node = t;
+ }
+ }
+ if(!node){
+ var context = new dd._Context(this);
+ if(!this._created){
+ delete context._getter;
+ }
+ var nodes = domConstruct.toDom(
+ this._template.render(context)
+ );
+ // TODO: is it really necessary to look for the first node?
+ if(nodes.nodeType !== 1 && nodes.nodeType !== 3){
+ // nodes.nodeType === 11
+ // the node is a document fragment
+ for(var i = 0, l = nodes.childNodes.length; i < l; ++i){
+ node = nodes.childNodes[i];
+ if(node.nodeType == 1){
+ break;
+ }
+ }
+ }else{
+ // the node is an element or a text
+ node = nodes;
+ }
+ }
+ this._attachTemplateNodes(node, function(n,p){
+ return n.getAttribute(p);
+ });
+ if(this.widgetsInTemplate){
+ //Make sure dojoType is used for parsing widgets in template.
+ //The Parser.query could be changed from multiversion support.
+ var parser = Parser, qry, attr;
+ if(parser._query != "[dojoType]"){
+ qry = parser._query;
+ attr = parser._attrName;
+ parser._query = "[dojoType]";
+ parser._attrName = "dojoType";
+ }
+
+ //Store widgets that we need to start at a later point in time
+ var cw = (this._startupWidgets = Parser.parse(node, {
+ noStart: !this._earlyTemplatedStartup,
+ inherited: {dir: this.dir, lang: this.lang}
+ }));
+
+ //Restore the query.
+ if(qry){
+ parser._query = qry;
+ parser._attrName = attr;
+ }
+
+ this._supportingWidgets = dijitMgr.findWidgets(node);
+
+ this._attachTemplateNodes(cw, function(n,p){
+ return n[p];
+ });
+ }
+
+ if(this.domNode){
+ domConstruct.place(node, this.domNode, "before");
+ this.destroyDescendants();
+ domConstruct.destroy(this.domNode);
+ }
+ this.domNode = node;
+
+ this._fillContent(this.srcNodeRef);
+ },
+ _templateCache: {},
+ getCachedTemplate: function(templatePath, templateString, alwaysUseString){
+ // summary:
+ // Layer for dijit._Templated.getCachedTemplate
+ var tmplts = this._templateCache;
+ var key = templateString || templatePath;
+ if(tmplts[key]){
+ return tmplts[key];
+ }
+
+ templateString = dString.trim(templateString || Cache(templatePath, {sanitize: true}));
+
+ if( this._dijitTemplateCompat &&
+ (alwaysUseString || templateString.match(/\$\{([^\}]+)\}/g))
+ ){
+ templateString = this._stringRepl(templateString);
+ }
+
+ // If we always use a string, or find no variables, just store it as a node
+ if(alwaysUseString || !templateString.match(/\{[{%]([^\}]+)[%}]\}/g)){
+ return tmplts[key] = domConstruct.toDom(templateString);
+ }else{
+ return tmplts[key] = new dd.Template(templateString);
+ }
+ },
+ render: function(){
+ // summary: Renders the widget.
+ this.buildRendering();
+ },
+ startup: function(){
+ // summary: The method overrides dijit._TemplatedMixin.startup.
+ Array.forEach(this._startupWidgets, function(w){
+ if(w && !w._started && w.startup){
+ w.startup();
+ }
+ });
+ this.inherited(arguments);
+ }
+ });
+}); \ No newline at end of file
diff --git a/js/dojo/dojox/dtl/_base.js b/js/dojo/dojox/dtl/_base.js
new file mode 100644
index 0000000..3f11bb1
--- /dev/null
+++ b/js/dojo/dojox/dtl/_base.js
@@ -0,0 +1,766 @@
+//>>built
+define("dojox/dtl/_base", [
+ "dojo/_base/kernel",
+ "dojo/_base/lang",
+ "dojox/string/tokenize",
+ "dojo/_base/json",
+ "dojo/dom",
+ "dojo/_base/xhr",
+ "dojox/string/Builder",
+ "dojo/_base/Deferred"],
+ function(kernel, lang, Tokenize, json, dom, xhr, StringBuilder, deferred){
+ /*=====
+ Tokenize = dojox.string.tokenize;
+ StringBuilder = dojox.string.Builder;
+ =====*/
+ kernel.experimental("dojox.dtl");
+ var dd = lang.getObject("dojox.dtl", true);
+ dd._base = {};
+ /*=====
+ dd = dojox.dtl;
+ =====*/
+
+ dd.TOKEN_BLOCK = -1;
+ dd.TOKEN_VAR = -2;
+ dd.TOKEN_COMMENT = -3;
+ dd.TOKEN_TEXT = 3;
+
+ /*=====
+ dd._Context = function(dict){
+ // summary: Pass one of these when rendering a template to tell the template what values to use.
+ }
+ =====*/
+ dd._Context = lang.extend(function(dict){
+ // summary: Pass one of these when rendering a template to tell the template what values to use.
+ if(dict){
+ lang._mixin(this, dict);
+ if(dict.get){
+ // Preserve passed getter and restore prototype get
+ this._getter = dict.get;
+ delete this.get;
+ }
+ }
+ },
+ {
+ push: function(){
+ var last = this;
+ var context = lang.delegate(this);
+ context.pop = function(){ return last; }
+ return context;
+ },
+ pop: function(){
+ throw new Error("pop() called on empty Context");
+ },
+ get: function(key, otherwise){
+ var n = this._normalize;
+
+ if(this._getter){
+ var got = this._getter(key);
+ if(got !== undefined){
+ return n(got);
+ }
+ }
+
+ if(this[key] !== undefined){
+ return n(this[key]);
+ }
+
+ return otherwise;
+ },
+ _normalize: function(value){
+ if(value instanceof Date){
+ value.year = value.getFullYear();
+ value.month = value.getMonth() + 1;
+ value.day = value.getDate();
+ value.date = value.year + "-" + ("0" + value.month).slice(-2) + "-" + ("0" + value.day).slice(-2);
+ value.hour = value.getHours();
+ value.minute = value.getMinutes();
+ value.second = value.getSeconds();
+ value.microsecond = value.getMilliseconds();
+ }
+ return value;
+ },
+ update: function(dict){
+ var context = this.push();
+ if(dict){
+ lang._mixin(this, dict);
+ }
+ return context;
+ }
+ });
+
+ var smart_split_re = /("(?:[^"\\]*(?:\\.[^"\\]*)*)"|'(?:[^'\\]*(?:\\.[^'\\]*)*)'|[^\s]+)/g;
+ var split_re = /\s+/g;
+ var split = function(/*String|RegExp?*/ splitter, /*Integer?*/ limit){
+ splitter = splitter || split_re;
+ if(!(splitter instanceof RegExp)){
+ splitter = new RegExp(splitter, "g");
+ }
+ if(!splitter.global){
+ throw new Error("You must use a globally flagged RegExp with split " + splitter);
+ }
+ splitter.exec(""); // Reset the global
+
+ var part, parts = [], lastIndex = 0, i = 0;
+ while((part = splitter.exec(this))){
+ parts.push(this.slice(lastIndex, splitter.lastIndex - part[0].length));
+ lastIndex = splitter.lastIndex;
+ if(limit && (++i > limit - 1)){
+ break;
+ }
+ }
+ parts.push(this.slice(lastIndex));
+ return parts;
+ }
+
+ dd.Token = function(token_type, contents){
+ this.token_type = token_type;
+ this.contents = new String(lang.trim(contents));
+ this.contents.split = split;
+ this.split = function(){
+ return String.prototype.split.apply(this.contents, arguments);
+ }
+ }
+ dd.Token.prototype.split_contents = function(/*Integer?*/ limit){
+ var bit, bits = [], i = 0;
+ limit = limit || 999;
+ while(i++ < limit && (bit = smart_split_re.exec(this.contents))){
+ bit = bit[0];
+ if(bit.charAt(0) == '"' && bit.slice(-1) == '"'){
+ bits.push('"' + bit.slice(1, -1).replace('\\"', '"').replace('\\\\', '\\') + '"');
+ }else if(bit.charAt(0) == "'" && bit.slice(-1) == "'"){
+ bits.push("'" + bit.slice(1, -1).replace("\\'", "'").replace('\\\\', '\\') + "'");
+ }else{
+ bits.push(bit);
+ }
+ }
+ return bits;
+ }
+
+ var ddt = dd.text = {
+ _get: function(module, name, errorless){
+ // summary: Used to find both tags and filters
+ var params = dd.register.get(module, name.toLowerCase(), errorless);
+ if(!params){
+ if(!errorless){
+ throw new Error("No tag found for " + name);
+ }
+ return null;
+ }
+
+ var fn = params[1];
+ var deps = params[2];
+
+ var parts;
+ if(fn.indexOf(":") != -1){
+ parts = fn.split(":");
+ fn = parts.pop();
+ }
+
+// FIXME: THIS DESIGN DOES NOT WORK WITH ASYNC LOADERS!
+ var mod = deps;
+ if (/\./.test(deps)) {
+ deps = deps.replace(/\./g, "/");
+ }
+ require([deps], function(){});
+
+ var parent = lang.getObject(mod);
+
+ return parent[fn || name] || parent[name + "_"] || parent[fn + "_"];
+ },
+ getTag: function(name, errorless){
+ return ddt._get("tag", name, errorless);
+ },
+ getFilter: function(name, errorless){
+ return ddt._get("filter", name, errorless);
+ },
+ getTemplate: function(file){
+ return new dd.Template(ddt.getTemplateString(file));
+ },
+ getTemplateString: function(file){
+ return xhr._getText(file.toString()) || "";
+ },
+ _resolveLazy: function(location, sync, json){
+ if(sync){
+ if(json){
+ return json.fromJson(xhr._getText(location)) || {};
+ }else{
+ return dd.text.getTemplateString(location);
+ }
+ }else{
+ return xhr.get({
+ handleAs: json ? "json" : "text",
+ url: location
+ });
+ }
+ },
+ _resolveTemplateArg: function(arg, sync){
+ if(ddt._isTemplate(arg)){
+ if(!sync){
+ var d = new deferred();
+ d.callback(arg);
+ return d;
+ }
+ return arg;
+ }
+ return ddt._resolveLazy(arg, sync);
+ },
+ _isTemplate: function(arg){
+ return (arg === undefined) || (typeof arg == "string" && (arg.match(/^\s*[<{]/) || arg.indexOf(" ") != -1));
+ },
+ _resolveContextArg: function(arg, sync){
+ if(arg.constructor == Object){
+ if(!sync){
+ var d = new deferred;
+ d.callback(arg);
+ return d;
+ }
+ return arg;
+ }
+ return ddt._resolveLazy(arg, sync, true);
+ },
+ _re: /(?:\{\{\s*(.+?)\s*\}\}|\{%\s*(load\s*)?(.+?)\s*%\})/g,
+ tokenize: function(str){
+ return Tokenize(str, ddt._re, ddt._parseDelims);
+ },
+ _parseDelims: function(varr, load, tag){
+ if(varr){
+ return [dd.TOKEN_VAR, varr];
+ }else if(load){
+ var parts = lang.trim(tag).split(/\s+/g);
+ for(var i = 0, part; part = parts[i]; i++){
+ if (/\./.test(part)){
+ part = part.replace(/\./g,"/");
+ }
+ require([part]);
+ }
+ }else{
+ return [dd.TOKEN_BLOCK, tag];
+ }
+ }
+ }
+
+ /*=====
+ dd.Template = function(template, isString){
+ // summary:
+ // The base class for text-based templates.
+ // template: String|dojo._Url
+ // The string or location of the string to
+ // use as a template
+ // isString: Boolean
+ // Indicates whether the template is a string or a url.
+ };
+ dd.Template.prototype.update= function(node, context){
+ // summary:
+ // Updates this template according to the given context.
+ // node: DOMNode|String|dojo.NodeList
+ // A node reference or set of nodes
+ // context: dojo._Url|String|Object
+ // The context object or location
+ }
+ dd.Template.prototype.render= function(context, buffer){
+ // summary:
+ // Renders this template.
+ // context: Object
+ // The runtime context.
+ // buffer: StringBuilder?
+ // A string buffer.
+ }
+
+ =====*/
+ dd.Template = lang.extend(function(/*String|dojo._Url*/ template, /*Boolean*/ isString){
+ // template:
+ // The string or location of the string to
+ // use as a template
+ var str = isString ? template : ddt._resolveTemplateArg(template, true) || "";
+ var tokens = ddt.tokenize(str);
+ var parser = new dd._Parser(tokens);
+ this.nodelist = parser.parse();
+ },
+ {
+ update: function(node, context){
+ // summary:
+ // Updates this template according to the given context.
+ // node: DOMNode|String|dojo.NodeList
+ // A node reference or set of nodes
+ // context: dojo._Url|String|Object
+ // The context object or location
+ return ddt._resolveContextArg(context).addCallback(this, function(contextObject){
+ var content = this.render(new dd._Context(contextObject));
+ if(node.forEach){
+ node.forEach(function(item){
+ item.innerHTML = content;
+ });
+ }else{
+ dom.byId(node).innerHTML = content;
+ }
+ return this;
+ });
+ },
+ render: function(context, /*concatenatable?*/ buffer){
+ buffer = buffer || this.getBuffer();
+ context = context || new dd._Context({});
+ return this.nodelist.render(context, buffer) + "";
+ },
+ getBuffer: function(){
+ return new StringBuilder();
+ }
+ });
+
+ var qfRe = /\{\{\s*(.+?)\s*\}\}/g;
+ dd.quickFilter = function(str){
+ if(!str){
+ return new dd._NodeList();
+ }
+
+ if(str.indexOf("{%") == -1){
+ return new dd._QuickNodeList(Tokenize(str, qfRe, function(token){
+ return new dd._Filter(token);
+ }));
+ }
+ }
+
+ dd._QuickNodeList = lang.extend(function(contents){
+ this.contents = contents;
+ },
+ {
+ render: function(context, buffer){
+ for(var i = 0, l = this.contents.length; i < l; i++){
+ if(this.contents[i].resolve){
+ buffer = buffer.concat(this.contents[i].resolve(context));
+ }else{
+ buffer = buffer.concat(this.contents[i]);
+ }
+ }
+ return buffer;
+ },
+ dummyRender: function(context){ return this.render(context, dd.Template.prototype.getBuffer()).toString(); },
+ clone: function(buffer){ return this; }
+ });
+
+ dd._Filter = lang.extend(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 cache = this._cache[token];
+ if(cache){
+ this.key = cache[0];
+ this.filters = cache[1];
+ }else{
+ this.filters = [];
+ Tokenize(token, this._re, this._tokenize, this);
+ this._cache[token] = [this.key, this.filters];
+ }
+ },
+ {
+ _cache: {},
+ _re: /(?:^_\("([^\\"]*(?:\\.[^\\"])*)"\)|^"([^\\"]*(?:\\.[^\\"]*)*)"|^([a-zA-Z0-9_.]+)|\|(\w+)(?::(?:_\("([^\\"]*(?:\\.[^\\"])*)"\)|"([^\\"]*(?:\\.[^\\"]*)*)"|([a-zA-Z0-9_.]+)|'([^\\']*(?:\\.[^\\']*)*)'))?|^'([^\\']*(?:\\.[^\\']*)*)')/g,
+ _values: {
+ 0: '"', // _("text")
+ 1: '"', // "text"
+ 2: "", // variable
+ 8: '"' // 'text'
+ },
+ _args: {
+ 4: '"', // :_("text")
+ 5: '"', // :"text"
+ 6: "", // :variable
+ 7: "'"// :'text'
+ },
+ _tokenize: function(){
+ var pos, arg;
+
+ for(var i = 0, has = []; i < arguments.length; i++){
+ has[i] = (arguments[i] !== undefined && typeof arguments[i] == "string" && arguments[i]);
+ }
+
+ if(!this.key){
+ for(pos in this._values){
+ if(has[pos]){
+ this.key = this._values[pos] + arguments[pos] + this._values[pos];
+ break;
+ }
+ }
+ }else{
+ for(pos in this._args){
+ if(has[pos]){
+ var value = arguments[pos];
+ if(this._args[pos] == "'"){
+ value = value.replace(/\\'/g, "'");
+ }else if(this._args[pos] == '"'){
+ value = value.replace(/\\"/g, '"');
+ }
+ arg = [!this._args[pos], value];
+ break;
+ }
+ }
+ // Get a named filter
+ var fn = ddt.getFilter(arguments[3]);
+ if(!lang.isFunction(fn)) throw new Error(arguments[3] + " is not registered as a filter");
+ this.filters.push([fn, arg]);
+ }
+ },
+ getExpression: function(){
+ return this.contents;
+ },
+ resolve: function(context){
+ if(this.key === undefined){
+ return "";
+ }
+
+ 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.slice(-1);
+ if(!isNaN(parseInt(first))){
+ current = (path.indexOf(".") == -1) ? parseInt(path) : parseFloat(path);
+ }else if(first == '"' && first == last){
+ current = path.slice(1, -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[0]);
+
+ if(lang.isFunction(current)){
+ var self = context.getThis && context.getThis();
+ if(current.alters_data){
+ current = "";
+ }else if(self){
+ current = current.call(self);
+ }else{
+ current = "";
+ }
+ }
+
+ for(var i = 1; i < parts.length; i++){
+ var part = parts[i];
+ if(current){
+ var base = current;
+ if(lang.isObject(current) && part == "items" && current[part] === undefined){
+ var items = [];
+ for(var key in current){
+ items.push([key, current[key]]);
+ }
+ current = items;
+ continue;
+ }
+
+ if(current.get && lang.isFunction(current.get) && current.get.safe){
+ current = current.get(part);
+ }else if(current[part] === undefined){
+ current = current[part];
+ break;
+ }else{
+ current = current[part];
+ }
+
+ if(lang.isFunction(current)){
+ if(current.alters_data){
+ current = "";
+ }else{
+ current = current.call(base);
+ }
+ }else if(current instanceof Date){
+ current = dd._Context.prototype._normalize(current);
+ }
+ }else{
+ return "";
+ }
+ }
+ }
+ return current;
+ }
+ });
+
+ dd._TextNode = dd._Node = lang.extend(function(/*Object*/ obj){
+ // summary: Basic catch-all node
+ this.contents = obj;
+ },
+ {
+ set: function(data){
+ this.contents = data;
+ return this;
+ },
+ render: function(context, buffer){
+ // summary: Adds content onto the buffer
+ return buffer.concat(this.contents);
+ },
+ isEmpty: function(){
+ return !lang.trim(this.contents);
+ },
+ clone: function(){ return this; }
+ });
+
+ dd._NodeList = lang.extend(function(/*Node[]*/ nodes){
+ // summary: Allows us to render a group of nodes
+ this.contents = nodes || [];
+ this.last = "";
+ },
+ {
+ push: function(node){
+ // summary: Add a new node to the list
+ this.contents.push(node);
+ return this;
+ },
+ concat: function(nodes){
+ this.contents = this.contents.concat(nodes);
+ return this;
+ },
+ 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 must return buffer");
+ }
+ return buffer;
+ },
+ dummyRender: function(context){
+ return this.render(context, dd.Template.prototype.getBuffer()).toString();
+ },
+ unrender: function(){ return arguments[1]; },
+ clone: function(){ return this; },
+ rtrim: function(){
+ while(1){
+ i = this.contents.length - 1;
+ if(this.contents[i] instanceof dd._TextNode && this.contents[i].isEmpty()){
+ this.contents.pop();
+ }else{
+ break;
+ }
+ }
+
+ return this;
+ }
+ });
+
+ dd._VarNode = lang.extend(function(str){
+ // summary: A node to be processed as a variable
+ this.contents = new dd._Filter(str);
+ },
+ {
+ render: function(context, buffer){
+ var str = this.contents.resolve(context);
+ if(!str.safe){
+ str = dd._base.escape("" + str);
+ }
+ return buffer.concat(str);
+ }
+ });
+
+ dd._noOpNode = new function(){
+ // summary: Adds a no-op node. Useful in custom tags
+ this.render = this.unrender = function(){ return arguments[1]; }
+ this.clone = function(){ return this; }
+ }
+
+ dd._Parser = lang.extend(function(tokens){
+ // summary: Parser used during initialization and for tag groups.
+ this.contents = tokens;
+ },
+ {
+ i: 0,
+ 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 terminators = {}, token;
+ stop_at = stop_at || [];
+ for(var i = 0; i < stop_at.length; i++){
+ terminators[stop_at[i]] = true;
+ }
+
+ var nodelist = new dd._NodeList();
+ while(this.i < this.contents.length){
+ token = this.contents[this.i++];
+ if(typeof token == "string"){
+ nodelist.push(new dd._TextNode(token));
+ }else{
+ var type = token[0];
+ var text = token[1];
+ if(type == dd.TOKEN_VAR){
+ nodelist.push(new dd._VarNode(text));
+ }else if(type == dd.TOKEN_BLOCK){
+ if(terminators[text]){
+ --this.i;
+ return nodelist;
+ }
+ var cmd = text.split(/\s+/g);
+ if(cmd.length){
+ cmd = cmd[0];
+ var fn = ddt.getTag(cmd);
+ if(fn){
+ nodelist.push(fn(this, new dd.Token(type, text)));
+ }
+ }
+ }
+ }
+ }
+
+ if(stop_at.length){
+ throw new Error("Could not find closing tag(s): " + stop_at.toString());
+ }
+
+ this.contents.length = 0;
+ return nodelist;
+ },
+ next_token: function(){
+ // summary: Returns the next token in the list.
+ var token = this.contents[this.i++];
+ return new dd.Token(token[0], token[1]);
+ },
+ delete_first_token: function(){
+ this.i++;
+ },
+ skip_past: function(endtag){
+ while(this.i < this.contents.length){
+ var token = this.contents[this.i++];
+ if(token[0] == dd.TOKEN_BLOCK && token[1] == endtag){
+ return;
+ }
+ }
+ throw new Error("Unclosed tag found when looking for " + endtag);
+ },
+ create_variable_node: function(expr){
+ return new dd._VarNode(expr);
+ },
+ create_text_node: function(expr){
+ return new dd._TextNode(expr || "");
+ },
+ getTemplate: function(file){
+ return new dd.Template(file);
+ }
+ });
+
+ dd.register = {
+ _registry: {
+ attributes: [],
+ tags: [],
+ filters: []
+ },
+ get: function(/*String*/ module, /*String*/ name){
+ var registry = dd.register._registry[module + "s"];
+ for(var i = 0, entry; entry = registry[i]; i++){
+ if(typeof entry[0] == "string"){
+ if(entry[0] == name){
+ return entry;
+ }
+ }else if(name.match(entry[0])){
+ return entry;
+ }
+ }
+ },
+ getAttributeTags: function(){
+ var tags = [];
+ var registry = dd.register._registry.attributes;
+ for(var i = 0, entry; entry = registry[i]; i++){
+ if(entry.length == 3){
+ tags.push(entry);
+ }else{
+ var fn = lang.getObject(entry[1]);
+ if(fn && lang.isFunction(fn)){
+ entry.push(fn);
+ tags.push(entry);
+ }
+ }
+ }
+ return tags;
+ },
+ _any: function(type, base, locations){
+ for(var path in locations){
+ for(var i = 0, fn; fn = locations[path][i]; i++){
+ var key = fn;
+ if(lang.isArray(fn)){
+ key = fn[0];
+ fn = fn[1];
+ }
+ if(typeof key == "string"){
+ if(key.substr(0, 5) == "attr:"){
+ var attr = fn;
+ if(attr.substr(0, 5) == "attr:"){
+ attr = attr.slice(5);
+ }
+ dd.register._registry.attributes.push([attr.toLowerCase(), base + "." + path + "." + attr]);
+ }
+ key = key.toLowerCase()
+ }
+ dd.register._registry[type].push([
+ key,
+ fn,
+ base + "." + path
+ ]);
+ }
+ }
+ },
+ tags: function(/*String*/ base, /*Object*/ locations){
+ dd.register._any("tags", base, locations);
+ },
+ filters: function(/*String*/ base, /*Object*/ locations){
+ dd.register._any("filters", base, locations);
+ }
+ }
+
+ var escapeamp = /&/g;
+ var escapelt = /</g;
+ var escapegt = />/g;
+ var escapeqt = /'/g;
+ var escapedblqt = /"/g;
+ dd._base.escape = function(value){
+ // summary: Escapes a string's HTML
+ return dd.mark_safe(value.replace(escapeamp, '&amp;').replace(escapelt, '&lt;').replace(escapegt, '&gt;').replace(escapedblqt, '&quot;').replace(escapeqt, '&#39;'));
+ }
+
+ dd._base.safe = function(value){
+ if(typeof value == "string"){
+ value = new String(value);
+ }
+ if(typeof value == "object"){
+ value.safe = true;
+ }
+ return value;
+ }
+ dd.mark_safe = dd._base.safe;
+
+ dd.register.tags("dojox.dtl.tag", {
+ "date": ["now"],
+ "logic": ["if", "for", "ifequal", "ifnotequal"],
+ "loader": ["extends", "block", "include", "load", "ssi"],
+ "misc": ["comment", "debug", "filter", "firstof", "spaceless", "templatetag", "widthratio", "with"],
+ "loop": ["cycle", "ifchanged", "regroup"]
+ });
+ dd.register.filters("dojox.dtl.filter", {
+ "dates": ["date", "time", "timesince", "timeuntil"],
+ "htmlstrings": ["linebreaks", "linebreaksbr", "removetags", "striptags"],
+ "integers": ["add", "get_digit"],
+ "lists": ["dictsort", "dictsortreversed", "first", "join", "length", "length_is", "random", "slice", "unordered_list"],
+ "logic": ["default", "default_if_none", "divisibleby", "yesno"],
+ "misc": ["filesizeformat", "pluralize", "phone2numeric", "pprint"],
+ "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"]
+ });
+ dd.register.filters("dojox.dtl", {
+ "_base": ["escape", "safe"]
+ });
+ return dd;
+});
+
diff --git a/js/dojo/dojox/dtl/contrib/data.js b/js/dojo/dojox/dtl/contrib/data.js
new file mode 100644
index 0000000..490119c
--- /dev/null
+++ b/js/dojo/dojox/dtl/contrib/data.js
@@ -0,0 +1,165 @@
+//>>built
+define("dojox/dtl/contrib/data", [
+ "dojo/_base/kernel",
+ "dojo/_base/lang",
+ "../_base",
+ "dojo/_base/array"
+], function(kernel,lang,dd,array){
+ /*=====
+ dd = dojox.dtl;
+ =====*/
+ lang.getObject("dojox.dtl.contrib.data", true);
+
+ var ddcd = dd.contrib.data;
+ var first = true;
+
+ ddcd._BoundItem = lang.extend(function(item, store){
+ this.item = item;
+ this.store = store;
+ },
+ {
+ get: function(key){
+ var store = this.store;
+ var item = this.item;
+
+ if(key == "getLabel"){
+ return store.getLabel(item);
+ }else if(key == "getAttributes"){
+ return store.getAttributes(item);
+ }else if(key == "getIdentity"){
+ if(store.getIdentity){
+ return store.getIdentity(item);
+ }
+ return "Store has no identity API";
+ }else{
+ if(!store.hasAttribute(item, key)){
+ if(key.slice(-1) == "s"){
+ if(first){
+ first = false;
+ kernel.deprecated("You no longer need an extra s to call getValues, it can be figured out automatically");
+ }
+ key = key.slice(0, -1);
+ }
+ if(!store.hasAttribute(item, key)){
+ return;
+ }
+ }
+
+ var values = store.getValues(item, key);
+ if(!values){
+ return;
+ }
+ if(!lang.isArray(values)){
+ return new ddcd._BoundItem(values, store);
+ }
+
+ values = array.map(values, function(value){
+ if(lang.isObject(value) && store.isItem(value)){
+ return new ddcd._BoundItem(value, store);
+ }
+ return value;
+ });
+ values.get = ddcd._get;
+ return values;
+ }
+ }
+ });
+ ddcd._BoundItem.prototype.get.safe = true;
+
+ ddcd.BindDataNode = lang.extend(function(items, query, store, alias){
+ this.items = items && new dd._Filter(items);
+ this.query = query && new dd._Filter(query);
+ this.store = new dd._Filter(store);
+ this.alias = alias;
+ },
+ {
+ render: function(context, buffer){
+ var items = this.items && this.items.resolve(context);
+ var query = this.query && this.query.resolve(context);
+ var store = this.store.resolve(context);
+ if(!store || !store.getFeatures){
+ throw new Error("data_bind didn't receive a store");
+ }
+
+ if(query){
+ var sync = false;
+
+ store.fetch({
+ query: query,
+ sync: true,
+ scope: this,
+ onComplete: function(it){
+ sync = true;
+ items = it;
+ }
+ });
+
+ if(!sync){
+ throw new Error("The bind_data tag only works with a query if the store executed synchronously");
+ }
+ }
+
+ var list = [];
+
+ if(items){
+ for(var i = 0, item; item = items[i]; i++){
+ list.push(new ddcd._BoundItem(item, store));
+ }
+ }
+
+ context[this.alias] = list;
+ return buffer;
+ },
+ unrender: function(context, buffer){
+ return buffer;
+ },
+ clone: function(){
+ return this;
+ }
+ });
+
+ lang.mixin(ddcd, {
+ _get: function(key){
+ if(this.length){
+ return (this[0] instanceof ddcd._BoundItem) ? this[0].get(key) : this[0][key];
+ }
+ },
+ bind_data: function(parser, token){
+ // summary: Turns a list of data store items into DTL compatible items
+ // example:
+ // `contextItems` and `contextStore` should be an item list
+ // and a data store that get assigned to `newVariable`
+ //
+ // | {% bind_data contextItems to contextStore as newVariable %}
+ var parts = token.contents.split();
+
+ if(parts[2] != 'to' || parts[4] != 'as' || !parts[5]){
+ throw new Error("data_bind expects the format: 'data_bind items to store as varName'");
+ }
+
+ return new ddcd.BindDataNode(parts[1], null, parts[3], parts[5]);
+ },
+ bind_query: function(parser, token){
+ // summary: Queries a data store and makes the returned items DTL compatible
+ // example:
+ // You can only use this with data stores that work in a synchronous
+ // way (meaning that `onComplete` is fired during the `fetch` call).
+ // A `sync` flag is sent to the fetch call so that stores that usually
+ // work asynchronously make themselves syncrhonous if possible.
+ // | {% bind_query contextQuery to contextStore as newVariable %}
+ var parts = token.contents.split();
+
+ if(parts[2] != 'to' || parts[4] != 'as' || !parts[5]){
+ throw new Error("data_bind expects the format: 'bind_query query to store as varName'");
+ }
+
+ return new ddcd.BindDataNode(null, parts[1], parts[3], parts[5]);
+ }
+ });
+ ddcd._get.safe = true;
+
+ dd.register.tags("dojox.dtl.contrib", {
+ "data": ["bind_data", "bind_query"]
+ });
+ return dojox.dtl.contrib.data;
+}); \ No newline at end of file
diff --git a/js/dojo/dojox/dtl/contrib/dijit.js b/js/dojo/dojox/dtl/contrib/dijit.js
new file mode 100644
index 0000000..6b54320
--- /dev/null
+++ b/js/dojo/dojox/dtl/contrib/dijit.js
@@ -0,0 +1,234 @@
+//>>built
+define("dojox/dtl/contrib/dijit", [
+ "dojo/_base/lang",
+ "dojo/_base/connect",
+ "dojo/_base/array",
+ "dojo/query",
+ "../_base",
+ "../dom",
+ "dojo/parser",
+ "dojo/_base/sniff"
+], function(lang,connect,array,Query,dd,dxdom,Parser,has){
+ /*=====
+ Query = dojo.query;
+ Parser = dojo.parser;
+ dd = dojox.dtl;
+ =====*/
+ lang.getObject("dojox.dtl.contrib.dijit", true);
+ var ddcd = dd.contrib.dijit;
+ ddcd.AttachNode = lang.extend(function(keys, object){
+ this._keys = keys;
+ this._object = object;
+ },
+ {
+ render: function(context, buffer){
+ if(!this._rendered){
+ this._rendered = true;
+ for(var i = 0, key; key = this._keys[i]; i++){
+ context.getThis()[key] = this._object || buffer.getParent();
+ }
+ }
+ return buffer;
+ },
+ unrender: function(context, buffer){
+ if(this._rendered){
+ this._rendered = false;
+ for(var i = 0, key; key = this._keys[i]; i++){
+ if(context.getThis()[key] === (this._object || buffer.getParent())){
+ delete context.getThis()[key];
+ }
+ }
+ }
+ return buffer;
+ },
+ clone: function(buffer){
+ return new this.constructor(this._keys, this._object);
+ }
+ });
+
+ ddcd.EventNode = lang.extend(function(command, obj){
+ this._command = command;
+
+ var type, events = command.split(/\s*,\s*/);
+ var trim = lang.trim;
+ var types = [];
+ var fns = [];
+ while(type = events.pop()){
+ if(type){
+ var fn = null;
+ if(type.indexOf(":") != -1){
+ // oh, if only JS had tuple assignment
+ var funcNameArr = type.split(":");
+ type = trim(funcNameArr[0]);
+ fn = trim(funcNameArr.slice(1).join(":"));
+ }else{
+ type = trim(type);
+ }
+ if(!fn){
+ fn = type;
+ }
+ types.push(type);
+ fns.push(fn);
+ }
+ }
+
+ this._types = types;
+ this._fns = fns;
+ this._object = obj;
+ this._rendered = [];
+ },
+ {
+ // _clear: Boolean
+ // Make sure we kill the actual tags (onclick problems, etc)
+ _clear: false,
+ render: function(context, buffer){
+ for(var i = 0, type; type = this._types[i]; i++){
+ if(!this._clear && !this._object){
+ buffer.getParent()[type] = null;
+ }
+ var fn = this._fns[i];
+ var args;
+ if(fn.indexOf(" ") != -1){
+ if(this._rendered[i]){
+ connect.disconnect(this._rendered[i]);
+ this._rendered[i] = false;
+ }
+ args = array.map(fn.split(" ").slice(1), function(item){
+ return new dd._Filter(item).resolve(context);
+ });
+ fn = fn.split(" ", 2)[0];
+ }
+ if(!this._rendered[i]){
+ if(!this._object){
+ this._rendered[i] = buffer.addEvent(context, type, fn, args);
+ }else{
+ this._rendered[i] = connect.connect(this._object, type, context.getThis(), fn);
+ }
+ }
+ }
+ this._clear = true;
+
+ return buffer;
+ },
+ unrender: function(context, buffer){
+ while(this._rendered.length){
+ connect.disconnect(this._rendered.pop());
+ }
+ return buffer;
+ },
+ clone: function(){
+ return new this.constructor(this._command, this._object);
+ }
+ });
+
+ function cloneNode(n1){
+ var n2 = n1.cloneNode(true);
+ if(has("ie")){
+ Query("script", n2).forEach("item.text = this[index].text;", Query("script", n1));
+ }
+ return n2;
+ }
+
+ ddcd.DojoTypeNode = lang.extend(function(node, parsed){
+ this._node = node;
+ this._parsed = parsed;
+
+ var events = node.getAttribute("dojoAttachEvent") || node.getAttribute("data-dojo-attach-event");
+ if(events){
+ this._events = new ddcd.EventNode(lang.trim(events));
+ }
+ var attach = node.getAttribute("dojoAttachPoint") || node.getAttribute("data-dojo-attach-point");
+ if(attach){
+ this._attach = new ddcd.AttachNode(lang.trim(attach).split(/\s*,\s*/));
+ }
+
+ if(!parsed){
+ this._dijit = Parser.instantiate([cloneNode(node)])[0];
+ }else{
+ node = cloneNode(node);
+ var old = ddcd.widgetsInTemplate;
+ ddcd.widgetsInTemplate = false;
+ this._template = new dd.DomTemplate(node);
+ ddcd.widgetsInTemplate = old;
+ }
+ },
+ {
+ render: function(context, buffer){
+ if(this._parsed){
+ var _buffer = new dd.DomBuffer();
+ this._template.render(context, _buffer);
+ var root = cloneNode(_buffer.getRootNode());
+ var div = document.createElement("div");
+ div.appendChild(root);
+ var rendered = div.innerHTML;
+ div.removeChild(root);
+ if(rendered != this._rendered){
+ this._rendered = rendered;
+ if(this._dijit){
+ this._dijit.destroyRecursive();
+ }
+ this._dijit = Parser.instantiate([root])[0];
+ }
+ }
+
+ var node = this._dijit.domNode;
+
+ if(this._events){
+ this._events._object = this._dijit;
+ this._events.render(context, buffer);
+ }
+ if(this._attach){
+ this._attach._object = this._dijit;
+ this._attach.render(context, buffer);
+ }
+
+ return buffer.concat(node);
+ },
+ unrender: function(context, buffer){
+ return buffer.remove(this._dijit.domNode);
+ },
+ clone: function(){
+ return new this.constructor(this._node, this._parsed);
+ }
+ });
+
+ lang.mixin(ddcd, {
+ widgetsInTemplate: true,
+ dojoAttachPoint: function(parser, token){
+ return new ddcd.AttachNode(token.contents.slice(token.contents.indexOf("data-") !== -1 ? 23 : 16).split(/\s*,\s*/));
+ },
+ dojoAttachEvent: function(parser, token){
+ return new ddcd.EventNode(token.contents.slice(token.contents.indexOf("data-") !== -1 ? 23 : 16));
+ },
+ dojoType: function(parser, token){
+ var parsed = false;
+ if(token.contents.slice(-7) == " parsed"){
+ parsed = true;
+ }
+ var contents = token.contents.indexOf("data-") !== -1 ? token.contents.slice(15) : token.contents.slice(9);
+ var dojoType = parsed ? contents.slice(0, -7) : contents.toString();
+
+ if(ddcd.widgetsInTemplate){
+ var node = parser.swallowNode();
+ node.setAttribute("data-dojo-type", dojoType);
+ return new ddcd.DojoTypeNode(node, parsed);
+ }
+
+ return new dd.AttributeNode("data-dojo-type", dojoType);
+ },
+ on: function(parser, token){
+ // summary: Associates an event type to a function (on the current widget) by name
+ var parts = token.contents.split();
+ return new ddcd.EventNode(parts[0] + ":" + parts.slice(1).join(" "));
+ }
+ });
+ ddcd["data-dojo-type"] = ddcd.dojoType;
+ ddcd["data-dojo-attach-point"] = ddcd.dojoAttachPoint;
+ ddcd["data-dojo-attach-event"] = ddcd.dojoAttachEvent;
+
+
+ dd.register.tags("dojox.dtl.contrib", {
+ "dijit": ["attr:dojoType", "attr:data-dojo-type", "attr:dojoAttachPoint", "attr:data-dojo-attach-point", ["attr:attach", "dojoAttachPoint"], ["attr:attach", "data-dojo-attach-point"], "attr:dojoAttachEvent", "attr:data-dojo-attach-event", [/(attr:)?on(click|key(up))/i, "on"]]
+ });
+ return dojox.dtl.contrib.dijit;
+});
diff --git a/js/dojo/dojox/dtl/contrib/dom.js b/js/dojo/dojox/dtl/contrib/dom.js
new file mode 100644
index 0000000..d2e181f
--- /dev/null
+++ b/js/dojo/dojox/dtl/contrib/dom.js
@@ -0,0 +1,177 @@
+//>>built
+define("dojox/dtl/contrib/dom", [
+ "dojo/_base/kernel",
+ "dojo/_base/lang",
+ "dojo/_base/connect",
+ "dojo/dom-style",
+ "dojo/dom-construct",
+ "../_base",
+ "../dom"
+], function(kernel,lang,connect,domStyle,domConstruct,dd,dddom){
+ /*=====
+ dd = dojox.dtl;
+ =====*/
+ var ddch = lang.getObject("dojox.dtl.contrib.dom", true);
+
+ var simple = {render: function(){ return this.contents; }};
+
+ ddch.StyleNode = lang.extend(function(styles){
+ this.contents = {};
+ this._current = {};
+ this._styles = styles;
+ for(var key in styles){
+ if(styles[key].indexOf("{{") != -1){
+ var node = new dd.Template(styles[key]);
+ }else{
+ var node = lang.delegate(simple);
+ node.contents = styles[key];
+ }
+ this.contents[key] = node;
+ }
+ },
+ {
+ render: function(context, buffer){
+ for(var key in this.contents){
+ var value = this.contents[key].render(context);
+ if(this._current[key] != value){
+ domStyle.set(buffer.getParent(), key, this._current[key] = value);
+ }
+ }
+ return buffer;
+ },
+ unrender: function(context, buffer){
+ this._current = {};
+ return buffer;
+ },
+ clone: function(buffer){
+ return new this.constructor(this._styles);
+ }
+ });
+
+ ddch.BufferNode = lang.extend(function(nodelist, options){
+ this.nodelist = nodelist;
+ this.options = options;
+ },
+ {
+ _swap: function(type, node){
+ if(!this.swapped && this.parent.parentNode){
+ if(type == "node"){
+ if((node.nodeType == 3 && !this.options.text) || (node.nodeType == 1 && !this.options.node)){
+ return;
+ }
+ }else if(type == "class"){
+ if(type != "class"){
+ return;
+ }
+ }
+
+ this.onAddNode && connect.disconnect(this.onAddNode);
+ this.onRemoveNode && connect.disconnect(this.onRemoveNode);
+ this.onChangeAttribute && connect.disconnect(this.onChangeAttribute);
+ this.onChangeData && connect.disconnect(this.onChangeData);
+
+ this.swapped = this.parent.cloneNode(true);
+ this.parent.parentNode.replaceChild(this.swapped, this.parent);
+ }
+ },
+ render: function(context, buffer){
+ this.parent = buffer.getParent();
+ if(this.options.node){
+ this.onAddNode = connect.connect(buffer, "onAddNode", lang.hitch(this, "_swap", "node"));
+ this.onRemoveNode = connect.connect(buffer, "onRemoveNode", lang.hitch(this, "_swap", "node"));
+ }
+ if(this.options.text){
+ this.onChangeData = connect.connect(buffer, "onChangeData", lang.hitch(this, "_swap", "node"));
+ }
+ if(this.options["class"]){
+ this.onChangeAttribute = connect.connect(buffer, "onChangeAttribute", lang.hitch(this, "_swap", "class"));
+ }
+
+ buffer = this.nodelist.render(context, buffer);
+
+ if(this.swapped){
+ this.swapped.parentNode.replaceChild(this.parent, this.swapped);
+ domConstruct.destroy(this.swapped);
+ }else{
+ this.onAddNode && connect.disconnect(this.onAddNode);
+ this.onRemoveNode && connect.disconnect(this.onRemoveNode);
+ this.onChangeAttribute && connect.disconnect(this.onChangeAttribute);
+ this.onChangeData && connect.disconnect(this.onChangeData);
+ }
+
+ delete this.parent;
+ delete this.swapped;
+ return buffer;
+ },
+ unrender: function(context, buffer){
+ return this.nodelist.unrender(context, buffer);
+ },
+ clone: function(buffer){
+ return new this.constructor(this.nodelist.clone(buffer), this.options);
+ }
+ });
+
+ lang.mixin(ddch, {
+ buffer: function(parser, token){
+ // summary:
+ // Buffer large DOM manipulations during re-render.
+ // description:
+ // When using DomTemplate, wrap any content
+ // that you expect to change often during
+ // re-rendering. It will then remove its parent
+ // from the main document while it re-renders that
+ // section of code. It will only remove it from
+ // the main document if a mainpulation of somes sort
+ // happens. ie It won't swap out if it diesn't have to.
+ // example:
+ // By default, it considers only node addition/removal
+ // to be "changing"
+ //
+ // | {% buffer %}{% for item in items %}<li>{{ item }}</li>{% endfor %}{% endbuffer %}
+ // example:
+ // You can explicitly declare options:
+ //
+ // * node: Watch node removal/addition
+ // * class: Watch for a classname to be changed
+ // * text: Watch for any text to be changed
+ //
+ // | {% buffer node class %}{% for item in items %}<li>{{ item }}</li>{% endfor %}{% endbuffer %}
+ var parts = token.contents.split().slice(1);
+ var options = {};
+ var found = false;
+ for(var i = parts.length; i--;){
+ found = true;
+ options[parts[i]] = true;
+ }
+ if(!found){
+ options.node = true;
+ }
+ var nodelist = parser.parse(["endbuffer"]);
+ parser.next_token();
+ return new ddch.BufferNode(nodelist, options);
+ },
+ html: function(parser, token){
+ kernel.deprecated("{% html someVariable %}", "Use {{ someVariable|safe }} instead");
+ return parser.create_variable_node(token.contents.slice(5) + "|safe");
+ },
+ style_: function(parser, token){
+ var styles = {};
+ token = token.contents.replace(/^style\s+/, "");
+ var rules = token.split(/\s*;\s*/g);
+ for(var i = 0, rule; rule = rules[i]; i++){
+ var parts = rule.split(/\s*:\s*/g);
+ var key = parts[0];
+ var value = lang.trim(parts[1]);
+ if(value){
+ styles[key] = value;
+ }
+ }
+ return new ddch.StyleNode(styles);
+ }
+ });
+
+ dd.register.tags("dojox.dtl.contrib", {
+ "dom": ["html", "attr:style", "buffer"]
+ });
+ return dojox.dtl.contrib.dom;
+}); \ No newline at end of file
diff --git a/js/dojo/dojox/dtl/contrib/objects.js b/js/dojo/dojox/dtl/contrib/objects.js
new file mode 100644
index 0000000..ea1d07b
--- /dev/null
+++ b/js/dojo/dojox/dtl/contrib/objects.js
@@ -0,0 +1,21 @@
+//>>built
+define("dojox/dtl/contrib/objects", [
+ "dojo/_base/lang",
+ "../_base"
+], function(lang,dd){
+ /*=====
+ dd = dojox.dtl;
+ =====*/
+ lang.getObject("dojox.dtl.contrib.objects", true);
+
+ lang.mixin(dd.contrib.objects, {
+ key: function(value, arg){
+ return value[arg];
+ }
+ });
+
+ dd.register.filters("dojox.dtl.contrib", {
+ "objects": ["key"]
+ });
+ return dojox.dtl.contrib.objects;
+}); \ No newline at end of file
diff --git a/js/dojo/dojox/dtl/demos/demo_Animation.html b/js/dojo/dojox/dtl/demos/demo_Animation.html
new file mode 100644
index 0000000..f4b43ee
--- /dev/null
+++ b/js/dojo/dojox/dtl/demos/demo_Animation.html
@@ -0,0 +1,45 @@
+<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("dijit._WidgetBase");
+ dojo.require("dojox.dtl._DomTemplated");
+
+ dojo.declare("demo.Animation", [dijit._WidgetBase, dojox.dtl._DomTemplated],
+ {
+ buffer: 0, // Note: Sensitivity is 0 by default, but this is to emphasize we're not doing any buffering
+ templateString: dojo.cache("dojox.dtl.demos.templates", "animation.html"),
+ constructor: function(props, node){
+ console.debug("constructor");
+ this.x = 0;
+ this.y = 0;
+ },
+ postCreate: function(){
+ 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.x = obj;
+ this.y = Math.sqrt(obj) * 10;
+
+ dojo.style(this.blue, "left", this.x);
+ dojo.style(this.blue, "top", this.y + 10);
+
+ this.render();
+ }
+ });
+
+ dojo.require("dojo.parser");
+ </script>
+ </head>
+ <body>
+ <div dojoType="demo.Animation" ></div>
+ </body>
+</html>
diff --git a/js/dojo/dojox/dtl/demos/demo_Animation_amd.html b/js/dojo/dojox/dtl/demos/demo_Animation_amd.html
new file mode 100644
index 0000000..def5ecd
--- /dev/null
+++ b/js/dojo/dojox/dtl/demos/demo_Animation_amd.html
@@ -0,0 +1,53 @@
+<html>
+ <head>
+ <title>Testing dojox.dtl using animation to change attributes</title>
+ <script src="../../../dojo/dojo.js" data-dojo-config="parseOnLoad: true, usePlainJson: true, async:true"></script>
+ <script>
+ require(["dojo/_base/lang",
+ "dojo/_base/declare",
+ "dijit/_WidgetBase",
+ "dojox/dtl/_DomTemplated",
+ "dojo/text!./templates/animation.html",
+ "dojo/aspect",
+ "dojo/_base/fx",
+ "dojo/dom-style",
+ 'dojo/domReady!',
+ "dojo/parser",
+ "dojox/dtl/contrib/dom"], // the dtl deps used in animation.html. require it here so that it is loaded when dtl is processed.
+ function(lang, declare, _WidgetBase, _DomTemplated, template, aspect, fx, domstyle){
+
+ declare("demo.Animation", [_WidgetBase, _DomTemplated], {
+ buffer: 0, // Note: Sensitivity is 0 by default, but this is to emphasize we're not doing any buffering
+ templateString: template,
+ constructor: function(props, node){
+ this.x = 0;
+ this.y = 0;
+ },
+ postCreate: function(){
+ var anim = new fx.Animation({
+ curve: [0, 300],
+ rate: 10,
+ duration: 5000,
+ easing: fx._defaultEasing
+ });
+ aspect.after(anim, "onAnimate", lang.hitch(this, this._reDraw), true);
+ anim.play();
+ },
+ _reDraw: function(obj){
+ this.x = obj;
+ this.y = Math.sqrt(obj) * 10;
+
+ domstyle.set(this.blue, "left", this.x);
+ domstyle.set(this.blue, "top", this.y + 10);
+
+ this.render();
+ }
+ });
+ });
+
+ </script>
+ </head>
+ <body>
+ <div data-dojo-type="demo.Animation" ></div>
+ </body>
+</html>
diff --git a/js/dojo/dojox/dtl/demos/demo_Blog.html b/js/dojo/dojox/dtl/demos/demo_Blog.html
new file mode 100644
index 0000000..5f244b8
--- /dev/null
+++ b/js/dojo/dojox/dtl/demos/demo_Blog.html
@@ -0,0 +1,95 @@
+<html>
+ <head>
+ <title>Testing dojox.dtl using a blog example</title>
+ <script src="../../../dojo/dojo.js" djConfig="usePlainJson: true, parseOnLoad: true"></script>
+ <script>
+ dojo.require("dijit._WidgetBase");
+ dojo.require("dojox.dtl._DomTemplated");
+ dojo.require("dojo.parser");
+
+ dojo.declare("demo.Blog", [dijit._WidgetBase, dojox.dtl._DomTemplated],
+ {
+ templatePath: dojo.moduleUrl("dojox.dtl.demos.templates", "blog_list.html"),
+ base: {
+ url: dojo.moduleUrl("dojox.dtl.demos.templates", "blog_base.html"),
+ shared: true
+ },
+ constructor: function(props, node){
+ this.list = false;
+ this.blogs = {};
+ this.pages = {};
+ },
+ postCreate: function(){
+ if(!this.list){
+ dojo.xhrGet({
+ url: dojo.moduleUrl("dojox.dtl.demos.json.blog", "get_blog_list.json"),
+ handleAs: "json"
+ }).addCallback(this, "_loadList");
+ }
+ },
+ _showList: function(obj){
+ this.title = "Blog Posts";
+ this.setTemplate(this.templatePath);
+ },
+ _showDetail: function(obj){
+ var key = obj.target.className.substring(5);
+
+ if(this.blogs[key]){
+ this.title = "Blog Post";
+ this.blog = this.blogs[key];
+ this.blog.title = this.blog_list[key].title;
+ this.setTemplate(dojo.moduleUrl("dojox.dtl.demos.templates", "blog_detail.html"));
+ }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.pages[key]){
+ this.title = this.pages[key].title;
+ this.body = this.pages[key].body;
+ this.setTemplate(dojo.moduleUrl("dojox.dtl.demos.templates", "blog_page.html"));
+ }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.title = "Blog Posts";
+ dojo.mixin(this, data);
+ this.render();
+ },
+ _loadDetail: function(data){
+ data.date = new Date(data.date);
+ this.blogs[data.key] = data;
+ this.title = "Blog Post";
+ this.blog = data;
+ this.blog.title = this.blog_list[data.key].title;
+ this.setTemplate(dojo.moduleUrl("dojox.dtl.demos.templates", "blog_detail.html"));
+ },
+ _loadPage: function(data){
+ this.pages[data.key] = data;
+ dojo.mixin(this, data);
+ this.setTemplate(dojo.moduleUrl("dojox.dtl.demos.templates", "blog_page.html"));
+ }
+ });
+ </script>
+ </head>
+ <body>
+ <div dojoType="demo.Blog"></div>
+ </body>
+</html>
diff --git a/js/dojo/dojox/dtl/demos/demo_Data.html b/js/dojo/dojox/dtl/demos/demo_Data.html
new file mode 100644
index 0000000..d84ff26
--- /dev/null
+++ b/js/dojo/dojox/dtl/demos/demo_Data.html
@@ -0,0 +1,59 @@
+<html>
+ <head>
+ <title>Demo using the dojo.data bind_data tag</title>
+ <script type="text/javascript" src="../../../dojo/dojo.js"
+ djConfig="isDebug: true, parseOnLoad: true"></script>
+ <script type="text/javascript">
+ dojo.require("dijit._WidgetBase");
+ dojo.require("dojox.dtl._Templated");
+ dojo.require("dojox.data.FlickrRestStore");
+ dojo.require("dojo.parser");
+
+ dojo.declare("demo.Gallery", [dijit._WidgetBase, dojox.dtl._Templated], {
+ templateString: dojo.cache("dojox.dtl.demos.templates", "gallery.html"),
+ store: new dojox.data.FlickrRestStore(),
+ selectThumbnail: function(e){
+ this.selected = e.target.className;
+ this.render();
+ },
+ keyUp: function(e){
+ if(e.keyCode == dojo.keys.ENTER){
+ var search = e.target.value;
+ var query = {
+ query: {
+ userid: "44153025@N00",
+ apikey: "8c6803164dbc395fb7131c9d54843627",
+ sort: [
+ {
+ attribute: "interestingness",
+ descending: true
+ }
+ ],
+ tags: search.split(/\s*,\s*/g),
+ tag_mode: "any"
+ },
+ start: 0,
+ count: 10,
+ onBegin: dojo.hitch(this, function(total){
+ console.debug(total);
+ this._maxPhotos = total;
+ }),
+ onComplete: dojo.hitch(this, function(items, request){
+ console.debug(items);
+ if(items && items.length) {
+ this.items = items;
+ this.render();
+ }
+ })
+ };
+ this.store.fetch(query);
+ }
+ }
+ });
+ </script>
+ </head>
+ <body>
+ <p>Also see demo_Tree.html for an alternative way to use data stores.</p>
+ <div dojoType="demo.Gallery"></div>
+ </body>
+</html>
diff --git a/js/dojo/dojox/dtl/demos/demo_Dijitless.html b/js/dojo/dojox/dtl/demos/demo_Dijitless.html
new file mode 100644
index 0000000..e902ef6
--- /dev/null
+++ b/js/dojo/dojox/dtl/demos/demo_Dijitless.html
@@ -0,0 +1,50 @@
+<html>
+ <head>
+ <title>Demo using dojox.dtl._DomTemplated without Dijit</title>
+ <script type="text/javascript" src="../../../dojo/dojo.js"
+ djConfig="isDebug: true"></script>
+ <script type="text/javascript">
+ dojo.require("dojox.dtl.dom");
+ dojo.require("dojox.dtl.render.dom");
+ dojo.require("dojox.dtl.Context");
+
+ dojo.addOnLoad(function(){
+ var context = new dojox.dtl.Context({
+ items: ["apple", "banana", "orange"]
+ });
+
+ var template = new dojox.dtl.DomTemplate("<ul><!--{% for item in items %}--><li><!--{{ item }}--></li><!--{% endfor %}--></ul>");
+ // Render it plain
+ var node = template.render(context).getRootNode();
+ dojo.body().appendChild(node);
+
+ // Now show an example of how hard it is to manage stuff if the root node changes
+ var template2 = new dojox.dtl.DomTemplate("<!--{% ifequal items.length 3 %}--><ul><!--{% for item in items %}--><li><!--{{ item }}--></li><!--{% endfor %}--></ul>{% else %}<div>More than 3 items!</div>{% endifequal %}");
+ // Render it plain
+ var node2 = template2.render(context).getRootNode();
+ dojo.body().appendChild(node2);
+
+ // Now show how the HTML Render object makes this easier
+ var renderer = new dojox.dtl.render.dom.Render(dojo.byId("attach"), new dojox.dtl.DomTemplate("<!--{% ifequal items.length 3 %}--><ul><!--{% for item in items reversed %}--><li><!--{{ item }}--></li><!--{% endfor %}--></ul>{% else %}<div>More than 3 items!</div>{% endifequal %}"));
+ renderer.render(context);
+
+ // Now re-render and break template2
+ setTimeout(function(){
+ context.items.push("guava");
+ template.render(context);
+ template2.render(context);
+ renderer.render(context);
+
+ // This is what has to be done to fix template2
+ setTimeout(function(){
+ var frag = template2.render(context).getRootNode();
+ node2.parentNode.replaceChild(frag, node2);
+ }, 3000);
+ }, 3000);
+ });
+ </script>
+ </head>
+ <body>
+ <div id="attach"></div>
+ </body>
+</html>
diff --git a/js/dojo/dojox/dtl/demos/demo_DomTemplated.html b/js/dojo/dojox/dtl/demos/demo_DomTemplated.html
new file mode 100644
index 0000000..2e418e4
--- /dev/null
+++ b/js/dojo/dojox/dtl/demos/demo_DomTemplated.html
@@ -0,0 +1,44 @@
+<html>
+ <head>
+ <title>Demo using dojox.dtl._DomTemplated</title>
+ <script type="text/javascript" src="../../../dojo/dojo.js"
+ djConfig="isDebug: true, parseOnLoad: true"></script>
+ <style type="text/css">
+ @import "../../../dijit/themes/tundra/tundra.css";
+ #pane {
+ border: 1px solid darkblue;
+ }
+ </style>
+ <script type="text/javascript">
+ dojo.require("dijit._WidgetBase");
+ dojo.require("dojox.dtl._DomTemplated");
+ dojo.require("dijit.form.Button");
+ dojo.require("dijit.layout.ContentPane");
+
+ dojo.declare("Fruit", [dijit._WidgetBase, dojox.dtl._DomTemplated], {
+ widgetsInTemplate: true,
+ items: ["apple", "banana", "orange"],
+ keyUp: function(e){
+ if((e.type == "click" || e.keyCode == dojo.keys.ENTER) && this.input.value){
+ console.debug(this.button);
+ var i = dojo.indexOf(this.items, this.input.value);
+ if(i != -1){
+ this.items.splice(i, 1);
+ }else{
+ this.items.push(this.input.value);
+ }
+ this.input.value = "";
+ this.render();
+ }
+ },
+ // Note, the load tag here is superfluous, since _DomTemplate has a dojo.require for it.
+ templateString: '<div><input dojoAttachEvent="onkeyup: keyUp" dojoAttachPoint="input"> <button dojoType="dijit.form.Button" dojoAttachPoint="button" dojoAttachEvent="onClick: keyUp">Add/Remove Item</button><div id="pane" dojoType="dijit.layout.ContentPane parsed"><ul><!--{% for item in items %}--><li><button dojoType="dijit.form.Button parsed" title="Fruit: {{ item }}" otherAttr2="x_{{item}}"><!--{{ item }}--><script type="dojo/connect" event="onClick" args="e">console.debug("You clicked", this.containerNode.innerHTML);</' + 'script></button></li><!--{% endfor %}--></ul></div></div>'
+ });
+
+ dojo.require("dojo.parser");
+ </script>
+ </head>
+ <body class="tundra">
+ <div dojoType="Fruit" id="dtl"></div>
+ </body>
+</html>
diff --git a/js/dojo/dojox/dtl/demos/demo_DomTemplated_amd.html b/js/dojo/dojox/dtl/demos/demo_DomTemplated_amd.html
new file mode 100644
index 0000000..8d681fa
--- /dev/null
+++ b/js/dojo/dojox/dtl/demos/demo_DomTemplated_amd.html
@@ -0,0 +1,50 @@
+<html>
+ <head>
+ <title>Demo using dojox.dtl._DomTemplated</title>
+ <script type="text/javascript" src="../../../dojo/dojo.js"
+ data-dojo-config="async:true, isDebug: true, parseOnLoad: true"></script>
+ <style type="text/css">
+ @import "../../../dijit/themes/tundra/tundra.css";
+ #pane {
+ border: 1px solid darkblue;
+ }
+ </style>
+ <script type="text/javascript">
+ require(["dojo/_base/declare",
+ "dojo/keys",
+ "dojo/_base/array",
+ "dijit/_WidgetBase",
+ "dojox/dtl/_DomTemplated",
+ "dijit/form/Button",
+ "dijit/layout/ContentPane",
+ "dojo/parser",
+ "dojox/dtl/tag/logic"],
+ function(declare, keys, array, _WidgetBase, _DomTemplated, Button, ContentPane){
+
+ declare("Fruit", [_WidgetBase, _DomTemplated], {
+ widgetsInTemplate: true,
+ items: ["apple", "banana", "orange"],
+ keyUp: function(e){
+ if((e.type == "click" || e.keyCode == keys.ENTER) && this.input.value){
+ console.debug(this.button);
+ var i = array.indexOf(this.items, this.input.value);
+ if(i != -1){
+ this.items.splice(i, 1);
+ }else{
+ this.items.push(this.input.value);
+ }
+ this.input.value = "";
+ this.render();
+ }
+ },
+ templateString: '<div><input data-dojo-attach-event="onkeyup:keyUp" data-dojo-attach-point="input"> <button data-dojo-type="dijit.form.Button" data-dojo-attach-point="button" data-dojo-attach-event="onClick: keyUp">Add/Remove Item</button><div id="pane" data-dojo-type="dijit.layout.ContentPane parsed"><ul><!--{% for item in items %}--><li><button data-dojo-type="dijit.form.Button parsed" title="Fruit: {{ item }}" otherAttr2="x_{{item}}"><!--{{ item }}--><script type="dojo/on" data-dojo-event="click" data-dojo-args="e">console.debug("You clicked", this.containerNode.innerHTML);</' + 'script></button></li><!--{% endfor %}--></ul></div></div>'
+ });
+ }
+ );
+
+ </script>
+ </head>
+ <body class="tundra">
+ <div data-dojo-type="Fruit" id="dtl"></div>
+ </body>
+</html>
diff --git a/js/dojo/dojox/dtl/demos/demo_Events.html b/js/dojo/dojox/dtl/demos/demo_Events.html
new file mode 100644
index 0000000..ec181b9
--- /dev/null
+++ b/js/dojo/dojox/dtl/demos/demo_Events.html
@@ -0,0 +1,46 @@
+<html>
+ <head>
+ <title>Demo using dojox.dtl._Templated</title>
+ <script type="text/javascript" src="../../../dojo/dojo.js"
+ djConfig="isDebug: true, parseOnLoad: true"></script>
+ <style type="text/css">
+ @import "../../../dijit/themes/tundra/tundra.css";
+ </style>
+ <script type="text/javascript">
+ dojo.require("dijit._WidgetBase");
+ dojo.require("dojox.dtl._DomTemplated");
+ dojo.require("dijit.form.Button");
+
+ dojo.declare("Fruit", [dijit._WidgetBase, dojox.dtl._DomTemplated], {
+ widgetsInTemplate: true,
+ items: ["apple", "banana", "orange"],
+ keyUp: function(e){
+ if((e.type == "click" || e.keyCode == dojo.keys.ENTER) && this.input.value){
+ var i = dojo.indexOf(this.items, this.input.value);
+ if(i != -1){
+ this.items.splice(i, 1);
+ }else{
+ this.items.push(this.input.value);
+ }
+ this.input.value = "";
+ this.render();
+ }
+ },
+ postCreate: function(){
+ this.render();
+ dojo.connect(this.button, "onClick", this, "keyUp");
+ },
+ debug: function(e, verb, fruit){
+ console.debug("You " + verb + " a:", fruit);
+ },
+ // Note, the load tag here is superfluous, since _DomTemplate has a dojo.require for it.
+ templateString: '{% load dojox.dtl.contrib.dijit %}<div><input dojoAttachEvent="onkeyup: keyUp" dojoAttachPoint="input"> <button dojoType="dijit.form.Button" dojoAttachPoint="button">Add/Remove Item</button><ul><!--{% for item in items %}--><li onclick="debug \'ate\' item"><!--{{ item }}--></li><!--{% endfor %}--></ul></div>'
+ });
+
+ dojo.require("dojo.parser");
+ </script>
+ </head>
+ <body class="tundra">
+ <div dojoType="Fruit"></div>
+ </body>
+</html>
diff --git a/js/dojo/dojox/dtl/demos/demo_Inline.html b/js/dojo/dojox/dtl/demos/demo_Inline.html
new file mode 100644
index 0000000..7c16ea3
--- /dev/null
+++ b/js/dojo/dojox/dtl/demos/demo_Inline.html
@@ -0,0 +1,51 @@
+<html>
+ <head>
+ <title>Demo using dojox.dtl._DomTemplated inline in DOM</title>
+ <script type="text/javascript" src="../../../dojo/dojo.js"
+ djConfig="isDebug: true, parseOnLoad: true"></script>
+ <script type="text/javascript">
+ dojo.require("dojo.parser");
+ dojo.require("dojox.dtl.Inline");
+ dojo.require("dojox.dtl.DomInline");
+
+ gContext = {items: ["apple", "banana", "orange"]};
+
+ dojo.addOnLoad(function(){
+ // The Re-render each with a new item
+ setTimeout(function(){
+ var inline = dijit.byId("inline");
+ inline.context.items.push("guava");
+ inline.render();
+ var dominline = dijit.byId("dominline");
+ dominline.context.items.push("pineapple");
+ dominline.render();
+
+ setTimeout(function(){
+ // You can define an altogether new context in either of the following ways
+ inline.context = {items: ["lions", "tigers", "bears"]};
+ inline.render();
+ dominline.render({items: ["duck", "chicken", "turkey"]});
+ }, 3000);
+ }, 3000);
+ });
+ </script>
+ </head>
+ <body>
+ <script type="text/html" dojoType="dojox.dtl.Inline" id="inline" context="{items: ['apple', 'banana', 'orange']}">
+ <ul>
+ {% for item in items %}
+ <li>{{ item }}</li>
+ {% endfor %}
+ </ul>
+ </script>
+
+ <!-- Use the DOM-based version with an external context -->
+ <script type="text/html" dojoType="dojox.dtl.DomInline" id="dominline" context="gContext">
+ <ul>
+ {% for item in items %}
+ <li>{{ item }}</li>
+ {% endfor %}
+ </ul>
+ </script>
+ </body>
+</html>
diff --git a/js/dojo/dojox/dtl/demos/demo_NodeList.html b/js/dojo/dojox/dtl/demos/demo_NodeList.html
new file mode 100644
index 0000000..d1ab0a8
--- /dev/null
+++ b/js/dojo/dojox/dtl/demos/demo_NodeList.html
@@ -0,0 +1,37 @@
+<html>
+ <head>
+ <title>Demo using dojox.dtl._Templated</title>
+ <script type="text/javascript" src="../../../dojo/dojo.js"
+ djConfig="isDebug: true, parseOnLoad: true"></script>
+ <script type="text/javascript">
+ dojo.require("dojox.dtl.ext-dojo.NodeList");
+ dojo.require("dojox.dtl.Context");
+
+ dojo.addOnLoad(function(){
+ // First, look at the NodeList extension
+ dojo.query(".fruit").dtl(dojo.moduleUrl("dojox.dtl.demos.templates", "nodelist.html"), { items: ["apple", "banana", "pear"] });
+
+ dojo.query(".fruit2").dtl("<div><ul>{% for item in items %}<li>{{ item }}</li>{% endfor %}</ul></div", { items: ["apple", "banana", "pear"] });
+
+ // Now, create a real template object
+ var tpl = new dojox.dtl.Template(dojo.moduleUrl("dojox.dtl.demos.templates", "nodelist.html"));
+
+ // And test its update function with a dojo.query
+ tpl.update(dojo.query(".update"), dojo.moduleUrl("dojox.dtl.demos.json", "fruit.json"));
+
+ setTimeout(function(){
+ // And now test it with an ID reference
+ tpl.update("updateId", dojo.moduleUrl("dojox.dtl.demos.json", "morefruit.json"));
+ // And throw in a standard rendering just for fun
+ dojo.byId("updateId2").innerHTML = tpl.render(new dojox.dtl.Context({ items: ["pineapple", "orange", "tomato"] }));
+ }, 5000);
+ });
+ </script>
+ </head>
+ <body>
+ <div class="fruit"></div>
+ <div class="fruit2"></div>
+ <div class="update" id="updateId"></div>
+ <div class="update" id="updateId2"></div>
+ </body>
+</html>
diff --git a/js/dojo/dojox/dtl/demos/demo_NodeList_amd.html b/js/dojo/dojox/dtl/demos/demo_NodeList_amd.html
new file mode 100644
index 0000000..840d444
--- /dev/null
+++ b/js/dojo/dojox/dtl/demos/demo_NodeList_amd.html
@@ -0,0 +1,42 @@
+<html>
+ <head>
+ <title>Demo using dojox.dtl._Templated</title>
+ <script type="text/javascript" src="../../../dojo/dojo.js"
+ djConfig="async: true, isDebug: true, parseOnLoad: true"></script>
+ <script type="text/javascript">
+ require(['dojox/dtl/ext-dojo/NodeList',
+ 'dojox/dtl/Context',
+ 'dojo/query',
+ 'dojo/dom',
+ 'dojo/parser',
+ 'dojo/domReady!',
+ 'dojox/dtl/tag/logic'],
+ function(NodeList, Context, query, dom){
+
+ // First, look at the NodeList extension
+ query(".fruit").dtl(require.toUrl("dojox/dtl/demos/templates/nodelist.html"), { items: ["apple", "banana", "pear"] });
+
+ query(".fruit2").dtl("<div><ul>{% for item in items %}<li>{{ item }}</li>{% endfor %}</ul></div", { items: ["apple", "banana", "pear"] });
+
+ // Now, create a real template object
+ var tpl = new dojox.dtl.Template(require.toUrl("dojox/dtl/demos/templates/nodelist.html"));
+
+ // And test its update function with a dojo.query
+ tpl.update(query(".update"), require.toUrl("dojox/dtl/demos/json/fruit.json"));
+
+ setTimeout(function(){
+ // And now test it with an ID reference
+ tpl.update("updateId", require.toUrl("dojox/dtl/demos/json/morefruit.json"));
+ // And throw in a standard rendering just for fun
+ dom.byId("updateId2").innerHTML = tpl.render(new dojox.dtl.Context({ items: ["pineapple", "orange", "tomato"] }));
+ }, 5000);
+ });
+ </script>
+ </head>
+ <body>
+ <div class="fruit"></div>
+ <div class="fruit2"></div>
+ <div class="update" id="updateId"></div>
+ <div class="update" id="updateId2"></div>
+ </body>
+</html>
diff --git a/js/dojo/dojox/dtl/demos/demo_Table.html b/js/dojo/dojox/dtl/demos/demo_Table.html
new file mode 100644
index 0000000..f1aa911
--- /dev/null
+++ b/js/dojo/dojox/dtl/demos/demo_Table.html
@@ -0,0 +1,4073 @@
+<html>
+ <head>
+ <title>Demo to show a massive nested for loop to render a table</title>
+ <script type="text/javascript" src="../../../dojo/dojo.js"
+ djConfig="isDebug: true, parseOnLoad: true"></script>
+ <style type="text/css">
+ @import "../../../dijit/themes/tundra/tundra.css";
+
+ table {
+ border-collapse: collapse;
+ }
+ th {
+ background-color: #ccf;
+ }
+ th, td {
+ border: 1px solid #aaa;
+ padding: 2px 15px;
+ }
+ tr.even td {
+ background-color: #ffc;
+ }
+ </style>
+ <script type="text/javascript">
+ dojo.require("dijit._WidgetBase");
+ dojo.require("dojox.dtl._DomTemplated");
+ dojo.require("dojox.dtl.tag.logic");
+ dojo.require("dojox.dtl.tag.loop");
+ dojo.require("dojox.dtl.filter.lists");
+
+ dojo.declare("demo.Table", [dijit._WidgetBase, dojox.dtl._DomTemplated], {
+ pos: 0,
+ postMixInProperties: function(){
+ this.ths = dojo.query("th", this.domNode).map(function(item){
+ return item.innerHTML;
+ });
+ this.trs = dojo.query("tbody tr", this.domNode).map(function(item){
+ return dojo.query("td", item).map(function(item){
+ return item.innerHTML;
+ });
+ });
+ },
+ postCreate: function(){
+ //unset display to show it (this is copied from the original node)
+ this.domNode.style.display="";
+ },
+ sortColumn: function(e){
+ this.pos = dojo.indexOf(this.ths, e.target.innerHTML);
+ console.time("render2");
+ this.render();
+ console.timeEnd("render2");
+ },
+ templateString: '<table><thead><tr><!--{% for th in ths %}--><th dojoAttachEvent="onclick: sortColumn"><!--{{ th }}--></th><!--{% endfor %}--></tr></thead><tbody><!--{% for tr in trs|dictsort:pos %}--><tr class="{% cycle \'odd\' \'even\' %}"><!--{% for td in tr %}--><td><!--{{ td }}--></td><!--{% endfor %}--></tr><!--{% endfor %}--></tbody></table>'
+ });
+
+ dojo.require("dojo.parser");
+ </script>
+ </head>
+ <body class="tundra">
+ <table dojoType="demo.Table" style="display: none;">
+ <thead>
+ <tr>
+ <th>Index</th>
+ <th>Numeric</th>
+ <th>Text</th>
+ <th>Currency</th>
+ <th>Date</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <td>0</td>
+ <td>158.9</td>
+ <td>Bill</td>
+ <td>$22.44</td>
+
+ <td>2008-12-28</td>
+ </tr>
+ <tr>
+ <td>1</td>
+ <td>690.4</td>
+ <td>Joe</td>
+ <td>$3.03</td>
+
+ <td>2009-07-03</td>
+ </tr>
+ <tr>
+ <td>2</td>
+ <td>843</td>
+ <td>Bob</td>
+ <td>$11.14</td>
+
+ <td>2010-09-30</td>
+ </tr>
+ <tr>
+ <td>3</td>
+ <td>57.8</td>
+ <td>Matt</td>
+ <td>$70.64</td>
+
+ <td>2009-12-16</td>
+ </tr>
+ <tr>
+ <td>4</td>
+ <td>494.6</td>
+ <td>Mark</td>
+ <td>$9.13</td>
+
+ <td>2010-05-11</td>
+ </tr>
+ <tr>
+ <td>5</td>
+ <td>766.3</td>
+ <td>Tom</td>
+ <td>$55.34</td>
+
+ <td>2008-03-10</td>
+ </tr>
+ <tr>
+ <td>6</td>
+ <td>699.3</td>
+ <td>Jake</td>
+ <td>$26.24</td>
+
+ <td>2008-11-26</td>
+ </tr>
+ <tr>
+ <td>7</td>
+ <td>487.8</td>
+ <td>Greg</td>
+ <td>$72.94</td>
+
+ <td>2010-06-23</td>
+ </tr>
+ <tr>
+ <td>8</td>
+ <td>786.2</td>
+ <td>Adam</td>
+ <td>$34.64</td>
+
+ <td>2008-09-19</td>
+ </tr>
+ <tr>
+ <td>9</td>
+ <td>188.6</td>
+ <td>Steve</td>
+ <td>$6.33</td>
+
+ <td>2009-01-01</td>
+ </tr>
+ <tr>
+ <td>10</td>
+ <td>898.4</td>
+ <td>George</td>
+ <td>$22.24</td>
+
+ <td>2009-09-18</td>
+ </tr>
+ <tr>
+ <td>11</td>
+ <td>222.2</td>
+ <td>John</td>
+ <td>$91.24</td>
+
+ <td>2009-10-23</td>
+ </tr>
+ <tr>
+ <td>12</td>
+ <td>707.9</td>
+ <td>Phil</td>
+ <td>$75.54</td>
+
+ <td>2010-02-28</td>
+ </tr>
+ <tr>
+ <td>13</td>
+ <td>585.5</td>
+ <td>Jack</td>
+ <td>$81.34</td>
+
+ <td>2009-03-24</td>
+ </tr>
+ <tr>
+ <td>14</td>
+ <td>213.8</td>
+ <td>Paul</td>
+ <td>$30.74</td>
+
+ <td>2009-07-08</td>
+ </tr>
+ <tr>
+ <td>15</td>
+ <td>968.5</td>
+ <td>Rob</td>
+ <td>$7.33</td>
+
+ <td>2008-02-06</td>
+ </tr>
+ <tr>
+ <td>16</td>
+ <td>39.3</td>
+ <td>Walt</td>
+ <td>$77.34</td>
+
+ <td>2008-12-05</td>
+ </tr>
+ <tr>
+ <td>17</td>
+ <td>335.7</td>
+ <td>Nathan</td>
+ <td>$26.14</td>
+
+ <td>2008-01-27</td>
+ </tr>
+ <tr>
+ <td>18</td>
+ <td>127.6</td>
+ <td>Dan</td>
+ <td>$4.73</td>
+
+ <td>2009-03-03</td>
+ </tr>
+ <tr>
+ <td>19</td>
+ <td>365.3</td>
+ <td>Jeff</td>
+ <td>$23.54</td>
+
+ <td>2009-05-15</td>
+ </tr>
+ <tr>
+ <td>20</td>
+ <td>692.9</td>
+ <td>Bill</td>
+ <td>$13.34</td>
+
+ <td>2010-01-26</td>
+ </tr>
+ <tr>
+ <td>21</td>
+ <td>244.9</td>
+ <td>Joe</td>
+ <td>$35.64</td>
+
+ <td>2009-10-16</td>
+ </tr>
+ <tr>
+ <td>22</td>
+ <td>827</td>
+ <td>Bob</td>
+ <td>$6.33</td>
+
+ <td>2009-01-06</td>
+ </tr>
+ <tr>
+ <td>23</td>
+ <td>519.6</td>
+ <td>Matt</td>
+ <td>$64.94</td>
+
+ <td>2008-06-03</td>
+ </tr>
+ <tr>
+ <td>24</td>
+ <td>917.8</td>
+ <td>Mark</td>
+ <td>$86.34</td>
+
+ <td>2009-05-24</td>
+ </tr>
+ <tr>
+ <td>25</td>
+ <td>407.1</td>
+ <td>Tom</td>
+ <td>$83.14</td>
+
+ <td>2009-08-17</td>
+ </tr>
+ <tr>
+ <td>26</td>
+ <td>449.3</td>
+ <td>Jake</td>
+ <td>$87.04</td>
+
+ <td>2008-11-27</td>
+ </tr>
+ <tr>
+ <td>27</td>
+ <td>753.5</td>
+ <td>Greg</td>
+ <td>$20.64</td>
+
+ <td>2009-09-25</td>
+ </tr>
+ <tr>
+ <td>28</td>
+ <td>787</td>
+ <td>Adam</td>
+ <td>$33.44</td>
+
+ <td>2009-11-18</td>
+ </tr>
+ <tr>
+ <td>29</td>
+ <td>166.9</td>
+ <td>Steve</td>
+ <td>$69.94</td>
+
+ <td>2010-08-17</td>
+ </tr>
+ <tr>
+ <td>30</td>
+ <td>609.6</td>
+ <td>George</td>
+ <td>$39.24</td>
+
+ <td>2011-01-18</td>
+ </tr>
+ <tr>
+ <td>31</td>
+ <td>274</td>
+ <td>John</td>
+ <td>$63.64</td>
+
+ <td>2009-01-02</td>
+ </tr>
+ <tr>
+ <td>32</td>
+ <td>850.3</td>
+ <td>Phil</td>
+ <td>$46.34</td>
+
+ <td>2009-03-17</td>
+ </tr>
+ <tr>
+ <td>33</td>
+ <td>181.4</td>
+ <td>Jack</td>
+ <td>$98.34</td>
+
+ <td>2008-02-04</td>
+ </tr>
+ <tr>
+ <td>34</td>
+ <td>325.3</td>
+ <td>Paul</td>
+ <td>$90.14</td>
+
+ <td>2010-10-30</td>
+ </tr>
+ <tr>
+ <td>35</td>
+ <td>776.3</td>
+ <td>Rob</td>
+ <td>$30.84</td>
+
+ <td>2010-04-17</td>
+ </tr>
+ <tr>
+ <td>36</td>
+ <td>300.8</td>
+ <td>Walt</td>
+ <td>$75.74</td>
+
+ <td>2009-11-18</td>
+ </tr>
+ <tr>
+ <td>37</td>
+ <td>598</td>
+ <td>Nathan</td>
+ <td>$51.04</td>
+
+ <td>2010-07-15</td>
+ </tr>
+ <tr>
+ <td>38</td>
+ <td>155.6</td>
+ <td>Dan</td>
+ <td>$29.74</td>
+
+ <td>2008-06-04</td>
+ </tr>
+ <tr>
+ <td>39</td>
+ <td>759.8</td>
+ <td>Jeff</td>
+ <td>$46.44</td>
+
+ <td>2010-08-21</td>
+ </tr>
+ <tr>
+ <td>40</td>
+ <td>599.2</td>
+ <td>Bill</td>
+ <td>$7.43</td>
+
+ <td>2008-09-16</td>
+ </tr>
+ <tr>
+ <td>41</td>
+ <td>571.9</td>
+ <td>Joe</td>
+ <td>$34.84</td>
+
+ <td>2010-09-23</td>
+ </tr>
+ <tr>
+ <td>42</td>
+ <td>900.3</td>
+ <td>Bob</td>
+ <td>$19.84</td>
+
+ <td>2009-01-09</td>
+ </tr>
+ <tr>
+ <td>43</td>
+ <td>292.2</td>
+ <td>Matt</td>
+ <td>$37.94</td>
+
+ <td>2008-12-21</td>
+ </tr>
+ <tr>
+ <td>44</td>
+ <td>333</td>
+ <td>Mark</td>
+ <td>$70.54</td>
+
+ <td>2008-08-28</td>
+ </tr>
+ <tr>
+ <td>45</td>
+ <td>236.4</td>
+ <td>Tom</td>
+ <td>$48.14</td>
+
+ <td>2009-08-19</td>
+ </tr>
+ <tr>
+ <td>46</td>
+ <td>970.9</td>
+ <td>Jake</td>
+ <td>$78.24</td>
+
+ <td>2008-11-10</td>
+ </tr>
+ <tr>
+ <td>47</td>
+ <td>575.8</td>
+ <td>Greg</td>
+ <td>$37.94</td>
+
+ <td>2010-06-24</td>
+ </tr>
+ <tr>
+ <td>48</td>
+ <td>386.7</td>
+ <td>Adam</td>
+ <td>$53.54</td>
+
+ <td>2008-04-02</td>
+ </tr>
+ <tr>
+ <td>49</td>
+ <td>531.1</td>
+ <td>Steve</td>
+ <td>$29.54</td>
+
+ <td>2009-09-21</td>
+ </tr>
+ <tr>
+ <td>50</td>
+ <td>374.3</td>
+ <td>George</td>
+ <td>$89.44</td>
+
+ <td>2009-12-15</td>
+ </tr>
+ <tr>
+ <td>51</td>
+ <td>609.1</td>
+ <td>John</td>
+ <td>$46.64</td>
+
+ <td>2011-01-22</td>
+ </tr>
+ <tr>
+ <td>52</td>
+ <td>480.3</td>
+ <td>Phil</td>
+ <td>$36.64</td>
+
+ <td>2008-07-07</td>
+ </tr>
+ <tr>
+ <td>53</td>
+ <td>814.8</td>
+ <td>Jack</td>
+ <td>$65.84</td>
+
+ <td>2009-09-19</td>
+ </tr>
+ <tr>
+ <td>54</td>
+ <td>132.2</td>
+ <td>Paul</td>
+ <td>$99.14</td>
+
+ <td>2008-10-12</td>
+ </tr>
+ <tr>
+ <td>55</td>
+ <td>350.1</td>
+ <td>Rob</td>
+ <td>$22.84</td>
+
+ <td>2010-04-22</td>
+ </tr>
+ <tr>
+ <td>56</td>
+ <td>875.7</td>
+ <td>Walt</td>
+ <td>$19.84</td>
+
+ <td>2009-08-12</td>
+ </tr>
+ <tr>
+ <td>57</td>
+ <td>158.1</td>
+ <td>Nathan</td>
+ <td>$77.44</td>
+
+ <td>2010-10-25</td>
+ </tr>
+ <tr>
+ <td>58</td>
+ <td>950.9</td>
+ <td>Dan</td>
+ <td>$16.14</td>
+
+ <td>2009-05-05</td>
+ </tr>
+ <tr>
+ <td>59</td>
+ <td>41.1</td>
+ <td>Jeff</td>
+ <td>$69.24</td>
+
+ <td>2010-04-11</td>
+ </tr>
+ <tr>
+ <td>60</td>
+ <td>595.4</td>
+ <td>Bill</td>
+ <td>$6.63</td>
+
+ <td>2009-12-09</td>
+ </tr>
+ <tr>
+ <td>61</td>
+ <td>223.4</td>
+ <td>Joe</td>
+ <td>$67.54</td>
+
+ <td>2008-03-30</td>
+ </tr>
+ <tr>
+ <td>62</td>
+ <td>199.2</td>
+ <td>Bob</td>
+ <td>$15.64</td>
+
+ <td>2009-05-28</td>
+ </tr>
+ <tr>
+ <td>63</td>
+ <td>372.8</td>
+ <td>Matt</td>
+ <td>$97.04</td>
+
+ <td>2008-04-28</td>
+ </tr>
+ <tr>
+ <td>64</td>
+ <td>925.7</td>
+ <td>Mark</td>
+ <td>$10.24</td>
+
+ <td>2008-04-17</td>
+ </tr>
+ <tr>
+ <td>65</td>
+ <td>183.1</td>
+ <td>Tom</td>
+ <td>$45.34</td>
+
+ <td>2009-01-05</td>
+ </tr>
+ <tr>
+ <td>66</td>
+ <td>921.2</td>
+ <td>Jake</td>
+ <td>$32.84</td>
+
+ <td>2009-08-23</td>
+ </tr>
+ <tr>
+ <td>67</td>
+ <td>440.8</td>
+ <td>Greg</td>
+ <td>$48.64</td>
+
+ <td>2008-12-04</td>
+ </tr>
+ <tr>
+ <td>68</td>
+ <td>339.8</td>
+ <td>Adam</td>
+ <td>$43.74</td>
+
+ <td>2009-06-08</td>
+ </tr>
+ <tr>
+ <td>69</td>
+ <td>773.7</td>
+ <td>Steve</td>
+ <td>$47.84</td>
+
+ <td>2008-06-17</td>
+ </tr>
+ <tr>
+ <td>70</td>
+ <td>502.3</td>
+ <td>George</td>
+ <td>$7.33</td>
+
+ <td>2008-09-01</td>
+ </tr>
+ <tr>
+ <td>71</td>
+ <td>124.8</td>
+ <td>John</td>
+ <td>$29.74</td>
+
+ <td>2010-10-22</td>
+ </tr>
+ <tr>
+ <td>72</td>
+ <td>213</td>
+ <td>Phil</td>
+ <td>$49.64</td>
+
+ <td>2008-02-18</td>
+ </tr>
+ <tr>
+ <td>73</td>
+ <td>667.3</td>
+ <td>Jack</td>
+ <td>$86.94</td>
+
+ <td>2008-01-14</td>
+ </tr>
+ <tr>
+ <td>74</td>
+ <td>779.8</td>
+ <td>Paul</td>
+ <td>$79.44</td>
+
+ <td>2008-05-12</td>
+ </tr>
+ <tr>
+ <td>75</td>
+ <td>883.3</td>
+ <td>Rob</td>
+ <td>$97.74</td>
+
+ <td>2009-10-17</td>
+ </tr>
+ <tr>
+ <td>76</td>
+ <td>214.4</td>
+ <td>Walt</td>
+ <td>$89.94</td>
+
+ <td>2010-11-01</td>
+ </tr>
+ <tr>
+ <td>77</td>
+ <td>743.7</td>
+ <td>Nathan</td>
+ <td>$33.94</td>
+
+ <td>2009-03-16</td>
+ </tr>
+ <tr>
+ <td>78</td>
+ <td>47</td>
+ <td>Dan</td>
+ <td>$67.94</td>
+
+ <td>2010-08-04</td>
+ </tr>
+ <tr>
+ <td>79</td>
+ <td>511</td>
+ <td>Jeff</td>
+ <td>$45.34</td>
+
+ <td>2008-12-08</td>
+ </tr>
+ <tr>
+ <td>80</td>
+ <td>666.7</td>
+ <td>Bill</td>
+ <td>$95.54</td>
+
+ <td>2009-03-03</td>
+ </tr>
+ <tr>
+ <td>81</td>
+ <td>888.5</td>
+ <td>Joe</td>
+ <td>$8.03</td>
+
+ <td>2010-02-09</td>
+ </tr>
+ <tr>
+ <td>82</td>
+ <td>785.4</td>
+ <td>Bob</td>
+ <td>$29.34</td>
+
+ <td>2008-07-06</td>
+ </tr>
+ <tr>
+ <td>83</td>
+ <td>837.7</td>
+ <td>Matt</td>
+ <td>$96.04</td>
+
+ <td>2008-02-05</td>
+ </tr>
+ <tr>
+ <td>84</td>
+ <td>860.2</td>
+ <td>Mark</td>
+ <td>$74.04</td>
+
+ <td>2010-08-12</td>
+ </tr>
+ <tr>
+ <td>85</td>
+ <td>985</td>
+ <td>Tom</td>
+ <td>$62.34</td>
+
+ <td>2010-07-17</td>
+ </tr>
+ <tr>
+ <td>86</td>
+ <td>562.3</td>
+ <td>Jake</td>
+ <td>$83.74</td>
+
+ <td>2010-03-21</td>
+ </tr>
+ <tr>
+ <td>87</td>
+ <td>467.6</td>
+ <td>Greg</td>
+ <td>$58.14</td>
+
+ <td>2008-02-16</td>
+ </tr>
+ <tr>
+ <td>88</td>
+ <td>859</td>
+ <td>Adam</td>
+ <td>$62.84</td>
+
+ <td>2010-04-12</td>
+ </tr>
+ <tr>
+ <td>89</td>
+ <td>687.5</td>
+ <td>Steve</td>
+ <td>$13.94</td>
+
+ <td>2008-07-17</td>
+ </tr>
+ <tr>
+ <td>90</td>
+ <td>993.9</td>
+ <td>George</td>
+ <td>$80.54</td>
+
+ <td>2008-05-26</td>
+ </tr>
+ <tr>
+ <td>91</td>
+ <td>373.8</td>
+ <td>John</td>
+ <td>$69.44</td>
+
+ <td>2008-08-26</td>
+ </tr>
+ <tr>
+ <td>92</td>
+ <td>50.4</td>
+ <td>Phil</td>
+ <td>$47.94</td>
+
+ <td>2009-07-30</td>
+ </tr>
+ <tr>
+ <td>93</td>
+ <td>222.8</td>
+ <td>Jack</td>
+ <td>$31.74</td>
+
+ <td>2009-06-14</td>
+ </tr>
+ <tr>
+ <td>94</td>
+ <td>263.9</td>
+ <td>Paul</td>
+ <td>$17.74</td>
+
+ <td>2008-08-16</td>
+ </tr>
+ <tr>
+ <td>95</td>
+ <td>99.2</td>
+ <td>Rob</td>
+ <td>$16.24</td>
+
+ <td>2010-08-07</td>
+ </tr>
+ <tr>
+ <td>96</td>
+ <td>911.8</td>
+ <td>Walt</td>
+ <td>$72.44</td>
+
+ <td>2010-01-31</td>
+ </tr>
+ <tr>
+ <td>97</td>
+ <td>623</td>
+ <td>Nathan</td>
+ <td>$19.24</td>
+
+ <td>2008-10-03</td>
+ </tr>
+ <tr>
+ <td>98</td>
+ <td>673.4</td>
+ <td>Dan</td>
+ <td>$5.03</td>
+
+ <td>2010-09-29</td>
+ </tr>
+ <tr>
+ <td>99</td>
+ <td>402.8</td>
+ <td>Jeff</td>
+ <td>$73.84</td>
+
+ <td>2008-01-06</td>
+ </tr>
+ <tr>
+ <td>100</td>
+ <td>584.8</td>
+ <td>Bill</td>
+ <td>$73.24</td>
+
+ <td>2010-07-26</td>
+ </tr>
+ <tr>
+ <td>101</td>
+ <td>721.7</td>
+ <td>Joe</td>
+ <td>$10.64</td>
+
+ <td>2009-08-06</td>
+ </tr>
+ <tr>
+ <td>102</td>
+ <td>938.1</td>
+ <td>Bob</td>
+ <td>$15.64</td>
+
+ <td>2011-02-11</td>
+ </tr>
+ <tr>
+ <td>103</td>
+ <td>447.1</td>
+ <td>Matt</td>
+ <td>$37.94</td>
+
+ <td>2008-12-12</td>
+ </tr>
+ <tr>
+ <td>104</td>
+ <td>915.9</td>
+ <td>Mark</td>
+ <td>$64.34</td>
+
+ <td>2009-07-05</td>
+ </tr>
+ <tr>
+ <td>105</td>
+ <td>124.2</td>
+ <td>Tom</td>
+ <td>$74.24</td>
+
+ <td>2010-01-08</td>
+ </tr>
+ <tr>
+ <td>106</td>
+ <td>955.3</td>
+ <td>Jake</td>
+ <td>$65.34</td>
+
+ <td>2009-02-23</td>
+ </tr>
+ <tr>
+ <td>107</td>
+ <td>623.6</td>
+ <td>Greg</td>
+ <td>$27.64</td>
+
+ <td>2009-10-02</td>
+ </tr>
+ <tr>
+ <td>108</td>
+ <td>872.6</td>
+ <td>Adam</td>
+ <td>$95.04</td>
+
+ <td>2009-11-30</td>
+ </tr>
+ <tr>
+ <td>109</td>
+ <td>749.4</td>
+ <td>Steve</td>
+ <td>$35.34</td>
+
+ <td>2009-01-30</td>
+ </tr>
+ <tr>
+ <td>110</td>
+ <td>764.7</td>
+ <td>George</td>
+ <td>$93.74</td>
+
+ <td>2008-03-26</td>
+ </tr>
+ <tr>
+ <td>111</td>
+ <td>585.4</td>
+ <td>John</td>
+ <td>$65.94</td>
+
+ <td>2008-07-26</td>
+ </tr>
+ <tr>
+ <td>112</td>
+ <td>99.8</td>
+ <td>Phil</td>
+ <td>$59.74</td>
+
+ <td>2009-01-23</td>
+ </tr>
+ <tr>
+ <td>113</td>
+ <td>93.2</td>
+ <td>Jack</td>
+ <td>$4.43</td>
+
+ <td>2010-04-06</td>
+ </tr>
+ <tr>
+ <td>114</td>
+ <td>403.3</td>
+ <td>Paul</td>
+ <td>$96.04</td>
+
+ <td>2009-02-16</td>
+ </tr>
+ <tr>
+ <td>115</td>
+ <td>890.2</td>
+ <td>Rob</td>
+ <td>$8.43</td>
+
+ <td>2008-04-23</td>
+ </tr>
+ <tr>
+ <td>116</td>
+ <td>538.9</td>
+ <td>Walt</td>
+ <td>$3.93</td>
+
+ <td>2010-05-19</td>
+ </tr>
+ <tr>
+ <td>117</td>
+ <td>911.6</td>
+ <td>Nathan</td>
+ <td>$66.34</td>
+
+ <td>2008-02-02</td>
+ </tr>
+ <tr>
+ <td>118</td>
+ <td>475.9</td>
+ <td>Dan</td>
+ <td>$53.54</td>
+
+ <td>2011-02-05</td>
+ </tr>
+ <tr>
+ <td>119</td>
+ <td>90.7</td>
+ <td>Jeff</td>
+ <td>$28.54</td>
+
+ <td>2009-01-16</td>
+ </tr>
+ <tr>
+ <td>120</td>
+ <td>443.3</td>
+ <td>Bill</td>
+ <td>$5.03</td>
+
+ <td>2008-11-05</td>
+ </tr>
+ <tr>
+ <td>121</td>
+ <td>527.7</td>
+ <td>Joe</td>
+ <td>$63.54</td>
+
+ <td>2010-12-07</td>
+ </tr>
+ <tr>
+ <td>122</td>
+ <td>717.7</td>
+ <td>Bob</td>
+ <td>$73.54</td>
+
+ <td>2009-08-28</td>
+ </tr>
+ <tr>
+ <td>123</td>
+ <td>63.5</td>
+ <td>Matt</td>
+ <td>$82.84</td>
+
+ <td>2009-10-18</td>
+ </tr>
+ <tr>
+ <td>124</td>
+ <td>788</td>
+ <td>Mark</td>
+ <td>$23.14</td>
+
+ <td>2009-09-02</td>
+ </tr>
+ <tr>
+ <td>125</td>
+ <td>155</td>
+ <td>Tom</td>
+ <td>$12.14</td>
+
+ <td>2009-12-08</td>
+ </tr>
+ <tr>
+ <td>126</td>
+ <td>263.6</td>
+ <td>Jake</td>
+ <td>$66.04</td>
+
+ <td>2010-01-22</td>
+ </tr>
+ <tr>
+ <td>127</td>
+ <td>25.6</td>
+ <td>Greg</td>
+ <td>$57.24</td>
+
+ <td>2008-12-28</td>
+ </tr>
+ <tr>
+ <td>128</td>
+ <td>63.9</td>
+ <td>Adam</td>
+ <td>$4.73</td>
+
+ <td>2010-09-09</td>
+ </tr>
+ <tr>
+ <td>129</td>
+ <td>52</td>
+ <td>Steve</td>
+ <td>$13.84</td>
+
+ <td>2008-06-03</td>
+ </tr>
+ <tr>
+ <td>130</td>
+ <td>392.5</td>
+ <td>George</td>
+ <td>$58.14</td>
+
+ <td>2008-07-31</td>
+ </tr>
+ <tr>
+ <td>131</td>
+ <td>670.3</td>
+ <td>John</td>
+ <td>$10.94</td>
+
+ <td>2010-08-04</td>
+ </tr>
+ <tr>
+ <td>132</td>
+ <td>607</td>
+ <td>Phil</td>
+ <td>$82.74</td>
+
+ <td>2009-10-01</td>
+ </tr>
+ <tr>
+ <td>133</td>
+ <td>140.7</td>
+ <td>Jack</td>
+ <td>$89.04</td>
+
+ <td>2009-03-16</td>
+ </tr>
+ <tr>
+ <td>134</td>
+ <td>718.3</td>
+ <td>Paul</td>
+ <td>$67.84</td>
+
+ <td>2009-12-08</td>
+ </tr>
+ <tr>
+ <td>135</td>
+ <td>255.9</td>
+ <td>Rob</td>
+ <td>$83.34</td>
+
+ <td>2010-04-27</td>
+ </tr>
+ <tr>
+ <td>136</td>
+ <td>877.6</td>
+ <td>Walt</td>
+ <td>$9.73</td>
+
+ <td>2009-03-29</td>
+ </tr>
+ <tr>
+ <td>137</td>
+ <td>538.6</td>
+ <td>Nathan</td>
+ <td>$12.24</td>
+
+ <td>2011-01-20</td>
+ </tr>
+ <tr>
+ <td>138</td>
+ <td>862.5</td>
+ <td>Dan</td>
+ <td>$18.64</td>
+
+ <td>2008-01-13</td>
+ </tr>
+ <tr>
+ <td>139</td>
+ <td>721.9</td>
+ <td>Jeff</td>
+ <td>$23.84</td>
+
+ <td>2008-06-21</td>
+ </tr>
+ <tr>
+ <td>140</td>
+ <td>866.2</td>
+ <td>Bill</td>
+ <td>$63.04</td>
+
+ <td>2010-04-25</td>
+ </tr>
+ <tr>
+ <td>141</td>
+ <td>59.9</td>
+ <td>Joe</td>
+ <td>$30.14</td>
+
+ <td>2010-08-29</td>
+ </tr>
+ <tr>
+ <td>142</td>
+ <td>888.4</td>
+ <td>Bob</td>
+ <td>$90.84</td>
+
+ <td>2010-02-09</td>
+ </tr>
+ <tr>
+ <td>143</td>
+ <td>451.5</td>
+ <td>Matt</td>
+ <td>$4.83</td>
+
+ <td>2009-10-05</td>
+ </tr>
+ <tr>
+ <td>144</td>
+ <td>842.2</td>
+ <td>Mark</td>
+ <td>$76.74</td>
+
+ <td>2008-09-27</td>
+ </tr>
+ <tr>
+ <td>145</td>
+ <td>463.9</td>
+ <td>Tom</td>
+ <td>$2.23</td>
+
+ <td>2008-03-18</td>
+ </tr>
+ <tr>
+ <td>146</td>
+ <td>206.6</td>
+ <td>Jake</td>
+ <td>$90.04</td>
+
+ <td>2008-07-08</td>
+ </tr>
+ <tr>
+ <td>147</td>
+ <td>609.3</td>
+ <td>Greg</td>
+ <td>$43.84</td>
+
+ <td>2008-11-26</td>
+ </tr>
+ <tr>
+ <td>148</td>
+ <td>583.6</td>
+ <td>Adam</td>
+ <td>$30.14</td>
+
+ <td>2009-06-29</td>
+ </tr>
+ <tr>
+ <td>149</td>
+ <td>605.2</td>
+ <td>Steve</td>
+ <td>$2.33</td>
+
+ <td>2010-03-31</td>
+ </tr>
+ <tr>
+ <td>150</td>
+ <td>764.8</td>
+ <td>George</td>
+ <td>$88.94</td>
+
+ <td>2009-01-27</td>
+ </tr>
+ <tr>
+ <td>151</td>
+ <td>505.6</td>
+ <td>John</td>
+ <td>$94.94</td>
+
+ <td>2010-01-10</td>
+ </tr>
+ <tr>
+ <td>152</td>
+ <td>355.4</td>
+ <td>Phil</td>
+ <td>$83.74</td>
+
+ <td>2009-09-25</td>
+ </tr>
+ <tr>
+ <td>153</td>
+ <td>31.9</td>
+ <td>Jack</td>
+ <td>$28.84</td>
+
+ <td>2009-11-20</td>
+ </tr>
+ <tr>
+ <td>154</td>
+ <td>598.4</td>
+ <td>Paul</td>
+ <td>$13.14</td>
+
+ <td>2009-02-23</td>
+ </tr>
+ <tr>
+ <td>155</td>
+ <td>842.9</td>
+ <td>Rob</td>
+ <td>$59.44</td>
+
+ <td>2009-03-20</td>
+ </tr>
+ <tr>
+ <td>156</td>
+ <td>920.5</td>
+ <td>Walt</td>
+ <td>$80.14</td>
+
+ <td>2008-11-24</td>
+ </tr>
+ <tr>
+ <td>157</td>
+ <td>94.5</td>
+ <td>Nathan</td>
+ <td>$41.04</td>
+
+ <td>2010-04-16</td>
+ </tr>
+ <tr>
+ <td>158</td>
+ <td>390.6</td>
+ <td>Dan</td>
+ <td>$99.44</td>
+
+ <td>2008-01-28</td>
+ </tr>
+ <tr>
+ <td>159</td>
+ <td>872.6</td>
+ <td>Jeff</td>
+ <td>$59.94</td>
+
+ <td>2008-02-23</td>
+ </tr>
+ <tr>
+ <td>160</td>
+ <td>592.3</td>
+ <td>Bill</td>
+ <td>$36.44</td>
+
+ <td>2010-12-18</td>
+ </tr>
+ <tr>
+ <td>161</td>
+ <td>942.4</td>
+ <td>Joe</td>
+ <td>$86.94</td>
+
+ <td>2010-10-19</td>
+ </tr>
+ <tr>
+ <td>162</td>
+ <td>593</td>
+ <td>Bob</td>
+ <td>$22.44</td>
+
+ <td>2010-04-13</td>
+ </tr>
+ <tr>
+ <td>163</td>
+ <td>151.1</td>
+ <td>Matt</td>
+ <td>$25.64</td>
+
+ <td>2008-01-11</td>
+ </tr>
+ <tr>
+ <td>164</td>
+ <td>757.4</td>
+ <td>Mark</td>
+ <td>$85.54</td>
+
+ <td>2008-06-10</td>
+ </tr>
+ <tr>
+ <td>165</td>
+ <td>130</td>
+ <td>Tom</td>
+ <td>$69.84</td>
+
+ <td>2010-04-29</td>
+ </tr>
+ <tr>
+ <td>166</td>
+ <td>525</td>
+ <td>Jake</td>
+ <td>$61.84</td>
+
+ <td>2009-09-10</td>
+ </tr>
+ <tr>
+ <td>167</td>
+ <td>819.8</td>
+ <td>Greg</td>
+ <td>$71.34</td>
+
+ <td>2010-12-29</td>
+ </tr>
+ <tr>
+ <td>168</td>
+ <td>552.9</td>
+ <td>Adam</td>
+ <td>$10.34</td>
+
+ <td>2010-12-22</td>
+ </tr>
+ <tr>
+ <td>169</td>
+ <td>586.8</td>
+ <td>Steve</td>
+ <td>$97.54</td>
+
+ <td>2009-09-13</td>
+ </tr>
+ <tr>
+ <td>170</td>
+ <td>643.5</td>
+ <td>George</td>
+ <td>$56.84</td>
+
+ <td>2010-11-08</td>
+ </tr>
+ <tr>
+ <td>171</td>
+ <td>588.9</td>
+ <td>John</td>
+ <td>$51.04</td>
+
+ <td>2010-06-10</td>
+ </tr>
+ <tr>
+ <td>172</td>
+ <td>482.9</td>
+ <td>Phil</td>
+ <td>$10.34</td>
+
+ <td>2007-12-25</td>
+ </tr>
+ <tr>
+ <td>173</td>
+ <td>213.9</td>
+ <td>Jack</td>
+ <td>$25.44</td>
+
+ <td>2008-10-17</td>
+ </tr>
+ <tr>
+ <td>174</td>
+ <td>233.2</td>
+ <td>Paul</td>
+ <td>$1.13</td>
+
+ <td>2008-05-01</td>
+ </tr>
+ <tr>
+ <td>175</td>
+ <td>383</td>
+ <td>Rob</td>
+ <td>$14.24</td>
+
+ <td>2010-07-18</td>
+ </tr>
+ <tr>
+ <td>176</td>
+ <td>127.1</td>
+ <td>Walt</td>
+ <td>$66.74</td>
+
+ <td>2009-05-01</td>
+ </tr>
+ <tr>
+ <td>177</td>
+ <td>672.2</td>
+ <td>Nathan</td>
+ <td>$48.64</td>
+
+ <td>2008-06-03</td>
+ </tr>
+ <tr>
+ <td>178</td>
+ <td>627.4</td>
+ <td>Dan</td>
+ <td>$3.93</td>
+
+ <td>2008-09-30</td>
+ </tr>
+ <tr>
+ <td>179</td>
+ <td>576.3</td>
+ <td>Jeff</td>
+ <td>$62.64</td>
+
+ <td>2008-09-01</td>
+ </tr>
+ <tr>
+ <td>180</td>
+ <td>124.1</td>
+ <td>Bill</td>
+ <td>$26.94</td>
+
+ <td>2010-06-20</td>
+ </tr>
+ <tr>
+ <td>181</td>
+ <td>35.3</td>
+ <td>Joe</td>
+ <td>$85.84</td>
+
+ <td>2008-11-30</td>
+ </tr>
+ <tr>
+ <td>182</td>
+ <td>815.7</td>
+ <td>Bob</td>
+ <td>$34.14</td>
+
+ <td>2009-03-30</td>
+ </tr>
+ <tr>
+ <td>183</td>
+ <td>820.6</td>
+ <td>Matt</td>
+ <td>$55.54</td>
+
+ <td>2010-01-18</td>
+ </tr>
+ <tr>
+ <td>184</td>
+ <td>81.8</td>
+ <td>Mark</td>
+ <td>$78.84</td>
+
+ <td>2010-01-31</td>
+ </tr>
+ <tr>
+ <td>185</td>
+ <td>197.5</td>
+ <td>Tom</td>
+ <td>$17.14</td>
+
+ <td>2010-07-14</td>
+ </tr>
+ <tr>
+ <td>186</td>
+ <td>10.8</td>
+ <td>Jake</td>
+ <td>$29.84</td>
+
+ <td>2009-06-23</td>
+ </tr>
+ <tr>
+ <td>187</td>
+ <td>442</td>
+ <td>Greg</td>
+ <td>$97.04</td>
+
+ <td>2011-01-06</td>
+ </tr>
+ <tr>
+ <td>188</td>
+ <td>585.7</td>
+ <td>Adam</td>
+ <td>$59.74</td>
+
+ <td>2007-12-21</td>
+ </tr>
+ <tr>
+ <td>189</td>
+ <td>832.2</td>
+ <td>Steve</td>
+ <td>$17.44</td>
+
+ <td>2009-12-14</td>
+ </tr>
+ <tr>
+ <td>190</td>
+ <td>54.3</td>
+ <td>George</td>
+ <td>$29.84</td>
+
+ <td>2010-10-22</td>
+ </tr>
+ <tr>
+ <td>191</td>
+ <td>844</td>
+ <td>John</td>
+ <td>$33.34</td>
+
+ <td>2010-05-10</td>
+ </tr>
+ <tr>
+ <td>192</td>
+ <td>143.9</td>
+ <td>Phil</td>
+ <td>$14.94</td>
+
+ <td>2008-04-07</td>
+ </tr>
+ <tr>
+ <td>193</td>
+ <td>546.8</td>
+ <td>Jack</td>
+ <td>$96.94</td>
+
+ <td>2010-01-09</td>
+ </tr>
+ <tr>
+ <td>194</td>
+ <td>203.8</td>
+ <td>Paul</td>
+ <td>$5.13</td>
+
+ <td>2009-05-09</td>
+ </tr>
+ <tr>
+ <td>195</td>
+ <td>872.3</td>
+ <td>Rob</td>
+ <td>$24.84</td>
+
+ <td>2009-11-22</td>
+ </tr>
+ <tr>
+ <td>196</td>
+ <td>682.3</td>
+ <td>Walt</td>
+ <td>$25.94</td>
+
+ <td>2010-11-02</td>
+ </tr>
+ <tr>
+ <td>197</td>
+ <td>158.7</td>
+ <td>Nathan</td>
+ <td>$70.14</td>
+
+ <td>2010-09-28</td>
+ </tr>
+ <tr>
+ <td>198</td>
+ <td>121.2</td>
+ <td>Dan</td>
+ <td>$28.74</td>
+
+ <td>2009-06-19</td>
+ </tr>
+ <tr>
+ <td>199</td>
+ <td>122.6</td>
+ <td>Jeff</td>
+ <td>$11.94</td>
+
+ <td>2010-01-06</td>
+ </tr>
+ <tr>
+ <td>200</td>
+ <td>749.8</td>
+ <td>Bill</td>
+ <td>$17.34</td>
+
+ <td>2010-12-17</td>
+ </tr>
+ <tr>
+ <td>201</td>
+ <td>646.1</td>
+ <td>Joe</td>
+ <td>$1.73</td>
+
+ <td>2008-11-05</td>
+ </tr>
+ <tr>
+ <td>202</td>
+ <td>400.4</td>
+ <td>Bob</td>
+ <td>$16.14</td>
+
+ <td>2009-04-26</td>
+ </tr>
+ <tr>
+ <td>203</td>
+ <td>495.5</td>
+ <td>Matt</td>
+ <td>$70.84</td>
+
+ <td>2009-03-21</td>
+ </tr>
+ <tr>
+ <td>204</td>
+ <td>145.3</td>
+ <td>Mark</td>
+ <td>$91.24</td>
+
+ <td>2009-05-19</td>
+ </tr>
+ <tr>
+ <td>205</td>
+ <td>582.9</td>
+ <td>Tom</td>
+ <td>$78.44</td>
+
+ <td>2010-03-02</td>
+ </tr>
+ <tr>
+ <td>206</td>
+ <td>191.3</td>
+ <td>Jake</td>
+ <td>$46.64</td>
+
+ <td>2010-12-27</td>
+ </tr>
+ <tr>
+ <td>207</td>
+ <td>97.5</td>
+ <td>Greg</td>
+ <td>$62.54</td>
+
+ <td>2010-01-15</td>
+ </tr>
+ <tr>
+ <td>208</td>
+ <td>973.7</td>
+ <td>Adam</td>
+ <td>$74.64</td>
+
+ <td>2010-12-13</td>
+ </tr>
+ <tr>
+ <td>209</td>
+ <td>447.2</td>
+ <td>Steve</td>
+ <td>$86.84</td>
+
+ <td>2008-02-27</td>
+ </tr>
+ <tr>
+ <td>210</td>
+ <td>94.3</td>
+ <td>George</td>
+ <td>$61.84</td>
+
+ <td>2008-09-15</td>
+ </tr>
+ <tr>
+ <td>211</td>
+ <td>39</td>
+ <td>John</td>
+ <td>$26.44</td>
+
+ <td>2008-10-04</td>
+ </tr>
+ <tr>
+ <td>212</td>
+ <td>316.7</td>
+ <td>Phil</td>
+ <td>$66.54</td>
+
+ <td>2009-04-09</td>
+ </tr>
+ <tr>
+ <td>213</td>
+ <td>743</td>
+ <td>Jack</td>
+ <td>$16.04</td>
+
+ <td>2008-05-05</td>
+ </tr>
+ <tr>
+ <td>214</td>
+ <td>138.4</td>
+ <td>Paul</td>
+ <td>$30.54</td>
+
+ <td>2008-01-24</td>
+ </tr>
+ <tr>
+ <td>215</td>
+ <td>584.7</td>
+ <td>Rob</td>
+ <td>$88.84</td>
+
+ <td>2010-07-19</td>
+ </tr>
+ <tr>
+ <td>216</td>
+ <td>279.3</td>
+ <td>Walt</td>
+ <td>$7.93</td>
+
+ <td>2008-11-08</td>
+ </tr>
+ <tr>
+ <td>217</td>
+ <td>233</td>
+ <td>Nathan</td>
+ <td>$17.74</td>
+
+ <td>2010-11-01</td>
+ </tr>
+ <tr>
+ <td>218</td>
+ <td>887.8</td>
+ <td>Dan</td>
+ <td>$15.04</td>
+
+ <td>2010-01-11</td>
+ </tr>
+ <tr>
+ <td>219</td>
+ <td>829.3</td>
+ <td>Jeff</td>
+ <td>$59.84</td>
+
+ <td>2009-08-12</td>
+ </tr>
+ <tr>
+ <td>220</td>
+ <td>889.7</td>
+ <td>Bill</td>
+ <td>$69.24</td>
+
+ <td>2008-05-27</td>
+ </tr>
+ <tr>
+ <td>221</td>
+ <td>123.3</td>
+ <td>Joe</td>
+ <td>$73.14</td>
+
+ <td>2009-03-29</td>
+ </tr>
+ <tr>
+ <td>222</td>
+ <td>373.9</td>
+ <td>Bob</td>
+ <td>$4.73</td>
+
+ <td>2008-03-06</td>
+ </tr>
+ <tr>
+ <td>223</td>
+ <td>785.6</td>
+ <td>Matt</td>
+ <td>$79.04</td>
+
+ <td>2008-09-07</td>
+ </tr>
+ <tr>
+ <td>224</td>
+ <td>904.9</td>
+ <td>Mark</td>
+ <td>$92.94</td>
+
+ <td>2009-08-26</td>
+ </tr>
+ <tr>
+ <td>225</td>
+ <td>935.8</td>
+ <td>Tom</td>
+ <td>$51.34</td>
+
+ <td>2009-04-19</td>
+ </tr>
+ <tr>
+ <td>226</td>
+ <td>750.5</td>
+ <td>Jake</td>
+ <td>$79.34</td>
+
+ <td>2009-07-19</td>
+ </tr>
+ <tr>
+ <td>227</td>
+ <td>31.2</td>
+ <td>Greg</td>
+ <td>$2.53</td>
+
+ <td>2010-02-09</td>
+ </tr>
+ <tr>
+ <td>228</td>
+ <td>936.7</td>
+ <td>Adam</td>
+ <td>$91.34</td>
+
+ <td>2010-08-02</td>
+ </tr>
+ <tr>
+ <td>229</td>
+ <td>588</td>
+ <td>Steve</td>
+ <td>$74.24</td>
+
+ <td>2009-04-23</td>
+ </tr>
+ <tr>
+ <td>230</td>
+ <td>107.7</td>
+ <td>George</td>
+ <td>$63.24</td>
+
+ <td>2008-05-01</td>
+ </tr>
+ <tr>
+ <td>231</td>
+ <td>245.7</td>
+ <td>John</td>
+ <td>$75.54</td>
+
+ <td>2010-08-25</td>
+ </tr>
+ <tr>
+ <td>232</td>
+ <td>647.8</td>
+ <td>Phil</td>
+ <td>$12.94</td>
+
+ <td>2010-10-19</td>
+ </tr>
+ <tr>
+ <td>233</td>
+ <td>714.6</td>
+ <td>Jack</td>
+ <td>$91.54</td>
+
+ <td>2010-02-18</td>
+ </tr>
+ <tr>
+ <td>234</td>
+ <td>941.3</td>
+ <td>Paul</td>
+ <td>$82.04</td>
+
+ <td>2009-11-28</td>
+ </tr>
+ <tr>
+ <td>235</td>
+ <td>473.3</td>
+ <td>Rob</td>
+ <td>$75.54</td>
+
+ <td>2008-05-13</td>
+ </tr>
+ <tr>
+ <td>236</td>
+ <td>893.4</td>
+ <td>Walt</td>
+ <td>$50.64</td>
+
+ <td>2010-11-17</td>
+ </tr>
+ <tr>
+ <td>237</td>
+ <td>392.7</td>
+ <td>Nathan</td>
+ <td>$53.74</td>
+
+ <td>2010-12-16</td>
+ </tr>
+ <tr>
+ <td>238</td>
+ <td>68.8</td>
+ <td>Dan</td>
+ <td>$47.44</td>
+
+ <td>2010-09-06</td>
+ </tr>
+ <tr>
+ <td>239</td>
+ <td>895.2</td>
+ <td>Jeff</td>
+ <td>$6.13</td>
+
+ <td>2009-11-12</td>
+ </tr>
+ <tr>
+ <td>240</td>
+ <td>319.1</td>
+ <td>Bill</td>
+ <td>$16.94</td>
+
+ <td>2008-09-12</td>
+ </tr>
+ <tr>
+ <td>241</td>
+ <td>434.7</td>
+ <td>Joe</td>
+ <td>$41.54</td>
+
+ <td>2011-02-04</td>
+ </tr>
+ <tr>
+ <td>242</td>
+ <td>281.1</td>
+ <td>Bob</td>
+ <td>$6.33</td>
+
+ <td>2008-05-02</td>
+ </tr>
+ <tr>
+ <td>243</td>
+ <td>174.8</td>
+ <td>Matt</td>
+ <td>$77.74</td>
+
+ <td>2008-01-24</td>
+ </tr>
+ <tr>
+ <td>244</td>
+ <td>859</td>
+ <td>Mark</td>
+ <td>$71.84</td>
+
+ <td>2010-08-30</td>
+ </tr>
+ <tr>
+ <td>245</td>
+ <td>471.8</td>
+ <td>Tom</td>
+ <td>$19.14</td>
+
+ <td>2009-11-19</td>
+ </tr>
+ <tr>
+ <td>246</td>
+ <td>597.9</td>
+ <td>Jake</td>
+ <td>$8.53</td>
+
+ <td>2008-04-26</td>
+ </tr>
+ <tr>
+ <td>247</td>
+ <td>516.5</td>
+ <td>Greg</td>
+ <td>$47.84</td>
+
+ <td>2010-01-08</td>
+ </tr>
+ <tr>
+ <td>248</td>
+ <td>460.6</td>
+ <td>Adam</td>
+ <td>$54.64</td>
+
+ <td>2008-05-08</td>
+ </tr>
+ <tr>
+ <td>249</td>
+ <td>317.8</td>
+ <td>Steve</td>
+ <td>$44.14</td>
+
+ <td>2008-07-18</td>
+ </tr>
+ <tr>
+ <td>250</td>
+ <td>917.4</td>
+ <td>George</td>
+ <td>$76.04</td>
+
+ <td>2009-01-30</td>
+ </tr>
+ <tr>
+ <td>251</td>
+ <td>149.1</td>
+ <td>John</td>
+ <td>$19.54</td>
+
+ <td>2010-05-25</td>
+ </tr>
+ <tr>
+ <td>252</td>
+ <td>136.1</td>
+ <td>Phil</td>
+ <td>$47.64</td>
+
+ <td>2010-08-05</td>
+ </tr>
+ <tr>
+ <td>253</td>
+ <td>252.2</td>
+ <td>Jack</td>
+ <td>$65.14</td>
+
+ <td>2009-11-20</td>
+ </tr>
+ <tr>
+ <td>254</td>
+ <td>283</td>
+ <td>Paul</td>
+ <td>$51.04</td>
+
+ <td>2008-12-29</td>
+ </tr>
+ <tr>
+ <td>255</td>
+ <td>133.3</td>
+ <td>Rob</td>
+ <td>$98.24</td>
+
+ <td>2009-08-08</td>
+ </tr>
+ <tr>
+ <td>256</td>
+ <td>739</td>
+ <td>Walt</td>
+ <td>$57.94</td>
+
+ <td>2009-11-14</td>
+ </tr>
+ <tr>
+ <td>257</td>
+ <td>850.4</td>
+ <td>Nathan</td>
+ <td>$9.63</td>
+
+ <td>2008-03-19</td>
+ </tr>
+ <tr>
+ <td>258</td>
+ <td>498.6</td>
+ <td>Dan</td>
+ <td>$55.64</td>
+
+ <td>2009-12-11</td>
+ </tr>
+ <tr>
+ <td>259</td>
+ <td>620.3</td>
+ <td>Jeff</td>
+ <td>$87.44</td>
+
+ <td>2008-03-04</td>
+ </tr>
+ <tr>
+ <td>260</td>
+ <td>803.4</td>
+ <td>Bill</td>
+ <td>$79.14</td>
+
+ <td>2010-08-01</td>
+ </tr>
+ <tr>
+ <td>261</td>
+ <td>155.5</td>
+ <td>Joe</td>
+ <td>$94.04</td>
+
+ <td>2008-01-13</td>
+ </tr>
+ <tr>
+ <td>262</td>
+ <td>922.3</td>
+ <td>Bob</td>
+ <td>$7.63</td>
+
+ <td>2009-07-17</td>
+ </tr>
+ <tr>
+ <td>263</td>
+ <td>751.6</td>
+ <td>Matt</td>
+ <td>$32.94</td>
+
+ <td>2008-06-07</td>
+ </tr>
+ <tr>
+ <td>264</td>
+ <td>357.9</td>
+ <td>Mark</td>
+ <td>$61.14</td>
+
+ <td>2010-01-18</td>
+ </tr>
+ <tr>
+ <td>265</td>
+ <td>682.4</td>
+ <td>Tom</td>
+ <td>$74.54</td>
+
+ <td>2009-12-28</td>
+ </tr>
+ <tr>
+ <td>266</td>
+ <td>198.4</td>
+ <td>Jake</td>
+ <td>$48.44</td>
+
+ <td>2008-08-28</td>
+ </tr>
+ <tr>
+ <td>267</td>
+ <td>799.1</td>
+ <td>Greg</td>
+ <td>$33.44</td>
+
+ <td>2008-12-17</td>
+ </tr>
+ <tr>
+ <td>268</td>
+ <td>877.4</td>
+ <td>Adam</td>
+ <td>$83.34</td>
+
+ <td>2010-09-21</td>
+ </tr>
+ <tr>
+ <td>269</td>
+ <td>501.7</td>
+ <td>Steve</td>
+ <td>$45.34</td>
+
+ <td>2010-04-28</td>
+ </tr>
+ <tr>
+ <td>270</td>
+ <td>567.4</td>
+ <td>George</td>
+ <td>$25.64</td>
+
+ <td>2009-08-30</td>
+ </tr>
+ <tr>
+ <td>271</td>
+ <td>393.4</td>
+ <td>John</td>
+ <td>$41.14</td>
+
+ <td>2009-06-22</td>
+ </tr>
+ <tr>
+ <td>272</td>
+ <td>414.4</td>
+ <td>Phil</td>
+ <td>$33.44</td>
+
+ <td>2009-09-18</td>
+ </tr>
+ <tr>
+ <td>273</td>
+ <td>911.4</td>
+ <td>Jack</td>
+ <td>$8.53</td>
+
+ <td>2010-10-03</td>
+ </tr>
+ <tr>
+ <td>274</td>
+ <td>59.2</td>
+ <td>Paul</td>
+ <td>$44.34</td>
+
+ <td>2009-07-10</td>
+ </tr>
+ <tr>
+ <td>275</td>
+ <td>716.7</td>
+ <td>Rob</td>
+ <td>$12.64</td>
+
+ <td>2008-09-18</td>
+ </tr>
+ <tr>
+ <td>276</td>
+ <td>355.7</td>
+ <td>Walt</td>
+ <td>$32.44</td>
+
+ <td>2010-04-01</td>
+ </tr>
+ <tr>
+ <td>277</td>
+ <td>573.9</td>
+ <td>Nathan</td>
+ <td>$12.34</td>
+
+ <td>2008-02-20</td>
+ </tr>
+ <tr>
+ <td>278</td>
+ <td>887.7</td>
+ <td>Dan</td>
+ <td>$0.03</td>
+
+ <td>2010-10-10</td>
+ </tr>
+ <tr>
+ <td>279</td>
+ <td>757.8</td>
+ <td>Jeff</td>
+ <td>$50.24</td>
+
+ <td>2009-01-15</td>
+ </tr>
+ <tr>
+ <td>280</td>
+ <td>501.7</td>
+ <td>Bill</td>
+ <td>$6.93</td>
+
+ <td>2009-11-07</td>
+ </tr>
+ <tr>
+ <td>281</td>
+ <td>36.9</td>
+ <td>Joe</td>
+ <td>$46.34</td>
+
+ <td>2007-12-27</td>
+ </tr>
+ <tr>
+ <td>282</td>
+ <td>512.4</td>
+ <td>Bob</td>
+ <td>$87.74</td>
+
+ <td>2009-01-16</td>
+ </tr>
+ <tr>
+ <td>283</td>
+ <td>64.3</td>
+ <td>Matt</td>
+ <td>$78.84</td>
+
+ <td>2009-04-25</td>
+ </tr>
+ <tr>
+ <td>284</td>
+ <td>944.6</td>
+ <td>Mark</td>
+ <td>$84.74</td>
+
+ <td>2010-09-20</td>
+ </tr>
+ <tr>
+ <td>285</td>
+ <td>436.3</td>
+ <td>Tom</td>
+ <td>$56.44</td>
+
+ <td>2011-02-12</td>
+ </tr>
+ <tr>
+ <td>286</td>
+ <td>672.6</td>
+ <td>Jake</td>
+ <td>$92.04</td>
+
+ <td>2008-12-21</td>
+ </tr>
+ <tr>
+ <td>287</td>
+ <td>392.6</td>
+ <td>Greg</td>
+ <td>$49.44</td>
+
+ <td>2009-05-13</td>
+ </tr>
+ <tr>
+ <td>288</td>
+ <td>446.5</td>
+ <td>Adam</td>
+ <td>$38.14</td>
+
+ <td>2009-05-13</td>
+ </tr>
+ <tr>
+ <td>289</td>
+ <td>333</td>
+ <td>Steve</td>
+ <td>$13.94</td>
+
+ <td>2010-12-15</td>
+ </tr>
+ <tr>
+ <td>290</td>
+ <td>672.1</td>
+ <td>George</td>
+ <td>$64.14</td>
+
+ <td>2008-01-02</td>
+ </tr>
+ <tr>
+ <td>291</td>
+ <td>267.3</td>
+ <td>John</td>
+ <td>$67.84</td>
+
+ <td>2009-06-21</td>
+ </tr>
+ <tr>
+ <td>292</td>
+ <td>273.9</td>
+ <td>Phil</td>
+ <td>$19.04</td>
+
+ <td>2009-01-29</td>
+ </tr>
+ <tr>
+ <td>293</td>
+ <td>614.3</td>
+ <td>Jack</td>
+ <td>$25.44</td>
+
+ <td>2008-05-29</td>
+ </tr>
+ <tr>
+ <td>294</td>
+ <td>40</td>
+ <td>Paul</td>
+ <td>$19.94</td>
+
+ <td>2011-02-04</td>
+ </tr>
+ <tr>
+ <td>295</td>
+ <td>908.8</td>
+ <td>Rob</td>
+ <td>$63.54</td>
+
+ <td>2009-09-17</td>
+ </tr>
+ <tr>
+ <td>296</td>
+ <td>903.1</td>
+ <td>Walt</td>
+ <td>$30.84</td>
+
+ <td>2009-06-17</td>
+ </tr>
+ <tr>
+ <td>297</td>
+ <td>221.2</td>
+ <td>Nathan</td>
+ <td>$70.04</td>
+
+ <td>2011-01-09</td>
+ </tr>
+ <tr>
+ <td>298</td>
+ <td>662.1</td>
+ <td>Dan</td>
+ <td>$14.74</td>
+
+ <td>2009-01-23</td>
+ </tr>
+ <tr>
+ <td>299</td>
+ <td>103.2</td>
+ <td>Jeff</td>
+ <td>$47.94</td>
+
+ <td>2009-07-03</td>
+ </tr>
+ <tr>
+ <td>300</td>
+ <td>46.2</td>
+ <td>Bill</td>
+ <td>$15.24</td>
+
+ <td>2008-05-13</td>
+ </tr>
+ <tr>
+ <td>301</td>
+ <td>58.3</td>
+ <td>Joe</td>
+ <td>$41.94</td>
+
+ <td>2010-07-06</td>
+ </tr>
+ <tr>
+ <td>302</td>
+ <td>533</td>
+ <td>Bob</td>
+ <td>$69.34</td>
+
+ <td>2011-02-10</td>
+ </tr>
+ <tr>
+ <td>303</td>
+ <td>884.6</td>
+ <td>Matt</td>
+ <td>$30.74</td>
+
+ <td>2008-09-30</td>
+ </tr>
+ <tr>
+ <td>304</td>
+ <td>24.5</td>
+ <td>Mark</td>
+ <td>$34.74</td>
+
+ <td>2009-05-18</td>
+ </tr>
+ <tr>
+ <td>305</td>
+ <td>11.7</td>
+ <td>Tom</td>
+ <td>$25.64</td>
+
+ <td>2008-03-22</td>
+ </tr>
+ <tr>
+ <td>306</td>
+ <td>563</td>
+ <td>Jake</td>
+ <td>$15.94</td>
+
+ <td>2009-03-12</td>
+ </tr>
+ <tr>
+ <td>307</td>
+ <td>34.1</td>
+ <td>Greg</td>
+ <td>$38.04</td>
+
+ <td>2008-03-30</td>
+ </tr>
+ <tr>
+ <td>308</td>
+ <td>998.8</td>
+ <td>Adam</td>
+ <td>$4.23</td>
+
+ <td>2008-09-16</td>
+ </tr>
+ <tr>
+ <td>309</td>
+ <td>344.7</td>
+ <td>Steve</td>
+ <td>$14.54</td>
+
+ <td>2010-03-25</td>
+ </tr>
+ <tr>
+ <td>310</td>
+ <td>829.5</td>
+ <td>George</td>
+ <td>$19.14</td>
+
+ <td>2010-09-16</td>
+ </tr>
+ <tr>
+ <td>311</td>
+ <td>955</td>
+ <td>John</td>
+ <td>$24.94</td>
+
+ <td>2008-11-12</td>
+ </tr>
+ <tr>
+ <td>312</td>
+ <td>758</td>
+ <td>Phil</td>
+ <td>$78.34</td>
+
+ <td>2011-01-23</td>
+ </tr>
+ <tr>
+ <td>313</td>
+ <td>750.8</td>
+ <td>Jack</td>
+ <td>$66.74</td>
+
+ <td>2008-11-11</td>
+ </tr>
+ <tr>
+ <td>314</td>
+ <td>997.8</td>
+ <td>Paul</td>
+ <td>$69.14</td>
+
+ <td>2009-12-18</td>
+ </tr>
+ <tr>
+ <td>315</td>
+ <td>443.5</td>
+ <td>Rob</td>
+ <td>$70.34</td>
+
+ <td>2010-10-10</td>
+ </tr>
+ <tr>
+ <td>316</td>
+ <td>524</td>
+ <td>Walt</td>
+ <td>$26.64</td>
+
+ <td>2008-02-09</td>
+ </tr>
+ <tr>
+ <td>317</td>
+ <td>912</td>
+ <td>Nathan</td>
+ <td>$30.04</td>
+
+ <td>2009-04-24</td>
+ </tr>
+ <tr>
+ <td>318</td>
+ <td>1000</td>
+ <td>Dan</td>
+ <td>$29.94</td>
+
+ <td>2009-06-11</td>
+ </tr>
+ <tr>
+ <td>319</td>
+ <td>234.5</td>
+ <td>Jeff</td>
+ <td>$64.34</td>
+
+ <td>2009-11-26</td>
+ </tr>
+ <tr>
+ <td>320</td>
+ <td>948.4</td>
+ <td>Bill</td>
+ <td>$47.34</td>
+
+ <td>2010-07-05</td>
+ </tr>
+ <tr>
+ <td>321</td>
+ <td>813.7</td>
+ <td>Joe</td>
+ <td>$42.84</td>
+
+ <td>2008-02-18</td>
+ </tr>
+ <tr>
+ <td>322</td>
+ <td>97.7</td>
+ <td>Bob</td>
+ <td>$18.64</td>
+
+ <td>2010-08-11</td>
+ </tr>
+ <tr>
+ <td>323</td>
+ <td>74.3</td>
+ <td>Matt</td>
+ <td>$93.74</td>
+
+ <td>2009-07-22</td>
+ </tr>
+ <tr>
+ <td>324</td>
+ <td>357.7</td>
+ <td>Mark</td>
+ <td>$93.44</td>
+
+ <td>2008-07-29</td>
+ </tr>
+ <tr>
+ <td>325</td>
+ <td>988</td>
+ <td>Tom</td>
+ <td>$37.84</td>
+
+ <td>2010-10-21</td>
+ </tr>
+ <tr>
+ <td>326</td>
+ <td>873.8</td>
+ <td>Jake</td>
+ <td>$90.24</td>
+
+ <td>2008-06-24</td>
+ </tr>
+ <tr>
+ <td>327</td>
+ <td>918.3</td>
+ <td>Greg</td>
+ <td>$81.44</td>
+
+ <td>2009-06-06</td>
+ </tr>
+ <tr>
+ <td>328</td>
+ <td>342.7</td>
+ <td>Adam</td>
+ <td>$81.44</td>
+
+ <td>2010-05-18</td>
+ </tr>
+ <tr>
+ <td>329</td>
+ <td>809</td>
+ <td>Steve</td>
+ <td>$4.83</td>
+
+ <td>2009-03-31</td>
+ </tr>
+ <tr>
+ <td>330</td>
+ <td>420.4</td>
+ <td>George</td>
+ <td>$99.74</td>
+
+ <td>2010-09-30</td>
+ </tr>
+ <tr>
+ <td>331</td>
+ <td>223</td>
+ <td>John</td>
+ <td>$81.04</td>
+
+ <td>2008-12-06</td>
+ </tr>
+ <tr>
+ <td>332</td>
+ <td>275</td>
+ <td>Phil</td>
+ <td>$90.84</td>
+
+ <td>2009-07-09</td>
+ </tr>
+ <tr>
+ <td>333</td>
+ <td>109.5</td>
+ <td>Jack</td>
+ <td>$98.24</td>
+
+ <td>2009-04-27</td>
+ </tr>
+ <tr>
+ <td>334</td>
+ <td>610.9</td>
+ <td>Paul</td>
+ <td>$34.04</td>
+
+ <td>2009-02-10</td>
+ </tr>
+ <tr>
+ <td>335</td>
+ <td>803.7</td>
+ <td>Rob</td>
+ <td>$32.84</td>
+
+ <td>2010-04-23</td>
+ </tr>
+ <tr>
+ <td>336</td>
+ <td>699.6</td>
+ <td>Walt</td>
+ <td>$20.14</td>
+
+ <td>2009-12-30</td>
+ </tr>
+ <tr>
+ <td>337</td>
+ <td>861.4</td>
+ <td>Nathan</td>
+ <td>$12.04</td>
+
+ <td>2009-05-28</td>
+ </tr>
+ <tr>
+ <td>338</td>
+ <td>323.4</td>
+ <td>Dan</td>
+ <td>$46.24</td>
+
+ <td>2008-10-25</td>
+ </tr>
+ <tr>
+ <td>339</td>
+ <td>84.3</td>
+ <td>Jeff</td>
+ <td>$27.14</td>
+
+ <td>2008-12-19</td>
+ </tr>
+ <tr>
+ <td>340</td>
+ <td>488.6</td>
+ <td>Bill</td>
+ <td>$69.24</td>
+
+ <td>2008-12-15</td>
+ </tr>
+ <tr>
+ <td>341</td>
+ <td>365.7</td>
+ <td>Joe</td>
+ <td>$91.54</td>
+
+ <td>2008-05-10</td>
+ </tr>
+ <tr>
+ <td>342</td>
+ <td>670.8</td>
+ <td>Bob</td>
+ <td>$19.04</td>
+
+ <td>2008-01-24</td>
+ </tr>
+ <tr>
+ <td>343</td>
+ <td>161.5</td>
+ <td>Matt</td>
+ <td>$29.94</td>
+
+ <td>2008-01-03</td>
+ </tr>
+ <tr>
+ <td>344</td>
+ <td>588.8</td>
+ <td>Mark</td>
+ <td>$91.04</td>
+
+ <td>2009-01-30</td>
+ </tr>
+ <tr>
+ <td>345</td>
+ <td>950.3</td>
+ <td>Tom</td>
+ <td>$71.44</td>
+
+ <td>2010-02-13</td>
+ </tr>
+ <tr>
+ <td>346</td>
+ <td>689.5</td>
+ <td>Jake</td>
+ <td>$41.34</td>
+
+ <td>2010-10-04</td>
+ </tr>
+ <tr>
+ <td>347</td>
+ <td>330.4</td>
+ <td>Greg</td>
+ <td>$27.44</td>
+
+ <td>2007-12-20</td>
+ </tr>
+ <tr>
+ <td>348</td>
+ <td>785</td>
+ <td>Adam</td>
+ <td>$59.84</td>
+
+ <td>2009-06-07</td>
+ </tr>
+ <tr>
+ <td>349</td>
+ <td>53.2</td>
+ <td>Steve</td>
+ <td>$68.24</td>
+
+ <td>2010-04-17</td>
+ </tr>
+ <tr>
+ <td>350</td>
+ <td>369.6</td>
+ <td>George</td>
+ <td>$17.14</td>
+
+ <td>2009-04-25</td>
+ </tr>
+ <tr>
+ <td>351</td>
+ <td>682.4</td>
+ <td>John</td>
+ <td>$53.64</td>
+
+ <td>2009-01-17</td>
+ </tr>
+ <tr>
+ <td>352</td>
+ <td>805.3</td>
+ <td>Phil</td>
+ <td>$20.74</td>
+
+ <td>2009-08-24</td>
+ </tr>
+ <tr>
+ <td>353</td>
+ <td>836</td>
+ <td>Jack</td>
+ <td>$36.94</td>
+
+ <td>2010-08-05</td>
+ </tr>
+ <tr>
+ <td>354</td>
+ <td>848.6</td>
+ <td>Paul</td>
+ <td>$95.74</td>
+
+ <td>2010-04-23</td>
+ </tr>
+ <tr>
+ <td>355</td>
+ <td>201</td>
+ <td>Rob</td>
+ <td>$90.74</td>
+
+ <td>2009-05-26</td>
+ </tr>
+ <tr>
+ <td>356</td>
+ <td>880.9</td>
+ <td>Walt</td>
+ <td>$59.74</td>
+
+ <td>2010-09-16</td>
+ </tr>
+ <tr>
+ <td>357</td>
+ <td>762.2</td>
+ <td>Nathan</td>
+ <td>$92.74</td>
+
+ <td>2008-05-29</td>
+ </tr>
+ <tr>
+ <td>358</td>
+ <td>763.1</td>
+ <td>Dan</td>
+ <td>$71.24</td>
+
+ <td>2010-04-21</td>
+ </tr>
+ <tr>
+ <td>359</td>
+ <td>226.4</td>
+ <td>Jeff</td>
+ <td>$76.54</td>
+
+ <td>2009-04-18</td>
+ </tr>
+ <tr>
+ <td>360</td>
+ <td>960.8</td>
+ <td>Bill</td>
+ <td>$13.54</td>
+
+ <td>2009-11-02</td>
+ </tr>
+ <tr>
+ <td>361</td>
+ <td>386.9</td>
+ <td>Joe</td>
+ <td>$81.74</td>
+
+ <td>2008-05-14</td>
+ </tr>
+ <tr>
+ <td>362</td>
+ <td>727.6</td>
+ <td>Bob</td>
+ <td>$62.34</td>
+
+ <td>2009-01-08</td>
+ </tr>
+ <tr>
+ <td>363</td>
+ <td>257.8</td>
+ <td>Matt</td>
+ <td>$45.94</td>
+
+ <td>2010-03-11</td>
+ </tr>
+ <tr>
+ <td>364</td>
+ <td>87</td>
+ <td>Mark</td>
+ <td>$30.74</td>
+
+ <td>2010-01-20</td>
+ </tr>
+ <tr>
+ <td>365</td>
+ <td>826</td>
+ <td>Tom</td>
+ <td>$50.84</td>
+
+ <td>2009-10-05</td>
+ </tr>
+ <tr>
+ <td>366</td>
+ <td>278.6</td>
+ <td>Jake</td>
+ <td>$38.94</td>
+
+ <td>2008-06-25</td>
+ </tr>
+ <tr>
+ <td>367</td>
+ <td>144.2</td>
+ <td>Greg</td>
+ <td>$15.14</td>
+
+ <td>2008-04-02</td>
+ </tr>
+ <tr>
+ <td>368</td>
+ <td>284.2</td>
+ <td>Adam</td>
+ <td>$91.44</td>
+
+ <td>2010-07-05</td>
+ </tr>
+ <tr>
+ <td>369</td>
+ <td>22</td>
+ <td>Steve</td>
+ <td>$14.14</td>
+
+ <td>2009-10-07</td>
+ </tr>
+ <tr>
+ <td>370</td>
+ <td>441.8</td>
+ <td>George</td>
+ <td>$10.14</td>
+
+ <td>2010-03-12</td>
+ </tr>
+ <tr>
+ <td>371</td>
+ <td>32.2</td>
+ <td>John</td>
+ <td>$48.84</td>
+
+ <td>2009-08-13</td>
+ </tr>
+ <tr>
+ <td>372</td>
+ <td>158.8</td>
+ <td>Phil</td>
+ <td>$21.64</td>
+
+ <td>2008-06-02</td>
+ </tr>
+ <tr>
+ <td>373</td>
+ <td>492.4</td>
+ <td>Jack</td>
+ <td>$47.34</td>
+
+ <td>2009-11-14</td>
+ </tr>
+ <tr>
+ <td>374</td>
+ <td>194.4</td>
+ <td>Paul</td>
+ <td>$56.04</td>
+
+ <td>2010-11-05</td>
+ </tr>
+ <tr>
+ <td>375</td>
+ <td>853.5</td>
+ <td>Rob</td>
+ <td>$38.64</td>
+
+ <td>2009-04-14</td>
+ </tr>
+ <tr>
+ <td>376</td>
+ <td>420</td>
+ <td>Walt</td>
+ <td>$66.54</td>
+
+ <td>2010-07-09</td>
+ </tr>
+ <tr>
+ <td>377</td>
+ <td>583.4</td>
+ <td>Nathan</td>
+ <td>$80.94</td>
+
+ <td>2010-12-30</td>
+ </tr>
+ <tr>
+ <td>378</td>
+ <td>674</td>
+ <td>Dan</td>
+ <td>$9.33</td>
+
+ <td>2010-09-22</td>
+ </tr>
+ <tr>
+ <td>379</td>
+ <td>476.8</td>
+ <td>Jeff</td>
+ <td>$11.54</td>
+
+ <td>2008-01-01</td>
+ </tr>
+ <tr>
+ <td>380</td>
+ <td>44.9</td>
+ <td>Bill</td>
+ <td>$55.74</td>
+
+ <td>2008-04-27</td>
+ </tr>
+ <tr>
+ <td>381</td>
+ <td>748</td>
+ <td>Joe</td>
+ <td>$58.94</td>
+
+ <td>2009-11-13</td>
+ </tr>
+ <tr>
+ <td>382</td>
+ <td>268.4</td>
+ <td>Bob</td>
+ <td>$74.84</td>
+
+ <td>2010-07-21</td>
+ </tr>
+ <tr>
+ <td>383</td>
+ <td>411.3</td>
+ <td>Matt</td>
+ <td>$24.04</td>
+
+ <td>2008-11-18</td>
+ </tr>
+ <tr>
+ <td>384</td>
+ <td>12.8</td>
+ <td>Mark</td>
+ <td>$43.44</td>
+
+ <td>2010-08-29</td>
+ </tr>
+ <tr>
+ <td>385</td>
+ <td>921.3</td>
+ <td>Tom</td>
+ <td>$28.84</td>
+
+ <td>2008-09-18</td>
+ </tr>
+ <tr>
+ <td>386</td>
+ <td>337.8</td>
+ <td>Jake</td>
+ <td>$70.84</td>
+
+ <td>2010-10-27</td>
+ </tr>
+ <tr>
+ <td>387</td>
+ <td>143.3</td>
+ <td>Greg</td>
+ <td>$29.14</td>
+
+ <td>2010-03-20</td>
+ </tr>
+ <tr>
+ <td>388</td>
+ <td>99.8</td>
+ <td>Adam</td>
+ <td>$96.54</td>
+
+ <td>2010-07-06</td>
+ </tr>
+ <tr>
+ <td>389</td>
+ <td>970.4</td>
+ <td>Steve</td>
+ <td>$44.24</td>
+
+ <td>2010-11-16</td>
+ </tr>
+ <tr>
+ <td>390</td>
+ <td>981.5</td>
+ <td>George</td>
+ <td>$48.74</td>
+
+ <td>2009-06-21</td>
+ </tr>
+ <tr>
+ <td>391</td>
+ <td>93.8</td>
+ <td>John</td>
+ <td>$23.44</td>
+
+ <td>2008-03-02</td>
+ </tr>
+ <tr>
+ <td>392</td>
+ <td>694.2</td>
+ <td>Phil</td>
+ <td>$50.34</td>
+
+ <td>2010-07-16</td>
+ </tr>
+ <tr>
+ <td>393</td>
+ <td>510.3</td>
+ <td>Jack</td>
+ <td>$91.44</td>
+
+ <td>2008-02-17</td>
+ </tr>
+ <tr>
+ <td>394</td>
+ <td>799.7</td>
+ <td>Paul</td>
+ <td>$92.74</td>
+
+ <td>2009-07-04</td>
+ </tr>
+ <tr>
+ <td>395</td>
+ <td>649.5</td>
+ <td>Rob</td>
+ <td>$84.84</td>
+
+ <td>2010-06-02</td>
+ </tr>
+ <tr>
+ <td>396</td>
+ <td>885.6</td>
+ <td>Walt</td>
+ <td>$18.64</td>
+
+ <td>2009-06-28</td>
+ </tr>
+ <tr>
+ <td>397</td>
+ <td>786.6</td>
+ <td>Nathan</td>
+ <td>$32.94</td>
+
+ <td>2010-05-31</td>
+ </tr>
+ <tr>
+ <td>398</td>
+ <td>496.7</td>
+ <td>Dan</td>
+ <td>$42.94</td>
+
+ <td>2010-04-21</td>
+ </tr>
+ <tr>
+ <td>399</td>
+ <td>299.9</td>
+ <td>Jeff</td>
+ <td>$39.94</td>
+
+ <td>2008-07-13</td>
+ </tr>
+ <tr>
+ <td>400</td>
+ <td>218.1</td>
+ <td>Bill</td>
+ <td>$38.14</td>
+
+ <td>2010-01-27</td>
+ </tr>
+ <tr>
+ <td>401</td>
+ <td>693.2</td>
+ <td>Joe</td>
+ <td>$47.44</td>
+
+ <td>2010-10-26</td>
+ </tr>
+ <tr>
+ <td>402</td>
+ <td>757.2</td>
+ <td>Bob</td>
+ <td>$16.94</td>
+
+ <td>2009-03-29</td>
+ </tr>
+ <tr>
+ <td>403</td>
+ <td>568.9</td>
+ <td>Matt</td>
+ <td>$67.94</td>
+
+ <td>2008-12-20</td>
+ </tr>
+ <tr>
+ <td>404</td>
+ <td>620.5</td>
+ <td>Mark</td>
+ <td>$47.84</td>
+
+ <td>2008-09-26</td>
+ </tr>
+ <tr>
+ <td>405</td>
+ <td>106.4</td>
+ <td>Tom</td>
+ <td>$12.84</td>
+
+ <td>2008-04-04</td>
+ </tr>
+ <tr>
+ <td>406</td>
+ <td>880.1</td>
+ <td>Jake</td>
+ <td>$1.33</td>
+
+ <td>2008-11-05</td>
+ </tr>
+ <tr>
+ <td>407</td>
+ <td>361.5</td>
+ <td>Greg</td>
+ <td>$80.04</td>
+
+ <td>2009-11-20</td>
+ </tr>
+ <tr>
+ <td>408</td>
+ <td>133.8</td>
+ <td>Adam</td>
+ <td>$29.74</td>
+
+ <td>2008-01-29</td>
+ </tr>
+ <tr>
+ <td>409</td>
+ <td>871.1</td>
+ <td>Steve</td>
+ <td>$59.64</td>
+
+ <td>2009-05-05</td>
+ </tr>
+ <tr>
+ <td>410</td>
+ <td>50</td>
+ <td>George</td>
+ <td>$81.54</td>
+
+ <td>2010-07-20</td>
+ </tr>
+ <tr>
+ <td>411</td>
+ <td>715.4</td>
+ <td>John</td>
+ <td>$50.84</td>
+
+ <td>2008-11-18</td>
+ </tr>
+ <tr>
+ <td>412</td>
+ <td>615.3</td>
+ <td>Phil</td>
+ <td>$26.54</td>
+
+ <td>2009-06-01</td>
+ </tr>
+ <tr>
+ <td>413</td>
+ <td>18.1</td>
+ <td>Jack</td>
+ <td>$83.44</td>
+
+ <td>2008-05-25</td>
+ </tr>
+ <tr>
+ <td>414</td>
+ <td>335</td>
+ <td>Paul</td>
+ <td>$45.44</td>
+
+ <td>2009-11-30</td>
+ </tr>
+ <tr>
+ <td>415</td>
+ <td>578.7</td>
+ <td>Rob</td>
+ <td>$56.04</td>
+
+ <td>2010-04-27</td>
+ </tr>
+ <tr>
+ <td>416</td>
+ <td>670.5</td>
+ <td>Walt</td>
+ <td>$44.04</td>
+
+ <td>2010-05-12</td>
+ </tr>
+ <tr>
+ <td>417</td>
+ <td>948.2</td>
+ <td>Nathan</td>
+ <td>$80.24</td>
+
+ <td>2009-09-23</td>
+ </tr>
+ <tr>
+ <td>418</td>
+ <td>554.8</td>
+ <td>Dan</td>
+ <td>$93.64</td>
+
+ <td>2010-09-01</td>
+ </tr>
+ <tr>
+ <td>419</td>
+ <td>590.3</td>
+ <td>Jeff</td>
+ <td>$80.74</td>
+
+ <td>2009-05-22</td>
+ </tr>
+ <tr>
+ <td>420</td>
+ <td>24.8</td>
+ <td>Bill</td>
+ <td>$85.74</td>
+
+ <td>2008-10-19</td>
+ </tr>
+ <tr>
+ <td>421</td>
+ <td>839.9</td>
+ <td>Joe</td>
+ <td>$57.24</td>
+
+ <td>2010-05-29</td>
+ </tr>
+ <tr>
+ <td>422</td>
+ <td>129.3</td>
+ <td>Bob</td>
+ <td>$18.74</td>
+
+ <td>2008-01-29</td>
+ </tr>
+ <tr>
+ <td>423</td>
+ <td>587.2</td>
+ <td>Matt</td>
+ <td>$20.54</td>
+
+ <td>2010-09-20</td>
+ </tr>
+ <tr>
+ <td>424</td>
+ <td>723.7</td>
+ <td>Mark</td>
+ <td>$54.04</td>
+
+ <td>2008-12-27</td>
+ </tr>
+ <tr>
+ <td>425</td>
+ <td>338.5</td>
+ <td>Tom</td>
+ <td>$11.94</td>
+
+ <td>2010-10-07</td>
+ </tr>
+ <tr>
+ <td>426</td>
+ <td>81</td>
+ <td>Jake</td>
+ <td>$78.94</td>
+
+ <td>2008-12-28</td>
+ </tr>
+ <tr>
+ <td>427</td>
+ <td>836.9</td>
+ <td>Greg</td>
+ <td>$73.84</td>
+
+ <td>2008-05-13</td>
+ </tr>
+ <tr>
+ <td>428</td>
+ <td>392.7</td>
+ <td>Adam</td>
+ <td>$29.24</td>
+
+ <td>2008-02-29</td>
+ </tr>
+ <tr>
+ <td>429</td>
+ <td>245</td>
+ <td>Steve</td>
+ <td>$88.34</td>
+
+ <td>2010-09-19</td>
+ </tr>
+ <tr>
+ <td>430</td>
+ <td>693.7</td>
+ <td>George</td>
+ <td>$90.74</td>
+
+ <td>2010-04-06</td>
+ </tr>
+ <tr>
+ <td>431</td>
+ <td>956.8</td>
+ <td>John</td>
+ <td>$74.74</td>
+
+ <td>2008-11-27</td>
+ </tr>
+ <tr>
+ <td>432</td>
+ <td>727.5</td>
+ <td>Phil</td>
+ <td>$87.74</td>
+
+ <td>2009-07-02</td>
+ </tr>
+ <tr>
+ <td>433</td>
+ <td>763</td>
+ <td>Jack</td>
+ <td>$46.44</td>
+
+ <td>2010-02-24</td>
+ </tr>
+ <tr>
+ <td>434</td>
+ <td>632</td>
+ <td>Paul</td>
+ <td>$18.74</td>
+
+ <td>2008-09-10</td>
+ </tr>
+ <tr>
+ <td>435</td>
+ <td>955.1</td>
+ <td>Rob</td>
+ <td>$52.64</td>
+
+ <td>2009-01-26</td>
+ </tr>
+ <tr>
+ <td>436</td>
+ <td>838.7</td>
+ <td>Walt</td>
+ <td>$60.74</td>
+
+ <td>2008-05-27</td>
+ </tr>
+ <tr>
+ <td>437</td>
+ <td>162.7</td>
+ <td>Nathan</td>
+ <td>$44.44</td>
+
+ <td>2010-09-27</td>
+ </tr>
+ <tr>
+ <td>438</td>
+ <td>288.6</td>
+ <td>Dan</td>
+ <td>$83.64</td>
+
+ <td>2008-06-30</td>
+ </tr>
+ <tr>
+ <td>439</td>
+ <td>350.1</td>
+ <td>Jeff</td>
+ <td>$8.13</td>
+
+ <td>2008-02-15</td>
+ </tr>
+ <tr>
+ <td>440</td>
+ <td>218.4</td>
+ <td>Bill</td>
+ <td>$77.54</td>
+
+ <td>2010-12-31</td>
+ </tr>
+ <tr>
+ <td>441</td>
+ <td>943.2</td>
+ <td>Joe</td>
+ <td>$73.14</td>
+
+ <td>2010-03-14</td>
+ </tr>
+ <tr>
+ <td>442</td>
+ <td>240</td>
+ <td>Bob</td>
+ <td>$45.94</td>
+
+ <td>2009-10-22</td>
+ </tr>
+ <tr>
+ <td>443</td>
+ <td>724</td>
+ <td>Matt</td>
+ <td>$22.24</td>
+
+ <td>2008-02-09</td>
+ </tr>
+ <tr>
+ <td>444</td>
+ <td>413.3</td>
+ <td>Mark</td>
+ <td>$85.44</td>
+
+ <td>2008-09-13</td>
+ </tr>
+ <tr>
+ <td>445</td>
+ <td>642.8</td>
+ <td>Tom</td>
+ <td>$80.94</td>
+
+ <td>2010-05-14</td>
+ </tr>
+ <tr>
+ <td>446</td>
+ <td>991.3</td>
+ <td>Jake</td>
+ <td>$64.84</td>
+
+ <td>2009-02-13</td>
+ </tr>
+ <tr>
+ <td>447</td>
+ <td>129.2</td>
+ <td>Greg</td>
+ <td>$81.04</td>
+
+ <td>2010-07-11</td>
+ </tr>
+ <tr>
+ <td>448</td>
+ <td>4.6</td>
+ <td>Adam</td>
+ <td>$9.93</td>
+
+ <td>2010-01-02</td>
+ </tr>
+ <tr>
+ <td>449</td>
+ <td>172.2</td>
+ <td>Steve</td>
+ <td>$44.94</td>
+
+ <td>2010-04-06</td>
+ </tr>
+ <tr>
+ <td>450</td>
+ <td>222.3</td>
+ <td>George</td>
+ <td>$66.74</td>
+
+ <td>2009-07-19</td>
+ </tr>
+ <tr>
+ <td>451</td>
+ <td>179.7</td>
+ <td>John</td>
+ <td>$61.04</td>
+
+ <td>2008-09-11</td>
+ </tr>
+ <tr>
+ <td>452</td>
+ <td>884.3</td>
+ <td>Phil</td>
+ <td>$85.04</td>
+
+ <td>2010-02-24</td>
+ </tr>
+ <tr>
+ <td>453</td>
+ <td>465.3</td>
+ <td>Jack</td>
+ <td>$57.44</td>
+
+ <td>2010-11-08</td>
+ </tr>
+ <tr>
+ <td>454</td>
+ <td>510</td>
+ <td>Paul</td>
+ <td>$98.74</td>
+
+ <td>2010-05-22</td>
+ </tr>
+ <tr>
+ <td>455</td>
+ <td>741.8</td>
+ <td>Rob</td>
+ <td>$63.04</td>
+
+ <td>2009-10-13</td>
+ </tr>
+ <tr>
+ <td>456</td>
+ <td>499.2</td>
+ <td>Walt</td>
+ <td>$62.14</td>
+
+ <td>2008-08-31</td>
+ </tr>
+ <tr>
+ <td>457</td>
+ <td>863.3</td>
+ <td>Nathan</td>
+ <td>$75.04</td>
+
+ <td>2008-01-24</td>
+ </tr>
+ <tr>
+ <td>458</td>
+ <td>670.7</td>
+ <td>Dan</td>
+ <td>$75.54</td>
+
+ <td>2008-05-17</td>
+ </tr>
+ <tr>
+ <td>459</td>
+ <td>314.2</td>
+ <td>Jeff</td>
+ <td>$92.74</td>
+
+ <td>2009-10-19</td>
+ </tr>
+ <tr>
+ <td>460</td>
+ <td>38.7</td>
+ <td>Bill</td>
+ <td>$14.94</td>
+
+ <td>2008-09-28</td>
+ </tr>
+ <tr>
+ <td>461</td>
+ <td>537.8</td>
+ <td>Joe</td>
+ <td>$32.94</td>
+
+ <td>2010-09-05</td>
+ </tr>
+ <tr>
+ <td>462</td>
+ <td>768.2</td>
+ <td>Bob</td>
+ <td>$21.34</td>
+
+ <td>2010-03-15</td>
+ </tr>
+ <tr>
+ <td>463</td>
+ <td>457.5</td>
+ <td>Matt</td>
+ <td>$67.94</td>
+
+ <td>2008-11-07</td>
+ </tr>
+ <tr>
+ <td>464</td>
+ <td>368.5</td>
+ <td>Mark</td>
+ <td>$18.94</td>
+
+ <td>2008-10-23</td>
+ </tr>
+ <tr>
+ <td>465</td>
+ <td>133.3</td>
+ <td>Tom</td>
+ <td>$93.04</td>
+
+ <td>2010-10-22</td>
+ </tr>
+ <tr>
+ <td>466</td>
+ <td>706.9</td>
+ <td>Jake</td>
+ <td>$43.04</td>
+
+ <td>2009-08-10</td>
+ </tr>
+ <tr>
+ <td>467</td>
+ <td>927.9</td>
+ <td>Greg</td>
+ <td>$29.34</td>
+
+ <td>2008-10-25</td>
+ </tr>
+ <tr>
+ <td>468</td>
+ <td>959.1</td>
+ <td>Adam</td>
+ <td>$96.34</td>
+
+ <td>2008-01-16</td>
+ </tr>
+ <tr>
+ <td>469</td>
+ <td>88.8</td>
+ <td>Steve</td>
+ <td>$27.84</td>
+
+ <td>2010-12-24</td>
+ </tr>
+ <tr>
+ <td>470</td>
+ <td>667.2</td>
+ <td>George</td>
+ <td>$31.64</td>
+
+ <td>2008-04-13</td>
+ </tr>
+ <tr>
+ <td>471</td>
+ <td>912.6</td>
+ <td>John</td>
+ <td>$85.44</td>
+
+ <td>2009-04-29</td>
+ </tr>
+ <tr>
+ <td>472</td>
+ <td>768.1</td>
+ <td>Phil</td>
+ <td>$62.24</td>
+
+ <td>2010-01-01</td>
+ </tr>
+ <tr>
+ <td>473</td>
+ <td>473.8</td>
+ <td>Jack</td>
+ <td>$8.03</td>
+
+ <td>2008-12-25</td>
+ </tr>
+ <tr>
+ <td>474</td>
+ <td>753.4</td>
+ <td>Paul</td>
+ <td>$44.84</td>
+
+ <td>2009-07-31</td>
+ </tr>
+ <tr>
+ <td>475</td>
+ <td>20.3</td>
+ <td>Rob</td>
+ <td>$58.14</td>
+
+ <td>2009-05-11</td>
+ </tr>
+ <tr>
+ <td>476</td>
+ <td>917.3</td>
+ <td>Walt</td>
+ <td>$28.84</td>
+
+ <td>2010-09-20</td>
+ </tr>
+ <tr>
+ <td>477</td>
+ <td>435.6</td>
+ <td>Nathan</td>
+ <td>$21.64</td>
+
+ <td>2008-06-24</td>
+ </tr>
+ <tr>
+ <td>478</td>
+ <td>704.3</td>
+ <td>Dan</td>
+ <td>$17.54</td>
+
+ <td>2008-05-12</td>
+ </tr>
+ <tr>
+ <td>479</td>
+ <td>728.1</td>
+ <td>Jeff</td>
+ <td>$26.44</td>
+
+ <td>2009-03-29</td>
+ </tr>
+ <tr>
+ <td>480</td>
+ <td>678.9</td>
+ <td>Bill</td>
+ <td>$93.14</td>
+
+ <td>2010-03-30</td>
+ </tr>
+ <tr>
+ <td>481</td>
+ <td>779.1</td>
+ <td>Joe</td>
+ <td>$84.34</td>
+
+ <td>2009-10-12</td>
+ </tr>
+ <tr>
+ <td>482</td>
+ <td>208.3</td>
+ <td>Bob</td>
+ <td>$61.14</td>
+
+ <td>2008-07-31</td>
+ </tr>
+ <tr>
+ <td>483</td>
+ <td>850.8</td>
+ <td>Matt</td>
+ <td>$8.53</td>
+
+ <td>2008-10-31</td>
+ </tr>
+ <tr>
+ <td>484</td>
+ <td>171.8</td>
+ <td>Mark</td>
+ <td>$83.84</td>
+
+ <td>2010-04-03</td>
+ </tr>
+ <tr>
+ <td>485</td>
+ <td>681.4</td>
+ <td>Tom</td>
+ <td>$85.94</td>
+
+ <td>2008-12-04</td>
+ </tr>
+ <tr>
+ <td>486</td>
+ <td>121.1</td>
+ <td>Jake</td>
+ <td>$77.64</td>
+
+ <td>2009-11-02</td>
+ </tr>
+ <tr>
+ <td>487</td>
+ <td>990.2</td>
+ <td>Greg</td>
+ <td>$21.14</td>
+
+ <td>2010-07-10</td>
+ </tr>
+ <tr>
+ <td>488</td>
+ <td>152</td>
+ <td>Adam</td>
+ <td>$91.64</td>
+
+ <td>2011-01-28</td>
+ </tr>
+ <tr>
+ <td>489</td>
+ <td>277</td>
+ <td>Steve</td>
+ <td>$64.44</td>
+
+ <td>2008-09-28</td>
+ </tr>
+ <tr>
+ <td>490</td>
+ <td>679.5</td>
+ <td>George</td>
+ <td>$32.34</td>
+
+ <td>2008-07-10</td>
+ </tr>
+ <tr>
+ <td>491</td>
+ <td>398</td>
+ <td>John</td>
+ <td>$10.24</td>
+
+ <td>2008-01-10</td>
+ </tr>
+ <tr>
+ <td>492</td>
+ <td>970.4</td>
+ <td>Phil</td>
+ <td>$31.04</td>
+
+ <td>2009-12-18</td>
+ </tr>
+ <tr>
+ <td>493</td>
+ <td>164.7</td>
+ <td>Jack</td>
+ <td>$16.14</td>
+
+ <td>2010-03-26</td>
+ </tr>
+ <tr>
+ <td>494</td>
+ <td>438.5</td>
+ <td>Paul</td>
+ <td>$33.24</td>
+
+ <td>2009-09-20</td>
+ </tr>
+ <tr>
+ <td>495</td>
+ <td>160.2</td>
+ <td>Rob</td>
+ <td>$1.43</td>
+
+ <td>2009-04-10</td>
+ </tr>
+ <tr>
+ <td>496</td>
+ <td>463</td>
+ <td>Walt</td>
+ <td>$13.54</td>
+
+ <td>2008-07-24</td>
+ </tr>
+ <tr>
+ <td>497</td>
+ <td>53.9</td>
+ <td>Nathan</td>
+ <td>$12.54</td>
+
+ <td>2009-03-26</td>
+ </tr>
+ <tr>
+ <td>498</td>
+ <td>860.6</td>
+ <td>Dan</td>
+ <td>$27.74</td>
+
+ <td>2008-12-18</td>
+ </tr>
+ <tr>
+ <td>499</td>
+ <td>842.2</td>
+ <td>Jeff</td>
+ <td>$55.44</td>
+
+ <td>2011-01-02</td>
+ </tr>
+ </tbody>
+ </table>
+ </body>
+</html>
diff --git a/js/dojo/dojox/dtl/demos/demo_Templated.html b/js/dojo/dojox/dtl/demos/demo_Templated.html
new file mode 100644
index 0000000..b37af58
--- /dev/null
+++ b/js/dojo/dojox/dtl/demos/demo_Templated.html
@@ -0,0 +1,36 @@
+<html>
+ <head>
+ <title>Demo using dojox.dtl._Templated</title>
+ <script type="text/javascript" src="../../../dojo/dojo.js"
+ djConfig="isDebug: true, parseOnLoad: true"></script>
+ <script type="text/javascript">
+ dojo.require("dijit._WidgetBase");
+ dojo.require("dojox.dtl._Templated");
+
+ dojo.declare("Fruit", [dijit._WidgetBase, dojox.dtl._Templated], {
+ oldRepl: "Fruit: ",
+ _dijitTemplateCompat: true,
+ items: ["apple", "banana", "orange"],
+ keyUp: function(e){
+ if(e.keyCode == dojo.keys.ENTER){
+ var i = dojo.indexOf(this.items, e.target.value);
+ if(i != -1){
+ this.items.splice(i, 1);
+ }else{
+ this.items.push(e.target.value);
+ }
+ e.target.value = "";
+ this.render();
+ dojo.query("input", this.domNode).forEach("item.focus();");
+ }
+ },
+ templateString: '<div><input dojoAttachEvent="onkeyup: keyUp"><ul>{% for item in items %}<li>${oldRepl} {{ item }}</li>{% endfor %}</ul></div>'
+ });
+
+ dojo.require("dojo.parser");
+ </script>
+ </head>
+ <body>
+ <div dojoType="Fruit"></div>
+ </body>
+</html>
diff --git a/js/dojo/dojox/dtl/demos/demo_Templated_amd.html b/js/dojo/dojox/dtl/demos/demo_Templated_amd.html
new file mode 100644
index 0000000..7235aac
--- /dev/null
+++ b/js/dojo/dojox/dtl/demos/demo_Templated_amd.html
@@ -0,0 +1,42 @@
+<html>
+ <head>
+ <title>Demo using dojox.dtl._Templated</title>
+ <script type="text/javascript" src="../../../dojo/dojo.js"
+ data-dojo-config="isDebug: true, parseOnLoad: true, async:true"></script>
+ <script type="text/javascript">
+ require(["dijit/_WidgetBase",
+ "dojox/dtl/_Templated",
+ "dojo/_base/array",
+ "dojo/_base/declare",
+ "dojo/query",
+ "dojo/keys",
+ "dojo/parser",
+ "dojox/dtl/tag/logic"],
+ function(_WidgetBase, _Templated, array, declare, query, keys){
+
+ declare("Fruit", [_WidgetBase, _Templated], {
+ oldRepl: "Fruit: ",
+ _dijitTemplateCompat: true,
+ items: ["apple", "banana", "orange"],
+ keyUp: function(e){
+ if(e.keyCode == keys.ENTER){
+ var i = array.indexOf(this.items, e.target.value);
+ if(i != -1){
+ this.items.splice(i, 1);
+ }else{
+ this.items.push(e.target.value);
+ }
+ e.target.value = "";
+ this.render();
+ query("input", this.domNode).forEach("item.focus();");
+ }
+ },
+ templateString: '<div><input dojoAttachEvent="onkeyup: keyUp"><ul>{% for item in items %}<li>${oldRepl} {{ item }}</li>{% endfor %}</ul></div>'
+ });
+ });
+ </script>
+ </head>
+ <body>
+ <div data-dojo-type="Fruit"></div>
+ </body>
+</html>
diff --git a/js/dojo/dojox/dtl/demos/demo_Tree.html b/js/dojo/dojox/dtl/demos/demo_Tree.html
new file mode 100644
index 0000000..897ce8a
--- /dev/null
+++ b/js/dojo/dojox/dtl/demos/demo_Tree.html
@@ -0,0 +1,48 @@
+<html>
+ <head>
+ <title>Demo to show recursion in DTL</title>
+ <script type="text/javascript" src="../../../dojo/dojo.js"
+ djConfig="isDebug: true, parseOnLoad: true"></script>
+ <script type="text/javascript">
+ dojo.require("dijit._WidgetBase");
+ dojo.require("dojox.dtl._DomTemplated");
+ dojo.require("dojo.data.ItemFileReadStore");
+ dojo.require("dojo.parser");
+
+ (function(){
+ var data = {};
+
+ // The only way to get ItemFileReadStore to work
+ // synchronously (necessary for the bind_query format
+ // we'll be using below) at the time of this writing
+ // was to feed it data
+ dojo.xhrGet({
+ url: dojo.moduleUrl("dijit.tests._data", "countries.json"),
+ handleAs: "json",
+ sync: true,
+ load: function(json){
+ data = json;
+ }
+ });
+
+ dojo.declare("demo.Tree", [dijit._WidgetBase, dojox.dtl._DomTemplated], {
+ constructor: function(){
+ this.disabled = {};
+ },
+ toggle: function(e){
+ var dataid = dojo.attr(e.target, "dataid");
+ this.disabled[dataid] = !this.disabled[dataid];
+ this.render();
+ },
+ store: new dojo.data.ItemFileReadStore({ data: data }),
+ query: { type: "continent" },
+ templateString: '{% load dojox.dtl.contrib.objects %}{% load dojox.dtl.contrib.data %}{% bind_query query to store as countries %}<ul dojoAttachEvent="onclick: toggle">{% for country in countries %}{% include countrychildren %}{% endfor %}</ul>',
+ countrychildren: '<li dataid="{{ country.getIdentity }}">{{ country.type }}: {{ country.name }}{% if country.children %}{% if disabled|key:country.getIdentity %} &crarr;{% else %}<ul>{% for country in country.children %}{% include countrychildren %}{% endfor %}</ul>{% endif %}{% endif %}</li>'
+ });
+ })();
+ </script>
+ </head>
+ <body>
+ <div dojoType="demo.Tree"></div>
+ </body>
+</html>
diff --git a/js/dojo/dojox/dtl/demos/json/blog/get_blog_1.json b/js/dojo/dojox/dtl/demos/json/blog/get_blog_1.json
new file mode 100644
index 0000000..9c7dd9f
--- /dev/null
+++ b/js/dojo/dojox/dtl/demos/json/blog/get_blog_1.json
@@ -0,0 +1 @@
+{"teaser":"I'd be able to write a lot faster.","body":"I think I wouldn't be able to think.","date":1189125242601,"author":"jim"} \ No newline at end of file
diff --git a/js/dojo/dojox/dtl/demos/json/blog/get_blog_3.json b/js/dojo/dojox/dtl/demos/json/blog/get_blog_3.json
new file mode 100644
index 0000000..7c0a937
--- /dev/null
+++ b/js/dojo/dojox/dtl/demos/json/blog/get_blog_3.json
@@ -0,0 +1 @@
+{"teaser":"There was SO much sand","body":"I tried to walk so fast that I wouldn't leave foot prints.","date":1190245842601,"author":"jim"} \ No newline at end of file
diff --git a/js/dojo/dojox/dtl/demos/json/blog/get_blog_list.json b/js/dojo/dojox/dtl/demos/json/blog/get_blog_list.json
new file mode 100644
index 0000000..40f14a7
--- /dev/null
+++ b/js/dojo/dojox/dtl/demos/json/blog/get_blog_list.json
@@ -0,0 +1 @@
+{"blog_list":{"3":{"title":"My Trip to the Beach"},"1":{"title":"If I Were a Robot"}}} \ No newline at end of file
diff --git a/js/dojo/dojox/dtl/demos/json/blog/get_page_about.json b/js/dojo/dojox/dtl/demos/json/blog/get_page_about.json
new file mode 100644
index 0000000..05ddb9c
--- /dev/null
+++ b/js/dojo/dojox/dtl/demos/json/blog/get_page_about.json
@@ -0,0 +1 @@
+{"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>"} \ No newline at end of file
diff --git a/js/dojo/dojox/dtl/demos/json/fruit.json b/js/dojo/dojox/dtl/demos/json/fruit.json
new file mode 100644
index 0000000..e7a0bf8
--- /dev/null
+++ b/js/dojo/dojox/dtl/demos/json/fruit.json
@@ -0,0 +1 @@
+{ items: ["apple", "banana", "pear"] } \ No newline at end of file
diff --git a/js/dojo/dojox/dtl/demos/json/morefruit.json b/js/dojo/dojox/dtl/demos/json/morefruit.json
new file mode 100644
index 0000000..6a8beea
--- /dev/null
+++ b/js/dojo/dojox/dtl/demos/json/morefruit.json
@@ -0,0 +1 @@
+{ items: ["pineapple", "orange", "tomato"] } \ No newline at end of file
diff --git a/js/dojo/dojox/dtl/demos/templates/animation.html b/js/dojo/dojox/dtl/demos/templates/animation.html
new file mode 100644
index 0000000..d37908b
--- /dev/null
+++ b/js/dojo/dojox/dtl/demos/templates/animation.html
@@ -0,0 +1,5 @@
+{% load dojox.dtl.contrib.dijit dojox.dtl.contrib.dom %}
+<div>
+ <div style="top: {{ y }}px; left: {{ x }}px; width: 10px; height: 10px; background: red; position: absolute;">&nbsp;</div>
+ <div dojoAttachPoint="blue" style="top: 10px; left: 0; width: 10px; height: 10px; background: blue; position: absolute;">&nbsp;</div>
+</div> \ No newline at end of file
diff --git a/js/dojo/dojox/dtl/demos/templates/blog_base.html b/js/dojo/dojox/dtl/demos/templates/blog_base.html
new file mode 100644
index 0000000..cc5d150
--- /dev/null
+++ b/js/dojo/dojox/dtl/demos/templates/blog_base.html
@@ -0,0 +1,11 @@
+{% load dojox.dtl.contrib.dom %}
+<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>
+ <!--{% buffer %}-->
+ <!--{% block body %}--><!--{% endblock %}-->
+ <!--{% endbuffer %}-->
+</div> \ No newline at end of file
diff --git a/js/dojo/dojox/dtl/demos/templates/blog_detail.html b/js/dojo/dojox/dtl/demos/templates/blog_detail.html
new file mode 100644
index 0000000..2b6146d
--- /dev/null
+++ b/js/dojo/dojox/dtl/demos/templates/blog_detail.html
@@ -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 %}--> \ No newline at end of file
diff --git a/js/dojo/dojox/dtl/demos/templates/blog_list.html b/js/dojo/dojox/dtl/demos/templates/blog_list.html
new file mode 100644
index 0000000..a686a4c
--- /dev/null
+++ b/js/dojo/dojox/dtl/demos/templates/blog_list.html
@@ -0,0 +1,9 @@
+<!--{% extends base %}-->
+{% load dojox.dtl.contrib.dijit %}
+<!--{% block body %}-->
+<ul>
+<!--{% for key, blog in blog_list.items %}-->
+<li onclick="_showDetail" class="blog-{{ key }}" style="cursor: pointer;">{{ blog.title }}</li>
+<!--{% endfor %}-->
+</ul>
+<!--{% endblock %}--> \ No newline at end of file
diff --git a/js/dojo/dojox/dtl/demos/templates/blog_page.html b/js/dojo/dojox/dtl/demos/templates/blog_page.html
new file mode 100644
index 0000000..63ef126
--- /dev/null
+++ b/js/dojo/dojox/dtl/demos/templates/blog_page.html
@@ -0,0 +1,7 @@
+<!--{% extends "shared:templates/blog_base.html" %}-->
+{% load dojox.dtl.contrib.dom %}
+<!--{% block body %}-->
+<div>
+ <!--{{ body|safe }}-->
+</div>
+<!--{% endblock %}--> \ No newline at end of file
diff --git a/js/dojo/dojox/dtl/demos/templates/gallery.html b/js/dojo/dojox/dtl/demos/templates/gallery.html
new file mode 100644
index 0000000..5c9cdb8
--- /dev/null
+++ b/js/dojo/dojox/dtl/demos/templates/gallery.html
@@ -0,0 +1,16 @@
+{% load dojox.dtl.contrib.data %}
+{% bind_data items to store as flickr %}
+<div>
+ Type a tag and press enter: <input dojoAttachEvent="onkeypress: keyUp" value="beach">
+ <table>
+ <tr>
+ {% for item in flickr %}<td><img src="{{ item.imageUrlThumb }}" dojoAttachEvent="onclick: selectThumbnail" class="{{ item.imageUrl }}" /></td>{% endfor %}
+ <td width="100%"></td>
+ </tr>
+ <tr>
+ <td colspan="{{ flickr|length|add:1 }}">
+ {% if selected %}<img src="{{ selected }}" />{% endif %}
+ </td>
+ </tr>
+ </table>
+</div> \ No newline at end of file
diff --git a/js/dojo/dojox/dtl/demos/templates/nodelist.html b/js/dojo/dojox/dtl/demos/templates/nodelist.html
new file mode 100644
index 0000000..ddf7def
--- /dev/null
+++ b/js/dojo/dojox/dtl/demos/templates/nodelist.html
@@ -0,0 +1,5 @@
+<div>
+ <ul>
+ {% for item in items %}<li>{{ item }}</li>{% endfor %}
+ </ul>
+</div> \ No newline at end of file
diff --git a/js/dojo/dojox/dtl/dom.js b/js/dojo/dojox/dtl/dom.js
new file mode 100644
index 0000000..831f056
--- /dev/null
+++ b/js/dojo/dojox/dtl/dom.js
@@ -0,0 +1,1050 @@
+//>>built
+define("dojox/dtl/dom", [
+ "dojo/_base/lang",
+ "./_base",
+ "dojox/string/tokenize",
+ "./Context",
+ "dojo/dom",
+ "dojo/dom-construct",
+ "dojo/_base/html",
+ "dojo/_base/array",
+ "dojo/_base/connect",
+ "dojo/_base/sniff"
+], function(lang,dd,Tokenize,context,dom,domconstruct,html,array,connect,has){
+ /*=====
+ Tokenize = dojox.string.tokenize;
+ dd = dojox.dtl;
+ =====*/
+ dd.BOOLS = {checked: 1, disabled: 1, readonly: 1};
+ dd.TOKEN_CHANGE = -11;
+ dd.TOKEN_ATTR = -12;
+ dd.TOKEN_CUSTOM = -13;
+ dd.TOKEN_NODE = 1;
+
+ var ddt = dd.text;
+ var ddh = dd.dom = {
+ _attributes: {},
+ _uppers: {},
+ _re4: /^function anonymous\(\)\s*{\s*(.*)\s*}$/,
+ _reTrim: /(?:^[\n\s]*(\{%)?\s*|\s*(%\})?[\n\s]*$)/g,
+ _reSplit: /\s*%\}[\n\s]*\{%\s*/g,
+ 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"), comment = "Test comment handling, and long comments, using comments whenever possible.";
+ div.innerHTML = "<!--" + comment + "-->";
+ if(div.childNodes.length && div.firstChild.nodeType == 8 && div.firstChild.data == comment){
+ this._commentable = true;
+ }
+ }
+
+ if(!this._commentable){
+ // Strip comments
+ text = text.replace(/<!--({({|%).*?(%|})})-->/g, "$1");
+ }
+
+ if(has("ie")){
+ text = text.replace(/\b(checked|disabled|readonly|style)="/g, 't$1="');
+ }
+ text = text.replace(/\bstyle="/g, 'tstyle="');
+
+ var match;
+ var table = has("webkit");
+ var pairs = [ // Format: [enable, parent, allowed children (first for nesting), nestings]
+ [true, "select", "option"],
+ [table, "tr", "td|th"],
+ [table, "thead", "tr", "th"],
+ [table, "tbody", "tr", "td"],
+ [table, "table", "tbody|thead|tr", "tr", "td"]
+ ];
+ var replacements = [];
+ // Some tags can't contain text. So we wrap the text in tags that they can have.
+ for(var i = 0, pair; pair = pairs[i]; i++){
+ if(!pair[0]){
+ continue;
+ }
+ if(text.indexOf("<" + pair[1]) != -1){
+ var selectRe = new RegExp("<" + pair[1] + "(?:.|\n)*?>((?:.|\n)+?)</" + pair[1] + ">", "ig");
+ tagLoop: while(match = selectRe.exec(text)){
+ // Do it like this to make sure we don't double-wrap
+ var inners = pair[2].split("|");
+ var innerRe = [];
+ for(var j = 0, inner; inner = inners[j]; j++){
+ innerRe.push("<" + inner + "(?:.|\n)*?>(?:.|\n)*?</" + inner + ">");
+ }
+ var tags = [];
+ var tokens = Tokenize(match[1], new RegExp("(" + innerRe.join("|") + ")", "ig"), function(data){
+ var tag = /<(\w+)/.exec(data)[1];
+ if(!tags[tag]){
+ tags[tag] = true;
+ tags.push(tag);
+ }
+ return {data: data};
+ });
+ if(tags.length){
+ var tag = (tags.length == 1) ? tags[0] : pair[2].split("|")[0];
+
+ var replace = [];
+ for(var j = 0, jl = tokens.length; j < jl; j++) {
+ var token = tokens[j];
+ if(lang.isObject(token)){
+ replace.push(token.data);
+ }else{
+ var stripped = token.replace(this._reTrim, "");
+ if(!stripped){ continue; }
+ token = stripped.split(this._reSplit);
+ for(var k = 0, kl = token.length; k < kl; k++){
+ var replacement = "";
+ for(var p = 2, pl = pair.length; p < pl; p++){
+ if(p == 2){
+ replacement += "<" + tag + ' dtlinstruction="{% ' + token[k].replace('"', '\\"') + ' %}">';
+ }else if(tag == pair[p]) {
+ continue;
+ }else{
+ replacement += "<" + pair[p] + ">";
+ }
+ }
+ replacement += "DTL";
+ for(var p = pair.length - 1; p > 1; p--){
+ if(p == 2){
+ replacement += "</" + tag + ">";
+ }else if(tag == pair[p]) {
+ continue;
+ }else{
+ replacement += "</" + pair[p] + ">";
+ }
+ }
+ replace.push("\xFF" + replacements.length);
+ replacements.push(replacement);
+ }
+ }
+ }
+ text = text.replace(match[1], replace.join(""));
+ }
+ }
+ }
+ }
+
+ for(var i = replacements.length; i--;){
+ text = text.replace("\xFF" + i, replacements[i]);
+ }
+
+ var re = /\b([a-zA-Z_:][a-zA-Z0-9_\-\.:]*)=['"]/g;
+ while(match = re.exec(text)){
+ var lower = match[1].toLowerCase();
+ if(lower == "dtlinstruction"){ continue; }
+ if(lower != match[1]){
+ this._uppers[lower] = match[1];
+ }
+ this._attributes[lower] = true;
+ }
+ var div = document.createElement("div");
+ div.innerHTML = text;
+ var output = {nodes: []};
+ while(div.childNodes.length){
+ output.nodes.push(div.removeChild(div.childNodes[0]))
+ }
+
+ return output;
+ },
+ tokenize: function(/*Node*/ nodes){
+ var tokens = [];
+
+ for(var i = 0, node; node = nodes[i++];){
+ if(node.nodeType != 1){
+ this.__tokenize(node, tokens);
+ }else{
+ this._tokenize(node, tokens);
+ }
+ }
+
+ return tokens;
+ },
+ _swallowed: [],
+ _tokenize: function(/*Node*/ node, /*Array*/ tokens){
+ var first = false;
+ var swallowed = this._swallowed;
+ var i, j, tag, child;
+
+ if(!tokens.first){
+ // Try to efficiently associate tags that use an attribute to
+ // remove the node from DOM (eg dojoType) so that we can efficiently
+ // locate them later in the tokenizing.
+ first = tokens.first = true;
+ var tags = dd.register.getAttributeTags();
+ for(i = 0; tag = tags[i]; i++){
+ try{
+ (tag[2])({ swallowNode: function(){ throw 1; }}, new dd.Token(dd.TOKEN_ATTR, ""));
+ }catch(e){
+ swallowed.push(tag);
+ }
+ }
+ }
+
+ for(i = 0; tag = swallowed[i]; i++){
+ var text = node.getAttribute(tag[0]);
+ if(text){
+ var swallowed = false;
+ var custom = (tag[2])({ swallowNode: function(){ swallowed = true; return node; }}, new dd.Token(dd.TOKEN_ATTR, tag[0] + " " + text));
+ if(swallowed){
+ if(node.parentNode && node.parentNode.removeChild){
+ node.parentNode.removeChild(node);
+ }
+ tokens.push([dd.TOKEN_CUSTOM, custom]);
+ return;
+ }
+ }
+ }
+
+ var children = [];
+ if(has("ie") && node.tagName == "SCRIPT"){
+ children.push({
+ nodeType: 3,
+ data: node.text
+ });
+ node.text = "";
+ }else{
+ for(i = 0; child = node.childNodes[i]; i++){
+ children.push(child);
+ }
+ }
+
+ tokens.push([dd.TOKEN_NODE, node]);
+
+ var change = false;
+ if(children.length){
+ // Only do a change request if we need to
+ tokens.push([dd.TOKEN_CHANGE, node]);
+ change = true;
+ }
+
+ for(var key in this._attributes){
+ var clear = false;
+
+ var value = "";
+ if(key == "class"){
+ value = node.className || value;
+ }else if(key == "for"){
+ value = node.htmlFor || value;
+ }else if(key == "value" && node.value == node.innerHTML){
+ // Sometimes .value is set the same as the contents of the item (button)
+ continue;
+ }else if(node.getAttribute){
+ value = node.getAttribute(key, 2) || value;
+ if(key == "href" || key == "src"){
+ if(has("ie")){
+ 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 = decodeURIComponent(value);
+ }
+ }else if(key == "tstyle"){
+ clear = key; // Placeholder because we can't use style
+ key = "style";
+ }else if(dd.BOOLS[key.slice(1)] && lang.trim(value)){
+ key = key.slice(1);
+ }else if(this._uppers[key] && lang.trim(value)){
+ clear = this._uppers[key]; // Replaced by lowercase
+ }
+ }
+
+ if(clear){
+ // Clear out values that are different than will
+ // be used in plugins
+ node.setAttribute(clear, "");
+ node.removeAttribute(clear);
+ }
+
+ if(typeof value == "function"){
+ value = value.toString().replace(this._re4, "$1");
+ }
+
+ if(!change){
+ // Only do a change request if we need to
+ tokens.push([dd.TOKEN_CHANGE, node]);
+ change = true;
+ }
+
+ // We'll have to resolve attributes during parsing (some ref plugins)
+
+ tokens.push([dd.TOKEN_ATTR, node, key, value]);
+ }
+
+ for(i = 0, child; child = children[i]; i++){
+ if(child.nodeType == 1){
+ var instruction = child.getAttribute("dtlinstruction");
+ if(instruction){
+ child.parentNode.removeChild(child);
+ child = {
+ nodeType: 8,
+ data: instruction
+ };
+ }
+ }
+ this.__tokenize(child, tokens);
+ }
+
+ if(!first && node.parentNode && node.parentNode.tagName){
+ if(change){
+ tokens.push([dd.TOKEN_CHANGE, node, true]);
+ }
+ tokens.push([dd.TOKEN_CHANGE, node.parentNode]);
+ node.parentNode.removeChild(node);
+ }else{
+ // If this node is parentless, it's a base node, so we have to "up" change to itself
+ // and note that it's a top-level to watch for errors
+ tokens.push([dd.TOKEN_CHANGE, node, true, true]);
+ }
+ },
+ __tokenize: function(child, tokens){
+ var data = child.data;
+ switch(child.nodeType){
+ case 1:
+ this._tokenize(child, tokens);
+ return;
+ case 3:
+ if(data.match(/[^\s\n]/) && (data.indexOf("{{") != -1 || data.indexOf("{%") != -1)){
+ var texts = ddt.tokenize(data);
+ for(var j = 0, text; text = texts[j]; j++){
+ if(typeof text == "string"){
+ tokens.push([dd.TOKEN_TEXT, text]);
+ }else{
+ tokens.push(text);
+ }
+ }
+ }else{
+ tokens.push([child.nodeType, child]);
+ }
+ if(child.parentNode) child.parentNode.removeChild(child);
+ return;
+ case 8:
+ if(data.indexOf("{%") == 0){
+ var text = lang.trim(data.slice(2, -2));
+ if(text.substr(0, 5) == "load "){
+ var parts = lang.trim(text).split(/\s+/g);
+ for(var i = 1, part; part = parts[i]; i++){
+ if (/\./.test(part)){
+ part = part.replace(/\./g,"/");
+ }
+ require([part]);
+ }
+ }
+ tokens.push([dd.TOKEN_BLOCK, text]);
+ }
+ if(data.indexOf("{{") == 0){
+ tokens.push([dd.TOKEN_VAR, lang.trim(data.slice(2, -2))]);
+ }
+ if(child.parentNode) child.parentNode.removeChild(child);
+ return;
+ }
+ }
+ };
+
+ dd.DomTemplate = lang.extend(function(/*String|DOMNode|dojo._Url*/ obj){
+ // summary: The template class for DOM templating.
+ if(!obj.nodes){
+ var node = dom.byId(obj);
+ if(node && node.nodeType == 1){
+ array.forEach(["class", "src", "href", "name", "value"], function(item){
+ ddh._attributes[item] = true;
+ });
+ obj = {
+ nodes: [node]
+ };
+ }else{
+ if(typeof obj == "object"){
+ obj = ddt.getTemplateString(obj);
+ }
+ obj = ddh.getTemplate(obj);
+ }
+ }
+
+ var tokens = ddh.tokenize(obj.nodes);
+ if(dd.tests){
+ this.tokens = tokens.slice(0);
+ }
+
+ var parser = new dd._DomParser(tokens);
+ this.nodelist = parser.parse();
+ },
+ {
+ _count: 0,
+ _re: /\bdojo:([a-zA-Z0-9_]+)\b/g,
+ setClass: function(/*String*/str){
+ // summary: Sets the specified class name on the root node.
+ this.getRootNode().className = str;
+ },
+ getRootNode: function(){
+ // summary: Returns the template root node.
+ return this.buffer.rootNode;
+ },
+ getBuffer: function(){
+ // summary: Returns a new buffer.
+ return new dd.DomBuffer();
+ },
+ render: function(/*dojox.dtl.Context?*/context, /*concatenable?*/buffer){
+ // summary: Renders this template.
+ buffer = this.buffer = buffer || this.getBuffer();
+ this.rootNode = null;
+ var output = this.nodelist.render(context || new dd.Context({}), buffer);
+ for(var i = 0, node; node = buffer._cache[i]; i++){
+ if(node._cache){
+ node._cache.length = 0;
+ }
+ }
+ return output;
+ },
+ unrender: function(context, buffer){
+ return this.nodelist.unrender(context, buffer);
+ }
+ });
+
+ dd.DomBuffer = lang.extend(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 = [];
+ },
+ {
+ concat: function(/*DOMNode*/ node){
+ var parent = this._parent;
+ if(parent && node.parentNode && node.parentNode === parent && !parent._dirty){
+ return this;
+ }
+
+ if(node.nodeType == 1 && !this.rootNode){
+ this.rootNode = node || true;
+ return this;
+ }
+
+ if(!parent){
+ if(node.nodeType == 3 && lang.trim(node.data)){
+ throw new Error("Text should not exist outside of the root node in template");
+ }
+ return this;
+ }
+ if(this._closed){
+ if(node.nodeType == 3 && !lang.trim(node.data)){
+ return this;
+ }else{
+ throw new Error("Content should not exist outside of the root node in template");
+ }
+ }
+ if(parent._dirty){
+ if(node._drawn && node.parentNode == parent){
+ var caches = parent._cache;
+ if(caches){
+ for(var i = 0, cache; cache = caches[i]; i++){
+ this.onAddNode && this.onAddNode(cache);
+ parent.insertBefore(cache, node);
+ this.onAddNodeComplete && this.onAddNodeComplete(cache);
+ }
+ caches.length = 0;
+ }
+ }
+ parent._dirty = false;
+ }
+ if(!parent._cache){
+ parent._cache = [];
+ this._cache.push(parent);
+ }
+ parent._dirty = true;
+ parent._cache.push(node);
+ return this;
+ },
+ remove: function(/*String|DomNode*/obj){
+ if(typeof obj == "string"){
+ if(this._parent){
+ this._parent.removeAttribute(obj);
+ }
+ }else{
+ if(obj.nodeType == 1 && !this.getRootNode() && !this._removed){
+ this._removed = true;
+ return this;
+ }
+ if(obj.parentNode){
+ this.onRemoveNode && this.onRemoveNode(obj);
+ if(obj.parentNode){
+ obj.parentNode.removeChild(obj);
+ }
+ }
+ }
+ return this;
+ },
+ setAttribute: function(key, value){
+ var old = html.attr(this._parent, key);
+ if(this.onChangeAttribute && old != value){
+ this.onChangeAttribute(this._parent, key, old, value);
+ }
+ if(key == "style"){
+ //console.log(value);
+ this._parent.style.cssText = value;
+ }else{
+ html.attr(this._parent, key, value);
+ //console.log(this._parent, key, value);
+ if(key == "value"){
+ this._parent.setAttribute(key, value);
+ }
+ }
+ return this;
+ },
+ addEvent: function(context, type, fn, /*Array|Function*/ args){
+ if(!context.getThis()){ throw new Error("You must use Context.setObject(instance)"); }
+ this.onAddEvent && this.onAddEvent(this.getParent(), type, fn);
+ var resolved = fn;
+ if(lang.isArray(args)){
+ resolved = function(e){
+ this[fn].apply(this, [e].concat(args));
+ }
+ }
+ return connect.connect(this.getParent(), type, context.getThis(), resolved);
+ },
+ setParent: function(node, /*Boolean?*/ up, /*Boolean?*/ root){
+ if(!this._parent) this._parent = this._first = node;
+
+ if(up && root && node === this._first){
+ this._closed = true;
+ }
+
+ if(up){
+ var parent = this._parent;
+ var script = "";
+ var ie = has("ie") && parent.tagName == "SCRIPT";
+ if(ie){
+ parent.text = "";
+ }
+ if(parent._dirty){
+ var caches = parent._cache;
+ var select = (parent.tagName == "SELECT" && !parent.options.length);
+ for(var i = 0, cache; cache = caches[i]; i++){
+ if(cache !== parent){
+ this.onAddNode && this.onAddNode(cache);
+ if(ie){
+ script += cache.data;
+ }else{
+ parent.appendChild(cache);
+ if(select && cache.defaultSelected && i){
+ select = i;
+ }
+ }
+ this.onAddNodeComplete && this.onAddNodeComplete(cache);
+ }
+ }
+ if(select){
+ parent.options.selectedIndex = (typeof select == "number") ? select : 0;
+ }
+ caches.length = 0;
+ parent._dirty = false;
+ }
+ if(ie){
+ parent.text = script;
+ }
+ }
+
+ this._parent = node;
+ this.onSetParent && this.onSetParent(node, up, root);
+ return this;
+ },
+ getParent: function(){
+ return this._parent;
+ },
+ getRootNode: function(){
+ return this.rootNode;
+ }
+ /*=====
+ ,
+ onSetParent: function(node, up){
+ // summary: Stub called when setParent is used.
+ },
+ onAddNode: function(node){
+ // summary: Stub called before new nodes are added
+ },
+ onAddNodeComplete: function(node){
+ // summary: Stub called after new nodes are added
+ },
+ onRemoveNode: function(node){
+ // summary: Stub called when nodes are removed
+ },
+ onChangeAttribute: function(node, attribute, old, updated){
+ // summary: Stub called when an attribute is changed
+ },
+ onChangeData: function(node, old, updated){
+ // summary: Stub called when a data in a node is changed
+ },
+ onClone: function(from, to){
+ // summary: Stub called when a node is duplicated
+ // from: DOMNode
+ // to: DOMNode
+ },
+ onAddEvent: function(node, type, description){
+ // summary: Stub to call when you're adding an event
+ // node: DOMNode
+ // type: String
+ // description: String
+ }
+ =====*/
+ });
+
+ dd._DomNode = lang.extend(function(node){
+ // summary: Places a node into DOM
+ this.contents = node;
+ },
+ {
+ render: function(context, buffer){
+ this._rendered = true;
+ return buffer.concat(this.contents);
+ },
+ unrender: function(context, buffer){
+ if(!this._rendered){
+ return buffer;
+ }
+ this._rendered = false;
+ return buffer.remove(this.contents);
+ },
+ clone: function(buffer){
+ return new this.constructor(this.contents);
+ }
+ });
+
+ dd._DomNodeList = lang.extend(function(/*Node[]*/ nodes){
+ // summary: A list of any DOM-specific node objects
+ // 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 || [];
+ },
+ {
+ push: function(node){
+ this.contents.push(node);
+ },
+ unshift: function(node){
+ this.contents.unshift(node);
+ },
+ render: function(context, buffer, /*Node*/ instance){
+ buffer = buffer || dd.DomTemplate.prototype.getBuffer();
+
+ 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);
+ }
+ return buffer;
+ },
+ dummyRender: function(context, buffer, asNode){
+ // summary: A really expensive way of checking to see how a rendering will look.
+ // Used in the ifchanged tag
+ var div = document.createElement("div");
+
+ var parent = buffer.getParent();
+ var old = parent._clone;
+ // Tell the clone system to attach itself to our new div
+ parent._clone = div;
+ var nodelist = this.clone(buffer, div);
+ if(old){
+ // Restore state if there was a previous clone
+ parent._clone = old;
+ }else{
+ // Remove if there was no clone
+ parent._clone = null;
+ }
+
+ buffer = dd.DomTemplate.prototype.getBuffer();
+ nodelist.unshift(new dd.ChangeNode(div));
+ nodelist.unshift(new dd._DomNode(div));
+ nodelist.push(new dd.ChangeNode(div, true));
+ nodelist.render(context, buffer);
+
+ if(asNode){
+ return buffer.getRootNode();
+ }
+
+ var html = div.innerHTML;
+ return (has("ie")) ? domconstruct.replace(/\s*_(dirty|clone)="[^"]*"/g, "") : html;
+ },
+ unrender: function(context, buffer, instance){
+ if(instance){
+ var parent = buffer.getParent();
+ }
+ 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");
+ }
+ if(parent){
+ buffer.setParent(parent);
+ }
+ return buffer;
+ },
+ clone: function(buffer){
+ // summary:
+ // Used to create an identical copy of a NodeList, useful for things like the for tag.
+ var parent = buffer.getParent();
+ var contents = this.contents;
+ var nodelist = new dd._DomNodeList();
+ var cloned = [];
+ for(var i = 0; i < contents.length; i++){
+ var clone = contents[i].clone(buffer);
+ if(clone instanceof dd.ChangeNode || clone instanceof dd._DomNode){
+ var item = clone.contents._clone;
+ if(item){
+ clone.contents = item;
+ }else if(parent != clone.contents && clone instanceof dd._DomNode){
+ var node = clone.contents;
+ clone.contents = clone.contents.cloneNode(false);
+ buffer.onClone && buffer.onClone(node, clone.contents);
+ cloned.push(node);
+ node._clone = clone.contents;
+ }
+ }
+ nodelist.push(clone);
+ }
+
+ for(var i = 0, clone; clone = cloned[i]; i++){
+ clone._clone = null;
+ }
+
+ return nodelist;
+ },
+ rtrim: function(){
+ while(1){
+ var i = this.contents.length - 1;
+ if(this.contents[i] instanceof dd._DomTextNode && this.contents[i].isEmpty()){
+ this.contents.pop();
+ }else{
+ break;
+ }
+ }
+
+ return this;
+ }
+ });
+
+ dd._DomVarNode = lang.extend(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 dd._Filter(str);
+ },
+ {
+ render: function(context, buffer){
+ var str = this.contents.resolve(context);
+
+ // What type of rendering?
+ var type = "text";
+ if(str){
+ if(str.render && str.getRootNode){
+ type = "injection";
+ }else if(str.safe){
+ if(str.nodeType){
+ type = "node";
+ }else if(str.toString){
+ str = str.toString();
+ type = "html";
+ }
+ }
+ }
+
+ // Has the typed changed?
+ if(this._type && type != this._type){
+ this.unrender(context, buffer);
+ }
+ this._type = type;
+
+ // Now render
+ switch(type){
+ case "text":
+ this._rendered = true;
+ this._txt = this._txt || document.createTextNode(str);
+ if(this._txt.data != str){
+ var old = this._txt.data;
+ this._txt.data = str;
+ buffer.onChangeData && buffer.onChangeData(this._txt, old, this._txt.data);
+ }
+ return buffer.concat(this._txt);
+ case "injection":
+ var root = str.getRootNode();
+
+ if(this._rendered && root != this._root){
+ buffer = this.unrender(context, buffer);
+ }
+ this._root = root;
+
+ var injected = this._injected = new dd._DomNodeList();
+ injected.push(new dd.ChangeNode(buffer.getParent()));
+ injected.push(new dd._DomNode(root));
+ injected.push(str);
+ injected.push(new dd.ChangeNode(buffer.getParent()));
+ this._rendered = true;
+
+ return injected.render(context, buffer);
+ case "node":
+ this._rendered = true;
+ if(this._node && this._node != str && this._node.parentNode && this._node.parentNode === buffer.getParent()){
+ this._node.parentNode.removeChild(this._node);
+ }
+ this._node = str;
+ return buffer.concat(str);
+ case "html":
+ if(this._rendered && this._src != str){
+ buffer = this.unrender(context, buffer);
+ }
+ this._src = str;
+
+ // This can get reset in the above tag
+ if(!this._rendered){
+ this._rendered = true;
+ this._html = this._html || [];
+ var div = (this._div = this._div || document.createElement("div"));
+ div.innerHTML = str;
+ var children = div.childNodes;
+ while(children.length){
+ var removed = div.removeChild(children[0]);
+ this._html.push(removed);
+ buffer = buffer.concat(removed);
+ }
+ }
+
+ return buffer;
+ default:
+ return buffer;
+ }
+ },
+ unrender: function(context, buffer){
+ if(!this._rendered){
+ return buffer;
+ }
+ this._rendered = false;
+
+ // Unrender injected nodes
+ switch(this._type){
+ case "text":
+ return buffer.remove(this._txt);
+ case "injection":
+ return this._injection.unrender(context, buffer);
+ case "node":
+ if(this._node.parentNode === buffer.getParent()){
+ return buffer.remove(this._node);
+ }
+ return buffer;
+ case "html":
+ for(var i = 0, l = this._html.length; i < l; i++){
+ buffer = buffer.remove(this._html[i]);
+ }
+ return buffer;
+ default:
+ return buffer;
+ }
+ },
+ clone: function(){
+ return new this.constructor(this.contents.getExpression());
+ }
+ });
+
+ dd.ChangeNode = lang.extend(function(node, /*Boolean?*/ up, /*Bookean*/ root){
+ // summary: Changes the parent during render/unrender
+ this.contents = node;
+ this.up = up;
+ this.root = root;
+ },
+ {
+ render: function(context, buffer){
+ return buffer.setParent(this.contents, this.up, this.root);
+ },
+ unrender: function(context, buffer){
+ if(!buffer.getParent()){
+ return buffer;
+ }
+ return buffer.setParent(this.contents);
+ },
+ clone: function(){
+ return new this.constructor(this.contents, this.up, this.root);
+ }
+ });
+
+ dd.AttributeNode = lang.extend(function(key, value){
+ // summary: Works on attributes
+ this.key = key;
+ this.value = value;
+ this.contents = value;
+ if(this._pool[value]){
+ this.nodelist = this._pool[value];
+ }else{
+ if(!(this.nodelist = dd.quickFilter(value))){
+ this.nodelist = (new dd.Template(value, true)).nodelist;
+ }
+ this._pool[value] = this.nodelist;
+ }
+
+ this.contents = "";
+ },
+ {
+ _pool: {},
+ render: function(context, buffer){
+ var key = this.key;
+ var value = this.nodelist.dummyRender(context);
+ if(dd.BOOLS[key]){
+ value = !(value == "false" || value == "undefined" || !value);
+ }
+ if(value !== this.contents){
+ this.contents = value;
+ return buffer.setAttribute(key, value);
+ }
+ return buffer;
+ },
+ unrender: function(context, buffer){
+ this.contents = "";
+ return buffer.remove(this.key);
+ },
+ clone: function(buffer){
+ return new this.constructor(this.key, this.value);
+ }
+ });
+
+ dd._DomTextNode = lang.extend(function(str){
+ // summary: Adds a straight text node without any processing
+ this.contents = document.createTextNode(str);
+ this.upcoming = str;
+ },
+ {
+ set: function(data){
+ this.upcoming = data;
+ return this;
+ },
+ render: function(context, buffer){
+ if(this.contents.data != this.upcoming){
+ var old = this.contents.data;
+ this.contents.data = this.upcoming;
+ buffer.onChangeData && buffer.onChangeData(this.contents, old, this.upcoming);
+ }
+ return buffer.concat(this.contents);
+ },
+ unrender: function(context, buffer){
+ return buffer.remove(this.contents);
+ },
+ isEmpty: function(){
+ return !lang.trim(this.contents.data);
+ },
+ clone: function(){
+ return new this.constructor(this.contents.data);
+ }
+ });
+
+ dd._DomParser = lang.extend(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;
+ },
+ {
+ i: 0,
+ parse: function(/*Array?*/ stop_at){
+ 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._DomNodeList();
+ while(this.i < tokens.length){
+ var token = tokens[this.i++];
+ var type = token[0];
+ var value = token[1];
+ if(type == dd.TOKEN_CUSTOM){
+ nodelist.push(value);
+ }else if(type == dd.TOKEN_CHANGE){
+ var changeNode = new dd.ChangeNode(value, token[2], token[3]);
+ value[changeNode.attr] = changeNode;
+ nodelist.push(changeNode);
+ }else if(type == dd.TOKEN_ATTR){
+ var fn = ddt.getTag("attr:" + token[2], true);
+ if(fn && token[3]){
+ if (token[3].indexOf("{%") != -1 || token[3].indexOf("{{") != -1) {
+ value.setAttribute(token[2], "");
+ }
+ nodelist.push(fn(null, new dd.Token(type, token[2] + " " + token[3])));
+ }else if(lang.isString(token[3])){
+ if(token[2] == "style" || token[3].indexOf("{%") != -1 || token[3].indexOf("{{") != -1){
+ nodelist.push(new dd.AttributeNode(token[2], token[3]));
+ }else if(lang.trim(token[3])){
+ try{
+ html.attr(value, token[2], token[3]);
+ }catch(e){}
+ }
+ }
+ }else if(type == dd.TOKEN_NODE){
+ var fn = ddt.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, new dd.Token(type, value), value.tagName.toLowerCase()));
+ }
+ nodelist.push(new dd._DomNode(value));
+ }else if(type == dd.TOKEN_VAR){
+ nodelist.push(new dd._DomVarNode(value));
+ }else if(type == dd.TOKEN_TEXT){
+ nodelist.push(new dd._DomTextNode(value.data || value));
+ }else if(type == dd.TOKEN_BLOCK){
+ if(terminators[value]){
+ --this.i;
+ return nodelist;
+ }
+ var cmd = value.split(/\s+/g);
+ if(cmd.length){
+ cmd = cmd[0];
+ var fn = ddt.getTag(cmd);
+ if(typeof fn != "function"){
+ throw new Error("Function not found for " + cmd);
+ }
+ var tpl = fn(this, new dd.Token(type, 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_token: function(){
+ // summary: Returns the next token in the list.
+ var token = this.contents[this.i++];
+ return new dd.Token(token[0], token[1]);
+ },
+ delete_first_token: function(){
+ this.i++;
+ },
+ skip_past: function(endtag){
+ return dd._Parser.prototype.skip_past.call(this, endtag);
+ },
+ create_variable_node: function(expr){
+ return new dd._DomVarNode(expr);
+ },
+ create_text_node: function(expr){
+ return new dd._DomTextNode(expr || "");
+ },
+ getTemplate: function(/*String*/ loc){
+ return new dd.DomTemplate(ddh.getTemplate(loc));
+ }
+ });
+ return dojox.dtl.dom;
+});
diff --git a/js/dojo/dojox/dtl/ext-dojo/NodeList.js b/js/dojo/dojox/dtl/ext-dojo/NodeList.js
new file mode 100644
index 0000000..d501685
--- /dev/null
+++ b/js/dojo/dojox/dtl/ext-dojo/NodeList.js
@@ -0,0 +1,41 @@
+//>>built
+define("dojox/dtl/ext-dojo/NodeList", [
+ "dojo/_base/lang",
+ "dojo/_base/NodeList",
+ "../_base"
+], function(lang,Nodelist,dd){
+ /*=====
+ Nodelist = dojo.Nodelist;
+ dd = dojox.dtl;
+ =====*/
+
+ var nl = lang.getObject("dojox.dtl.ext-dojo.NodeList", true);
+
+ lang.extend(Nodelist, {
+ dtl: function(template, context){
+ // summary: Renders the specified template in each of the Nodelist entries.
+ // template: dojox.dtl.__StringArgs|String
+ // The template string or location
+ // context: dojox.dtl.__ObjectArgs|Object
+ // The context object or location
+ var d = dd, self = this;
+
+ var render = function(template, context){
+ var content = template.render(new d._Context(context));
+ self.forEach(function(node){
+ node.innerHTML = content;
+ });
+ }
+
+ d.text._resolveTemplateArg(template).addCallback(function(templateString){
+ template = new d.Template(templateString);
+ d.text._resolveContextArg(context).addCallback(function(context){
+ render(template, context);
+ });
+ });
+
+ return this;
+ }
+ });
+ return nl;
+}); \ No newline at end of file
diff --git a/js/dojo/dojox/dtl/filter/dates.js b/js/dojo/dojox/dtl/filter/dates.js
new file mode 100644
index 0000000..b9714ad
--- /dev/null
+++ b/js/dojo/dojox/dtl/filter/dates.js
@@ -0,0 +1,68 @@
+//>>built
+define("dojox/dtl/filter/dates", [
+ "dojo/_base/lang",
+ "../_base",
+ "../utils/date"
+], function(lang,dd,ddud){
+ /*=====
+ dd = dojox.dtl;
+ =====*/
+ lang.getObject("dojox.dtl.filter.dates", true);
+
+ var ddfd = dd.filter.dates;
+ lang.mixin(ddfd, {
+ _toDate: function(value){
+ if(value instanceof Date){
+ return value;
+ }
+ value = new Date(value);
+ if(value.getTime() == new Date(0).getTime()){
+ return "";
+ }
+ return value;
+ },
+ date: function(value, arg){
+ // summary: Formats a date according to the given format
+ value = ddfd._toDate(value);
+ if(!value){
+ return "";
+ }
+ arg = arg || "N j, Y";
+ return ddud.format(value, arg);
+ },
+ time: function(value, arg){
+ // summary: Formats a time according to the given format
+ value = ddfd._toDate(value);
+ if(!value){
+ return "";
+ }
+ arg = arg || "P";
+ return ddud.format(value, arg);
+ },
+ timesince: function(value, arg){
+ // summary: Formats a date as the time since that date (i.e. "4 days, 6 hours")
+ value = ddfd._toDate(value);
+ if(!value){
+ return "";
+ }
+ var timesince = ddud.timesince;
+ 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")
+ value = ddfd._toDate(value);
+ if(!value){
+ return "";
+ }
+ var timesince = ddud.timesince;
+ if(arg){
+ return timesince(arg, value);
+ }
+ return timesince(new Date(), value);
+ }
+ });
+ return dojox.dtl.filter.dates;
+}); \ No newline at end of file
diff --git a/js/dojo/dojox/dtl/filter/htmlstrings.js b/js/dojo/dojox/dtl/filter/htmlstrings.js
new file mode 100644
index 0000000..a10beef
--- /dev/null
+++ b/js/dojo/dojox/dtl/filter/htmlstrings.js
@@ -0,0 +1,53 @@
+//>>built
+define("dojox/dtl/filter/htmlstrings", [
+ "dojo/_base/lang",
+ "../_base"
+], function(lang,dd){
+ /*=====
+ dd = dojox.dtl;
+ =====*/
+ lang.getObject("dojox.dtl.filter.htmlstrings", true);
+
+ lang.mixin(dd.filter.htmlstrings, {
+ _linebreaksrn: /(\r\n|\n\r)/g,
+ _linebreaksn: /\n{2,}/g,
+ _linebreakss: /(^\s+|\s+$)/g,
+ _linebreaksbr: /\n/g,
+ _removetagsfind: /[a-z0-9]+/g,
+ _striptags: /<[^>]*?>/g,
+ linebreaks: function(value){
+ // summary: Converts newlines into <p> and <br />s
+ var output = [];
+ var dh = dd.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 = dd.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 = dd.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, "");
+ }
+ });
+ return dojox.dtl.filter.htmlstrings;
+}); \ No newline at end of file
diff --git a/js/dojo/dojox/dtl/filter/integers.js b/js/dojo/dojox/dtl/filter/integers.js
new file mode 100644
index 0000000..86d0e54
--- /dev/null
+++ b/js/dojo/dojox/dtl/filter/integers.js
@@ -0,0 +1,38 @@
+//>>built
+define("dojox/dtl/filter/integers", [
+ "dojo/_base/lang",
+ "../_base"
+], function(lang,dd){
+ /*=====
+ dd = dojox.dtl;
+ =====*/
+ lang.getObject("dojox.dtl.filter.integers", true);
+
+ lang.mixin(dd.filter.integers, {
+ add: function(value, arg){
+ value = parseInt(value, 10);
+ arg = parseInt(arg, 10);
+ 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, 10);
+ arg = parseInt(arg, 10) - 1;
+ if(arg >= 0){
+ value += "";
+ if(arg < value.length){
+ value = parseInt(value.charAt(arg), 10);
+ }else{
+ value = 0;
+ }
+ }
+ return (isNaN(value) ? 0 : value);
+ }
+ });
+ return dojox.dtl.filter.integers;
+}); \ No newline at end of file
diff --git a/js/dojo/dojox/dtl/filter/lists.js b/js/dojo/dojox/dtl/filter/lists.js
new file mode 100644
index 0000000..0292244
--- /dev/null
+++ b/js/dojo/dojox/dtl/filter/lists.js
@@ -0,0 +1,145 @@
+//>>built
+define("dojox/dtl/filter/lists", [
+ "dojo/_base/lang",
+ "../_base"
+], function(lang,dd){
+ /*=====
+ dd = dojox.dtl;
+ =====*/
+ lang.getObject("dojox.dtl.filter.lists", true);
+
+ lang.mixin(dd.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 i, item, items = [];
+ if(!lang.isArray(value)){
+ var obj = value, value = [];
+ for(var key in obj){
+ value.push(obj[key]);
+ }
+ }
+ for(i = 0; i < value.length; i++){
+ items.push([new dojox.dtl._Filter('var.' + arg).resolve(new dojox.dtl._Context({ 'var' : value[i]})), value[i]]);
+ }
+ items.sort(dojox.dtl.filter.lists._dictsort);
+ var output = [];
+ for(i = 0; 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 i, indent = "";
+ for(i = 0; i < tabs; i++){
+ indent += "\t";
+ }
+ if(value[1] && value[1].length){
+ var recurse = [];
+ for(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);
+ }
+ });
+ return dojox.dtl.filter.lists;
+}); \ No newline at end of file
diff --git a/js/dojo/dojox/dtl/filter/logic.js b/js/dojo/dojox/dtl/filter/logic.js
new file mode 100644
index 0000000..9c8bf39
--- /dev/null
+++ b/js/dojo/dojox/dtl/filter/logic.js
@@ -0,0 +1,46 @@
+//>>built
+define("dojox/dtl/filter/logic", [
+ "dojo/_base/lang",
+ "../_base"
+], function(lang,dd){
+ /*=====
+ dd = dojox.dtl;
+ =====*/
+ lang.getObject("dojox.dtl.filter.logic", true);
+
+ lang.mixin(dd.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, 10) % parseInt(arg, 10)) === 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];
+ }
+ });
+ return dojox.dtl.filter.logic;
+}); \ No newline at end of file
diff --git a/js/dojo/dojox/dtl/filter/misc.js b/js/dojo/dojox/dtl/filter/misc.js
new file mode 100644
index 0000000..2b88a4a
--- /dev/null
+++ b/js/dojo/dojox/dtl/filter/misc.js
@@ -0,0 +1,66 @@
+//>>built
+define("dojox/dtl/filter/misc", [
+ "dojo/_base/lang",
+ "dojo/_base/json", // dojo.toJson
+ "../_base"
+], function(lang,json,dd){
+ /*=====
+ dd = dojox.dtl;
+ =====*/
+ lang.getObject("dojox.dtl.filter.misc", true);
+
+ lang.mixin(dd.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, 10) != 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 = dd.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 json.toJson(value);
+ }
+ });
+ return dojox.dtl.filter.misc;
+});
diff --git a/js/dojo/dojox/dtl/filter/strings.js b/js/dojo/dojox/dtl/filter/strings.js
new file mode 100644
index 0000000..da71c3e
--- /dev/null
+++ b/js/dojo/dojox/dtl/filter/strings.js
@@ -0,0 +1,337 @@
+//>>built
+define("dojox/dtl/filter/strings", [
+ "dojo/_base/lang",
+ "dojo/_base/array",
+ "dojox/string/tokenize",
+ "dojox/string/sprintf",
+ "../filter/htmlstrings",
+ "../_base"
+], function(lang,array,Tokenize,Sprintf,htmlstrings,dd){
+ /*=====
+ dd = dojox.dtl;
+ Tokenize = dojox.string.tokenize;
+ Sprintf = dojox.string.sprintf;
+ =====*/
+ lang.getObject("dojox.dtl.filter.strings", true);
+
+ lang.mixin(dd.filter.strings, {
+ _urlquote: function(/*String*/ url, /*String?*/ safe){
+ if(!safe){
+ safe = "/";
+ }
+ return 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("");
+ },
+ 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, 10);
+ 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.filter.strings._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) + ". " + dojox.dtl._base.escape(line));
+ }
+ return output.join("\n");
+ },
+ ljust: function(value, arg){
+ value = value + "";
+ arg = parseInt(arg, 10);
+ 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, 10);
+ 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 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, 10);
+ 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, 10);
+
+ if(arg <= 0){
+ return "";
+ }
+
+ var strings = dojox.dtl.filter.strings;
+ var words = 0;
+ var open = [];
+
+ var output = 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 = array.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.filter.strings._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 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){
+ value = lang.trim(value);
+ if(!value){ return 0; }
+ return value.split(/\s+/g).length;
+ },
+ wordwrap: function(value, arg){
+ arg = parseInt(arg);
+ // summary: Wraps words at specified line length
+ var output = [];
+ var parts = value.split(/\s+/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("");
+ }
+ });
+ return dojox.dtl.filter.strings;
+}); \ No newline at end of file
diff --git a/js/dojo/dojox/dtl/render/dom.js b/js/dojo/dojox/dtl/render/dom.js
new file mode 100644
index 0000000..07af56a
--- /dev/null
+++ b/js/dojo/dojox/dtl/render/dom.js
@@ -0,0 +1,43 @@
+//>>built
+define("dojox/dtl/render/dom", [
+ "dojo/_base/lang",
+ "dojo/dom",
+ "../Context",
+ "../dom",
+ "../_base"
+], function(lang,dom,ddc,dddom,dd){
+ /*=====
+ dd = dojox.dtl;
+ =====*/
+ lang.getObject("dojox.dtl.render.dom", true);
+
+ dd.render.dom.Render = function(/*DOMNode?*/ attachPoint, /*dojox.dtl.DomTemplate?*/ tpl){
+ this._tpl = tpl;
+ this.domNode = dom.byId(attachPoint);
+ }
+ lang.extend(dd.render.dom.Render, {
+ setAttachPoint: function(/*Node*/ node){
+ this.domNode = node;
+ },
+ render: function(/*Object*/ context, /*dojox.dtl.DomTemplate?*/ tpl, /*dojox.dtl.DomBuffer?*/ buffer){
+ if(!this.domNode){
+ throw new Error("You cannot use the Render object without specifying where you want to render it");
+ }
+
+ this._tpl = tpl = tpl || this._tpl;
+ buffer = buffer || tpl.getBuffer();
+ context = context || new ddc();
+
+ var frag = tpl.render(context, buffer).getParent();
+ if(!frag){
+ throw new Error("Rendered template does not have a root node");
+ }
+
+ if(this.domNode !== frag){
+ this.domNode.parentNode.replaceChild(frag, this.domNode);
+ this.domNode = frag;
+ }
+ }
+ });
+ return dojox.dtl.render.dom;
+}); \ No newline at end of file
diff --git a/js/dojo/dojox/dtl/render/html.js b/js/dojo/dojox/dtl/render/html.js
new file mode 100644
index 0000000..6b7296f
--- /dev/null
+++ b/js/dojo/dojox/dtl/render/html.js
@@ -0,0 +1,14 @@
+//>>built
+define("dojox/dtl/render/html", [
+ "dojo/_base/lang",
+ "../render/dom",
+ "../_base"
+], function(lang,ddrd,dd){
+ /*=====
+ dd = dojox.dtl;
+ =====*/
+ lang.getObject("dojox.dtl.render.html", true);
+
+ dd.render.html.Render = ddrd.Render;
+ return dojox.dtl.render.html;
+});
diff --git a/js/dojo/dojox/dtl/tag/date.js b/js/dojo/dojox/dtl/tag/date.js
new file mode 100644
index 0000000..afb8aa3
--- /dev/null
+++ b/js/dojo/dojox/dtl/tag/date.js
@@ -0,0 +1,39 @@
+//>>built
+define("dojox/dtl/tag/date", [
+ "dojo/_base/lang",
+ "../_base",
+ "../utils/date"
+], function(lang,dd,ddud){
+ /*=====
+ dd = dojox.dtl;
+ =====*/
+ lang.getObject("dojox.dtl.tag.date", true);
+
+ dojox.dtl.tag.date.NowNode = function(format, node){
+ this._format = format;
+ this.format = new ddud.DateFormat(format);
+ this.contents = node;
+ }
+ lang.extend(dd.tag.date.NowNode, {
+ render: function(context, buffer){
+ this.contents.set(this.format.format(new Date()));
+ return this.contents.render(context, buffer);
+ },
+ unrender: function(context, buffer){
+ return this.contents.unrender(context, buffer);
+ },
+ clone: function(buffer){
+ return new this.constructor(this._format, this.contents.clone(buffer));
+ }
+ });
+
+ dojox.dtl.tag.date.now = function(parser, token){
+ // Split by either :" or :'
+ var parts = token.split_contents();
+ if(parts.length != 2){
+ throw new Error("'now' statement takes one argument");
+ }
+ return new dojox.dtl.tag.date.NowNode(parts[1].slice(1, -1), parser.create_text_node());
+ };
+ return dojox.dtl.tag.date;
+});
diff --git a/js/dojo/dojox/dtl/tag/loader.js b/js/dojo/dojox/dtl/tag/loader.js
new file mode 100644
index 0000000..6bd68d1
--- /dev/null
+++ b/js/dojo/dojox/dtl/tag/loader.js
@@ -0,0 +1,304 @@
+//>>built
+define("dojox/dtl/tag/loader", [
+ "dojo/_base/lang",
+ "../_base",
+ "dojo/_base/array",
+ "dojo/_base/connect"
+], function(lang,dd,array,connect){
+ /*=====
+ dd = dojox.dtl;
+ =====*/
+ lang.getObject("dojox.dtl.tag.loader", true);
+
+ var ddtl = dd.tag.loader;
+
+ ddtl.BlockNode = lang.extend(function(name, nodelist){
+ this.name = name;
+ this.nodelist = nodelist; // Can be overridden
+ },
+ {
+ "super": function(){
+ if(this.parent){
+ var html = this.parent.nodelist.dummyRender(this.context, null, true);
+ if(typeof html == "string"){
+ html = new String(html);
+ }
+ html.safe = true;
+ return html;
+ }
+ return '';
+ },
+ render: function(context, buffer){
+ var name = this.name;
+ var nodelist = this.nodelist;
+ var parent;
+ if(buffer.blocks){
+ var block = buffer.blocks[name];
+ if(block){
+ parent = block.parent;
+ nodelist = block.nodelist;
+ block.used = true;
+ }
+ }
+
+ this.rendered = nodelist;
+
+ context = context.push();
+ this.context = context;
+ this.parent = null;
+ if(nodelist != this.nodelist){
+ this.parent = this;
+ }
+ context.block = this;
+
+ if(buffer.getParent){
+ var bufferParent = buffer.getParent();
+ var setParent = connect.connect(buffer, "onSetParent", function(node, up, root){
+ if(up && root){
+ buffer.setParent(bufferParent);
+ }
+ });
+ }
+ buffer = nodelist.render(context, buffer, this);
+ setParent && connect.disconnect(setParent);
+ context = context.pop();
+ return buffer;
+ },
+ unrender: function(context, buffer){
+ return this.rendered.unrender(context, buffer);
+ },
+ clone: function(buffer){
+ return new this.constructor(this.name, this.nodelist.clone(buffer));
+ },
+ toString: function(){ return "dojox.dtl.tag.loader.BlockNode"; }
+ });
+
+ ddtl.ExtendsNode = lang.extend(function(getTemplate, nodelist, shared, parent, key){
+ this.getTemplate = getTemplate;
+ this.nodelist = nodelist;
+ this.shared = shared;
+ this.parent = parent;
+ this.key = key;
+ },
+ {
+ parents: {},
+ getParent: function(context){
+ var parent = this.parent;
+ if(!parent){
+ var string;
+ parent = this.parent = context.get(this.key, false);
+ if(!parent){
+ throw new Error("extends tag used a variable that did not resolve");
+ }
+ if(typeof parent == "object"){
+ var url = parent.url || parent.templatePath;
+ if(parent.shared){
+ this.shared = true;
+ }
+ if(url){
+ parent = this.parent = url.toString();
+ }else if(parent.templateString){
+ // Allow the builder's string interning to work
+ string = parent.templateString;
+ parent = this.parent = " ";
+ }else{
+ parent = this.parent = this.parent.toString();
+ }
+ }
+ if(parent && parent.indexOf("shared:") === 0){
+ this.shared = true;
+ parent = this.parent = parent.substring(7, parent.length);
+ }
+ }
+ 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(string || dojox.dtl.text.getTemplateString(parent));
+ if(this.shared){
+ this.parents[parent] = this.parent;
+ }
+ return this.parent;
+ },
+ render: function(context, buffer){
+ var parent = this.getParent(context);
+
+ parent.blocks = parent.blocks || {};
+ buffer.blocks = buffer.blocks || {};
+
+ for(var i = 0, node; node = this.nodelist.contents[i]; i++){
+ if(node instanceof dojox.dtl.tag.loader.BlockNode){
+ var old = parent.blocks[node.name];
+ if(old && old.nodelist != node.nodelist){
+ // In a shared template, the individual blocks might change
+ buffer = old.nodelist.unrender(context, buffer);
+ }
+ parent.blocks[node.name] = buffer.blocks[node.name] = {
+ shared: this.shared,
+ nodelist: node.nodelist,
+ used: false
+ }
+ }
+ }
+
+ this.rendered = parent;
+ return parent.nodelist.render(context, buffer, this);
+ },
+ unrender: function(context, buffer){
+ return this.rendered.unrender(context, buffer, this);
+ },
+ toString: function(){ return "dojox.dtl.block.ExtendsNode"; }
+ });
+
+ ddtl.IncludeNode = lang.extend(function(path, constant, getTemplate, text, parsed){
+ this._path = path;
+ this.constant = constant;
+ this.path = (constant) ? path : new dd._Filter(path);
+ this.getTemplate = getTemplate;
+ this.text = text;
+ this.parsed = (arguments.length == 5) ? parsed : true;
+ },
+ {
+ _cache: [{}, {}],
+ render: function(context, buffer){
+ var location = ((this.constant) ? this.path : this.path.resolve(context)).toString();
+ var parsed = Number(this.parsed);
+ var dirty = false;
+ if(location != this.last){
+ dirty = true;
+ if(this.last){
+ buffer = this.unrender(context, buffer);
+ }
+ this.last = location;
+ }
+
+ var cache = this._cache[parsed];
+
+ if(parsed){
+ if(!cache[location]){
+ cache[location] = dd.text._resolveTemplateArg(location, true);
+ }
+ if(dirty){
+ var template = this.getTemplate(cache[location]);
+ this.rendered = template.nodelist;
+ }
+ return this.rendered.render(context, buffer, this);
+ }else{
+ if(this.text instanceof dd._TextNode){
+ if(dirty){
+ this.rendered = this.text;
+ this.rendered.set(dd.text._resolveTemplateArg(location, true));
+ }
+ return this.rendered.render(context, buffer);
+ }else{
+ if(!cache[location]){
+ var nodelist = [];
+ var div = document.createElement("div");
+ div.innerHTML = dd.text._resolveTemplateArg(location, true);
+ var children = div.childNodes;
+ while(children.length){
+ var removed = div.removeChild(children[0]);
+ nodelist.push(removed);
+ }
+ cache[location] = nodelist;
+ }
+ if(dirty){
+ this.nodelist = [];
+ var exists = true;
+ for(var i = 0, child; child = cache[location][i]; i++){
+ this.nodelist.push(child.cloneNode(true));
+ }
+ }
+ for(var i = 0, node; node = this.nodelist[i]; i++){
+ buffer = buffer.concat(node);
+ }
+ }
+ }
+ return buffer;
+ },
+ unrender: function(context, buffer){
+ if(this.rendered){
+ buffer = this.rendered.unrender(context, buffer);
+ }
+ if(this.nodelist){
+ for(var i = 0, node; node = this.nodelist[i]; i++){
+ buffer = buffer.remove(node);
+ }
+ }
+ return buffer;
+ },
+ clone: function(buffer){
+ return new this.constructor(this._path, this.constant, this.getTemplate, this.text.clone(buffer), this.parsed);
+ }
+ });
+
+ lang.mixin(ddtl, {
+ block: function(parser, token){
+ var parts = token.contents.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]).rtrim();
+ parser.next_token();
+ return new dojox.dtl.tag.loader.BlockNode(name, nodelist);
+ },
+ extends_: function(parser, token){
+ var parts = token.contents.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);
+ },
+ include: function(parser, token){
+ var parts = token.contents.split();
+ if(parts.length != 2){
+ throw new Error(parts[0] + " tag takes one argument: the name of the template to be included");
+ }
+ var path = parts[1];
+ var constant = false;
+ if((path.charAt(0) == '"' || path.slice(-1) == "'") && path.charAt(0) == path.slice(-1)){
+ path = path.slice(1, -1);
+ constant = true;
+ }
+ return new ddtl.IncludeNode(path, constant, parser.getTemplate, parser.create_text_node());
+ },
+ ssi: function(parser, token){
+ // We're going to treat things a little differently here.
+ // First of all, this tag is *not* portable, so I'm not
+ // concerned about it being a "drop in" replacement.
+
+ // Instead, we'll just replicate the include tag, but with that
+ // optional "parsed" parameter.
+ var parts = token.contents.split();
+ var parsed = false;
+ if(parts.length == 3){
+ parsed = (parts.pop() == "parsed");
+ if(!parsed){
+ throw new Error("Second (optional) argument to ssi tag must be 'parsed'");
+ }
+ }
+ var node = ddtl.include(parser, new dd.Token(token.token_type, parts.join(" ")));
+ node.parsed = parsed;
+ return node;
+ }
+ });
+ return dojox.dtl.tag.loader;
+}); \ No newline at end of file
diff --git a/js/dojo/dojox/dtl/tag/logic.js b/js/dojo/dojox/dtl/tag/logic.js
new file mode 100644
index 0000000..3f84d25
--- /dev/null
+++ b/js/dojo/dojox/dtl/tag/logic.js
@@ -0,0 +1,281 @@
+//>>built
+define("dojox/dtl/tag/logic", [
+ "dojo/_base/lang",
+ "../_base"
+], function(lang, dd){
+ /*=====
+ dd = dojox.dtl;
+ =====*/
+ lang.getObject("dojox.dtl.tag.logic", true);
+
+ var ddt = dd.text;
+ var ddtl = dd.tag.logic;
+
+ ddtl.IfNode = lang.extend(function(bools, trues, falses, type){
+ this.bools = bools;
+ this.trues = trues;
+ this.falses = falses;
+ this.type = type;
+ },
+ {
+ render: function(context, buffer){
+ var i, bool, ifnot, filter, value;
+ if(this.type == "or"){
+ for(i = 0; bool = this.bools[i]; i++){
+ ifnot = bool[0];
+ filter = bool[1];
+ value = filter.resolve(context);
+ if((value && !ifnot) || (ifnot && !value)){
+ if(this.falses){
+ buffer = this.falses.unrender(context, buffer);
+ }
+ return (this.trues) ? this.trues.render(context, buffer, this) : buffer;
+ }
+ }
+ if(this.trues){
+ buffer = this.trues.unrender(context, buffer);
+ }
+ return (this.falses) ? this.falses.render(context, buffer, this) : buffer;
+ }else{
+ for(i = 0; bool = this.bools[i]; i++){
+ ifnot = bool[0];
+ filter = bool[1];
+ value = filter.resolve(context);
+ // If we ever encounter a false value
+ if(value == ifnot){
+ if(this.trues){
+ buffer = this.trues.unrender(context, buffer);
+ }
+ return (this.falses) ? this.falses.render(context, buffer, this) : buffer;
+ }
+ }
+ if(this.falses){
+ buffer = this.falses.unrender(context, buffer);
+ }
+ return (this.trues) ? this.trues.render(context, buffer, this) : buffer;
+ }
+ return buffer;
+ },
+ unrender: function(context, buffer){
+ buffer = (this.trues) ? this.trues.unrender(context, buffer) : buffer;
+ buffer = (this.falses) ? this.falses.unrender(context, buffer) : buffer;
+ return buffer;
+ },
+ clone: function(buffer){
+ var trues = (this.trues) ? this.trues.clone(buffer) : null;
+ var falses = (this.falses) ? this.falses.clone(buffer) : null;
+ return new this.constructor(this.bools, trues, falses, this.type);
+ }
+ });
+
+ ddtl.IfEqualNode = lang.extend(function(var1, var2, trues, falses, negate){
+ this.var1 = new dd._Filter(var1);
+ this.var2 = new dd._Filter(var2);
+ this.trues = trues;
+ this.falses = falses;
+ this.negate = negate;
+ },
+ {
+ render: function(context, buffer){
+ var var1 = this.var1.resolve(context);
+ var var2 = this.var2.resolve(context);
+ var1 = (typeof var1 != "undefined") ? var1 : "";
+ var2 = (typeof var1 != "undefined") ? var2 : "";
+ if((this.negate && var1 != var2) || (!this.negate && var1 == var2)){
+ if(this.falses){
+ buffer = this.falses.unrender(context, buffer, this);
+ }
+ return (this.trues) ? this.trues.render(context, buffer, this) : buffer;
+ }
+ if(this.trues){
+ buffer = this.trues.unrender(context, buffer, this);
+ }
+ return (this.falses) ? this.falses.render(context, buffer, this) : buffer;
+ },
+ unrender: function(context, buffer){
+ return ddtl.IfNode.prototype.unrender.call(this, context, buffer);
+ },
+ clone: function(buffer){
+ var trues = this.trues ? this.trues.clone(buffer) : null;
+ var falses = this.falses ? this.falses.clone(buffer) : null;
+ return new this.constructor(this.var1.getExpression(), this.var2.getExpression(), trues, falses, this.negate);
+ }
+ });
+
+ ddtl.ForNode = lang.extend(function(assign, loop, reversed, nodelist){
+ this.assign = assign;
+ this.loop = new dd._Filter(loop);
+ this.reversed = reversed;
+ this.nodelist = nodelist;
+ this.pool = [];
+ },
+ {
+ render: function(context, buffer){
+ var i, j, k;
+ var dirty = false;
+ var assign = this.assign;
+
+ for(k = 0; k < assign.length; k++){
+ if(typeof context[assign[k]] != "undefined"){
+ dirty = true;
+ context = context.push();
+ break;
+ }
+ }
+ if(!dirty && context.forloop){
+ dirty = true;
+ context = context.push();
+ }
+
+ var items = this.loop.resolve(context) || [];
+ for(i = items.length; i < this.pool.length; i++){
+ this.pool[i].unrender(context, buffer, this);
+ }
+ if(this.reversed){
+ items = items.slice(0).reverse();
+ }
+
+ var isObject = lang.isObject(items) && !lang.isArrayLike(items);
+ var arred = [];
+ if(isObject){
+ for(var key in items){
+ arred.push(items[key]);
+ }
+ }else{
+ arred = items;
+ }
+
+ var forloop = context.forloop = {
+ parentloop: context.get("forloop", {})
+ };
+ var j = 0;
+ for(i = 0; i < arred.length; i++){
+ var item = arred[i];
+
+ forloop.counter0 = j;
+ forloop.counter = j + 1;
+ forloop.revcounter0 = arred.length - j - 1;
+ forloop.revcounter = arred.length - j;
+ forloop.first = !j;
+ forloop.last = (j == arred.length - 1);
+
+ if(assign.length > 1 && lang.isArrayLike(item)){
+ if(!dirty){
+ dirty = true;
+ context = context.push();
+ }
+ var zipped = {};
+ for(k = 0; k < item.length && k < assign.length; k++){
+ zipped[assign[k]] = item[k];
+ }
+ lang.mixin(context, zipped);
+ }else{
+ context[assign[0]] = item;
+ }
+
+ if(j + 1 > this.pool.length){
+ this.pool.push(this.nodelist.clone(buffer));
+ }
+ buffer = this.pool[j++].render(context, buffer, this);
+ }
+
+ delete context.forloop;
+ if(dirty){
+ context = context.pop();
+ }else{
+ for(k = 0; k < assign.length; k++){
+ delete context[assign[k]];
+ }
+ }
+ 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.getExpression(), this.reversed, this.nodelist.clone(buffer));
+ }
+ });
+
+ lang.mixin(ddtl, {
+ if_: function(parser, token){
+ var i, part, type, bools = [], parts = token.contents.split();
+ parts.shift();
+ token = parts.join(" ");
+ parts = token.split(" and ");
+ if(parts.length == 1){
+ type = "or";
+ parts = token.split(" or ");
+ }else{
+ type = "and";
+ for(i = 0; i < parts.length; i++){
+ if(parts[i].indexOf(" or ") != -1){
+ // Note, since we split by and, this is the only place we need to error check
+ throw new Error("'if' tags can't mix 'and' and 'or'");
+ }
+ }
+ }
+ for(i = 0; part = parts[i]; i++){
+ var not = false;
+ if(part.indexOf("not ") == 0){
+ part = part.slice(4);
+ not = true;
+ }
+ bools.push([not, new dd._Filter(part)]);
+ }
+ var trues = parser.parse(["else", "endif"]);
+ var falses = false;
+ var token = parser.next_token();
+ if(token.contents == "else"){
+ falses = parser.parse(["endif"]);
+ parser.next_token();
+ }
+ return new ddtl.IfNode(bools, trues, falses, type);
+ },
+ _ifequal: function(parser, token, negate){
+ var parts = token.split_contents();
+ if(parts.length != 3){
+ throw new Error(parts[0] + " takes two arguments");
+ }
+ var end = 'end' + parts[0];
+ var trues = parser.parse(["else", end]);
+ var falses = false;
+ var token = parser.next_token();
+ if(token.contents == "else"){
+ falses = parser.parse([end]);
+ parser.next_token();
+ }
+ return new ddtl.IfEqualNode(parts[1], parts[2], trues, falses, negate);
+ },
+ ifequal: function(parser, token){
+ return ddtl._ifequal(parser, token);
+ },
+ ifnotequal: function(parser, token){
+ return ddtl._ifequal(parser, token, true);
+ },
+ for_: function(parser, token){
+ var parts = token.contents.split();
+ if(parts.length < 4){
+ throw new Error("'for' statements should have at least four words: " + token.contents);
+ }
+ var reversed = parts[parts.length - 1] == "reversed";
+ var index = (reversed) ? -3 : -2;
+ if(parts[parts.length + index] != "in"){
+ throw new Error("'for' tag received an invalid argument: " + token.contents);
+ }
+ var loopvars = parts.slice(1, index).join(" ").split(/ *, */);
+ for(var i = 0; i < loopvars.length; i++){
+ if(!loopvars[i] || loopvars[i].indexOf(" ") != -1){
+ throw new Error("'for' tag received an invalid argument: " + token.contents);
+ }
+ }
+ var nodelist = parser.parse(["endfor"]);
+ parser.next_token();
+ return new ddtl.ForNode(loopvars, parts[parts.length + index + 1], reversed, nodelist);
+ }
+ });
+ return dojox.dtl.tag.logic;
+}); \ No newline at end of file
diff --git a/js/dojo/dojox/dtl/tag/loop.js b/js/dojo/dojox/dtl/tag/loop.js
new file mode 100644
index 0000000..b8742ae
--- /dev/null
+++ b/js/dojo/dojox/dtl/tag/loop.js
@@ -0,0 +1,202 @@
+//>>built
+define("dojox/dtl/tag/loop", [
+ "dojo/_base/lang",
+ "dojo/_base/array",
+ "dojo/_base/json",
+ "../_base",
+ "dojox/string/tokenize"
+], function(lang,array,json,dd,Tokenize){
+ /*=====
+ Tokenize = dojox.string.tokenize;
+ dd = dojox.dtl;
+ =====*/
+ lang.getObject("dojox.dtl.tag.loop", true);
+
+ var ddtl = dd.tag.loop;
+
+ ddtl.CycleNode = lang.extend(function(cyclevars, name, text, shared){
+ this.cyclevars = cyclevars;
+ this.name = name;
+ this.contents = text;
+ this.shared = shared || {counter: -1, map: {}};
+ },
+ {
+ render: function(context, buffer){
+ if(context.forloop && !context.forloop.counter0){
+ this.shared.counter = -1;
+ }
+
+ ++this.shared.counter;
+ var value = this.cyclevars[this.shared.counter % this.cyclevars.length];
+
+ var map = this.shared.map;
+ if(!map[value]){
+ map[value] = new dd._Filter(value);
+ }
+ value = map[value].resolve(context, buffer);
+
+ if(this.name){
+ context[this.name] = value;
+ }
+ this.contents.set(value);
+ return this.contents.render(context, buffer);
+ },
+ unrender: function(context, buffer){
+ return this.contents.unrender(context, buffer);
+ },
+ clone: function(buffer){
+ return new this.constructor(this.cyclevars, this.name, this.contents.clone(buffer), this.shared);
+ }
+ });
+
+ ddtl.IfChangedNode = lang.extend(function(nodes, vars, shared){
+ this.nodes = nodes;
+ this._vars = vars;
+ this.shared = shared || {last: null, counter: 0};
+ this.vars = array.map(vars, function(item){
+ return new dojox.dtl._Filter(item);
+ });
+ }, {
+ render: function(context, buffer){
+ if(context.forloop){
+ if(context.forloop.counter <= this.shared.counter){
+ this.shared.last = null;
+ }
+ this.shared.counter = context.forloop.counter;
+ }
+
+ var change;
+ if(this.vars.length){
+ change = json.toJson(array.map(this.vars, function(item){
+ return item.resolve(context);
+ }));
+ }else{
+ change = this.nodes.dummyRender(context, buffer);
+ }
+
+ if(change != this.shared.last){
+ var firstloop = (this.shared.last === null);
+ this.shared.last = change;
+ context = context.push();
+ context.ifchanged = {firstloop: firstloop};
+ buffer = this.nodes.render(context, buffer);
+ context = context.pop();
+ }else{
+ buffer = this.nodes.unrender(context, buffer);
+ }
+ return buffer;
+ },
+ unrender: function(context, buffer){
+ return this.nodes.unrender(context, buffer);
+ },
+ clone: function(buffer){
+ return new this.constructor(this.nodes.clone(buffer), this._vars, this.shared);
+ }
+ });
+
+ ddtl.RegroupNode = lang.extend(function(expression, key, alias){
+ this._expression = expression;
+ this.expression = new dd._Filter(expression);
+ this.key = key;
+ this.alias = alias;
+ },
+ {
+ _push: function(container, grouper, stack){
+ if(stack.length){
+ container.push({ grouper: grouper, list: stack });
+ }
+ },
+ render: function(context, buffer){
+ context[this.alias] = [];
+ var list = this.expression.resolve(context);
+ if(list){
+ var last = null;
+ var stack = [];
+ for(var i = 0; i < list.length; i++){
+ var id = list[i][this.key];
+ if(last !== id){
+ this._push(context[this.alias], last, stack);
+ last = id;
+ stack = [list[i]];
+ }else{
+ stack.push(list[i]);
+ }
+ }
+ this._push(context[this.alias], last, stack);
+ }
+ return buffer;
+ },
+ unrender: function(context, buffer){
+ return buffer;
+ },
+ clone: function(context, buffer){
+ return this;
+ }
+ });
+
+ lang.mixin(ddtl, {
+ cycle: function(parser, token){
+ // summary: Cycle among the given strings each time this tag is encountered
+ var args = token.split_contents();
+
+ 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 ddtl.CycleNode(args.slice(1, args.length - 2), name, parser.create_text_node());
+
+ if(!parser._namedCycleNodes){
+ parser._namedCycleNodes = {};
+ }
+ parser._namedCycleNodes[name] = node;
+ }else{
+ node = new ddtl.CycleNode(args.slice(1), null, parser.create_text_node());
+ }
+
+ return node;
+ },
+ ifchanged: function(parser, token){
+ var parts = token.contents.split();
+ var nodes = parser.parse(["endifchanged"]);
+ parser.delete_first_token();
+ return new ddtl.IfChangedNode(nodes, parts.slice(1));
+ },
+ regroup: function(parser, token){
+ var tokens = Tokenize(token.contents, /(\s+)/g, function(spaces){
+ return spaces;
+ });
+ if(tokens.length < 11 || tokens[tokens.length - 3] != "as" || tokens[tokens.length - 7] != "by"){
+ throw new Error("Expected the format: regroup list by key as newList");
+ }
+ var expression = tokens.slice(2, -8).join("");
+ var key = tokens[tokens.length - 5];
+ var alias = tokens[tokens.length - 1];
+ return new ddtl.RegroupNode(expression, key, alias);
+ }
+ });
+ return dojox.dtl.tag.loop;
+}); \ No newline at end of file
diff --git a/js/dojo/dojox/dtl/tag/misc.js b/js/dojo/dojox/dtl/tag/misc.js
new file mode 100644
index 0000000..7570a36
--- /dev/null
+++ b/js/dojo/dojox/dtl/tag/misc.js
@@ -0,0 +1,294 @@
+//>>built
+define("dojox/dtl/tag/misc", [
+ "dojo/_base/lang",
+ "dojo/_base/array",
+ "dojo/_base/connect",
+ "../_base"
+], function(lang,array,connect,dd){
+ /*=====
+ dd = dojox.dtl;
+ =====*/
+ lang.getObject("dojox.dtl.tag.misc", true);
+
+ var ddtm = dd.tag.misc;
+
+ ddtm.DebugNode = lang.extend(function(text){
+ this.text = text;
+ },
+ {
+ render: function(context, buffer){
+ var keys = context.getKeys();
+ var debug = [];
+ var only = {};
+ for(var i = 0, key; key = keys[i]; i++){
+ only[key] = context[key];
+ debug += "[" + key + ": " + typeof context[key] + "]\n";
+ }
+ console.debug(only);
+ return this.text.set(debug).render(context, buffer, this);
+ },
+ unrender: function(context, buffer){
+ return buffer;
+ },
+ clone: function(buffer){
+ return new this.constructor(this.text.clone(buffer));
+ },
+ toString: function(){ return "ddtm.DebugNode"; }
+ });
+
+ ddtm.FilterNode = lang.extend(function(varnode, nodelist){
+ this._varnode = varnode;
+ this._nodelist = nodelist;
+ },
+ {
+ 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 = context.update({ "var": output.toString() });
+ var filtered = this._varnode.render(context, buffer);
+ context = context.pop();
+ return buffer;
+ },
+ unrender: function(context, buffer){
+ return buffer;
+ },
+ clone: function(buffer){
+ return new this.constructor(this._expression, this._nodelist.clone(buffer));
+ }
+ });
+
+ ddtm.FirstOfNode = lang.extend(function(vars, text){
+ this._vars = vars;
+ this.vars = array.map(vars, function(item){
+ return new dojox.dtl._Filter(item);
+ });
+ this.contents = text;
+ },
+ {
+ render: function(context, buffer){
+ for(var i = 0, item; item = this.vars[i]; i++){
+ var resolved = item.resolve(context);
+ if(typeof resolved != "undefined"){
+ if(resolved === null){
+ resolved = "null";
+ }
+ this.contents.set(resolved);
+ return this.contents.render(context, buffer);
+ }
+ }
+ return this.contents.unrender(context, buffer);
+ },
+ unrender: function(context, buffer){
+ return this.contents.unrender(context, buffer);
+ },
+ clone: function(buffer){
+ return new this.constructor(this._vars, this.contents.clone(buffer));
+ }
+ });
+
+ ddtm.SpacelessNode = lang.extend(function(nodelist, text){
+ this.nodelist = nodelist;
+ this.contents = text;
+ },
+ {
+ render: function(context, buffer){
+ if(buffer.getParent){
+ // Unfortunately, we have to branch here
+ var watch = [
+ connect.connect(buffer, "onAddNodeComplete", this, "_watch"),
+ connect.connect(buffer, "onSetParent", this, "_watchParent")
+ ];
+ buffer = this.nodelist.render(context, buffer);
+ connect.disconnect(watch[0]);
+ connect.disconnect(watch[1]);
+ }else{
+ var value = this.nodelist.dummyRender(context);
+ this.contents.set(value.replace(/>\s+</g, '><'));
+ buffer = this.contents.render(context, buffer);
+ }
+ return buffer;
+ },
+ unrender: function(context, buffer){
+ return this.nodelist.unrender(context, buffer);
+ },
+ clone: function(buffer){
+ return new this.constructor(this.nodelist.clone(buffer), this.contents.clone(buffer));
+ },
+ _isEmpty: function(node){
+ return (node.nodeType == 3 && !node.data.match(/[^\s\n]/));
+ },
+ _watch: function(node){
+ if(this._isEmpty(node)){
+ var remove = false;
+ if(node.parentNode.firstChild == node){
+ node.parentNode.removeChild(node);
+ }
+ }else{
+ var children = node.parentNode.childNodes;
+ if(node.nodeType == 1 && children.length > 2){
+ for(var i = 2, child; child = children[i]; i++){
+ if(children[i - 2].nodeType == 1 && this._isEmpty(children[i - 1])){
+ node.parentNode.removeChild(children[i - 1]);
+ return;
+ }
+ }
+ }
+ }
+ },
+ _watchParent: function(node){
+ var children = node.childNodes;
+ if(children.length){
+ while(node.childNodes.length){
+ var last = node.childNodes[node.childNodes.length - 1];
+ if(!this._isEmpty(last)){
+ return;
+ }
+ node.removeChild(last);
+ }
+ }
+ }
+ });
+
+ ddtm.TemplateTagNode = lang.extend(function(tag, text){
+ this.tag = tag;
+ this.contents = text;
+ },
+ {
+ mapping: {
+ openblock: "{%",
+ closeblock: "%}",
+ openvariable: "{{",
+ closevariable: "}}",
+ openbrace: "{",
+ closebrace: "}",
+ opencomment: "{#",
+ closecomment: "#}"
+ },
+ render: function(context, buffer){
+ this.contents.set(this.mapping[this.tag]);
+ return this.contents.render(context, buffer);
+ },
+ unrender: function(context, buffer){
+ return this.contents.unrender(context, buffer);
+ },
+ clone: function(buffer){
+ return new this.constructor(this.tag, this.contents.clone(buffer));
+ }
+ });
+
+ ddtm.WidthRatioNode = lang.extend(function(current, max, width, text){
+ this.current = new dd._Filter(current);
+ this.max = new dd._Filter(max);
+ this.width = width;
+ this.contents = text;
+ },
+ {
+ render: function(context, buffer){
+ var current = +this.current.resolve(context);
+ var max = +this.max.resolve(context);
+ if(typeof current != "number" || typeof max != "number" || !max){
+ this.contents.set("");
+ }else{
+ this.contents.set("" + Math.round((current / max) * this.width));
+ }
+ return this.contents.render(context, buffer);
+ },
+ unrender: function(context, buffer){
+ return this.contents.unrender(context, buffer);
+ },
+ clone: function(buffer){
+ return new this.constructor(this.current.getExpression(), this.max.getExpression(), this.width, this.contents.clone(buffer));
+ }
+ });
+
+ ddtm.WithNode = lang.extend(function(target, alias, nodelist){
+ this.target = new dd._Filter(target);
+ this.alias = alias;
+ this.nodelist = nodelist;
+ },
+ {
+ render: function(context, buffer){
+ var target = this.target.resolve(context);
+ context = context.push();
+ context[this.alias] = target;
+ buffer = this.nodelist.render(context, buffer);
+ context = context.pop();
+ return buffer;
+ },
+ unrender: function(context, buffer){
+ return buffer;
+ },
+ clone: function(buffer){
+ return new this.constructor(this.target.getExpression(), this.alias, this.nodelist.clone(buffer));
+ }
+ });
+
+ lang.mixin(ddtm, {
+ comment: function(parser, token){
+ // summary: Ignore everything between {% comment %} and {% endcomment %}
+ parser.skip_past("endcomment");
+ return dd._noOpNode;
+ },
+ debug: function(parser, token){
+ // summary: Output the current context, maybe add more stuff later.
+ return new ddtm.DebugNode(parser.create_text_node());
+ },
+ filter: function(parser, token){
+ // summary: Filter the contents of the blog through variable filters.
+ var rest = token.contents.split(null, 1)[1];
+ var varnode = parser.create_variable_node("var|" + rest);
+ var nodelist = parser.parse(["endfilter"]);
+ parser.next_token();
+ return new ddtm.FilterNode(varnode, nodelist);
+ },
+ firstof: function(parser, token){
+ var parts = token.split_contents().slice(1);
+ if(!parts.length){
+ throw new Error("'firstof' statement requires at least one argument");
+ }
+ return new ddtm.FirstOfNode(parts, parser.create_text_node());
+ },
+ spaceless: function(parser, token){
+ var nodelist = parser.parse(["endspaceless"]);
+ parser.delete_first_token();
+ return new ddtm.SpacelessNode(nodelist, parser.create_text_node());
+ },
+ templatetag: function(parser, token){
+ var parts = token.contents.split();
+ if(parts.length != 2){
+ throw new Error("'templatetag' statement takes one argument");
+ }
+ var tag = parts[1];
+ var mapping = ddtm.TemplateTagNode.prototype.mapping;
+ if(!mapping[tag]){
+ var keys = [];
+ for(var key in mapping){
+ keys.push(key);
+ }
+ throw new Error("Invalid templatetag argument: '" + tag + "'. Must be one of: " + keys.join(", "));
+ }
+ return new ddtm.TemplateTagNode(tag, parser.create_text_node());
+ },
+ widthratio: function(parser, token){
+ var parts = token.contents.split();
+ if(parts.length != 4){
+ throw new Error("widthratio takes three arguments");
+ }
+ var width = +parts[3];
+ if(typeof width != "number"){
+ throw new Error("widthratio final argument must be an integer");
+ }
+ return new ddtm.WidthRatioNode(parts[1], parts[2], width, parser.create_text_node());
+ },
+ with_: function(parser, token){
+ var parts = token.split_contents();
+ if(parts.length != 4 || parts[2] != "as"){
+ throw new Error("do_width expected format as 'with value as name'");
+ }
+ var nodelist = parser.parse(["endwith"]);
+ parser.next_token();
+ return new ddtm.WithNode(parts[1], parts[3], nodelist);
+ }
+ });
+ return dojox.dtl.tag.misc;
+}); \ No newline at end of file
diff --git a/js/dojo/dojox/dtl/utils/date.js b/js/dojo/dojox/dtl/utils/date.js
new file mode 100644
index 0000000..1d7b3dd
--- /dev/null
+++ b/js/dojo/dojox/dtl/utils/date.js
@@ -0,0 +1,80 @@
+//>>built
+define("dojox/dtl/utils/date", [
+ "dojo/_base/lang",
+ "dojox/date/php",
+ "../_base"
+], function(lang,ddp,dd){
+ /*=====
+ ddp = dojox.data.php;
+ dd = dojox.dtl;
+ =====*/
+ lang.getObject("dojox.dtl.utils.date", true);
+
+ dd.utils.date.DateFormat = ddp.DateFormat;
+ lang.extend(dd.utils.date.DateFormat, ddp.DateFormat.prototype, {
+ 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.
+ return (!this.date.getMinutes()) ? this.g() : this.g() + ":" + this.i();
+ },
+ 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 this.f() + " " + this.a();
+ }
+ });
+
+ lang.mixin(dojox.dtl.utils.date, {
+ format: function(/*Date*/ date, /*String*/ format){
+ var df = new dojox.dtl.utils.date.DateFormat(format);
+ return df.format(date);
+ },
+ 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."]
+ });
+ return dojox.dtl.utils.date;
+});