1 | define([ |
---|
2 | "dojo/aspect", |
---|
3 | "dojo/_base/declare", |
---|
4 | "./_base", |
---|
5 | "dijit/_TemplatedMixin", |
---|
6 | "dojo/dom-construct", |
---|
7 | "dojo/cache", |
---|
8 | "dojo/_base/array", |
---|
9 | "dojo/string", |
---|
10 | "dojo/parser" |
---|
11 | ], function(aspect,declare,dd,TemplatedMixin, domConstruct,Cache,Array,dString,Parser){ |
---|
12 | |
---|
13 | return declare("dojox.dtl._Templated", TemplatedMixin, { |
---|
14 | // summary: |
---|
15 | // The base-class for DTL-templated widgets. |
---|
16 | |
---|
17 | _dijitTemplateCompat: false, |
---|
18 | |
---|
19 | buildRendering: function(){ |
---|
20 | var node; |
---|
21 | |
---|
22 | if(this.domNode && !this._template){ |
---|
23 | return; |
---|
24 | } |
---|
25 | |
---|
26 | if(!this._template){ |
---|
27 | var t = this.getCachedTemplate( |
---|
28 | this.templatePath, |
---|
29 | this.templateString, |
---|
30 | this._skipNodeCache |
---|
31 | ); |
---|
32 | if(t instanceof dd.Template) { |
---|
33 | this._template = t; |
---|
34 | }else{ |
---|
35 | node = t.cloneNode(true); |
---|
36 | } |
---|
37 | } |
---|
38 | if(!node){ |
---|
39 | var context = new dd._Context(this); |
---|
40 | if(!this._created){ |
---|
41 | delete context._getter; |
---|
42 | } |
---|
43 | var nodes = domConstruct.toDom( |
---|
44 | this._template.render(context) |
---|
45 | ); |
---|
46 | // TODO: is it really necessary to look for the first node? |
---|
47 | if(nodes.nodeType !== 1 && nodes.nodeType !== 3){ |
---|
48 | // nodes.nodeType === 11 |
---|
49 | // the node is a document fragment |
---|
50 | for(var i = 0, l = nodes.childNodes.length; i < l; ++i){ |
---|
51 | node = nodes.childNodes[i]; |
---|
52 | if(node.nodeType == 1){ |
---|
53 | break; |
---|
54 | } |
---|
55 | } |
---|
56 | }else{ |
---|
57 | // the node is an element or a text |
---|
58 | node = nodes; |
---|
59 | } |
---|
60 | } |
---|
61 | this._attachTemplateNodes(node); |
---|
62 | if(this.widgetsInTemplate){ |
---|
63 | //Make sure dojoType is used for parsing widgets in template. |
---|
64 | //The Parser.query could be changed from multiversion support. |
---|
65 | var parser = Parser, qry, attr; |
---|
66 | if(parser._query != "[dojoType]"){ |
---|
67 | qry = parser._query; |
---|
68 | attr = parser._attrName; |
---|
69 | parser._query = "[dojoType]"; |
---|
70 | parser._attrName = "dojoType"; |
---|
71 | } |
---|
72 | |
---|
73 | //Store widgets that we need to start at a later point in time |
---|
74 | var cw = (this._startupWidgets = Parser.parse(node, { |
---|
75 | noStart: !this._earlyTemplatedStartup, |
---|
76 | inherited: {dir: this.dir, lang: this.lang} |
---|
77 | })); |
---|
78 | |
---|
79 | //Restore the query. |
---|
80 | if(qry){ |
---|
81 | parser._query = qry; |
---|
82 | parser._attrName = attr; |
---|
83 | } |
---|
84 | |
---|
85 | // Hook up attach points and events for nodes that were converted to widgets |
---|
86 | for(var i = 0; i < cw.length; i++){ |
---|
87 | this._processTemplateNode(cw[i], function(n,p){ |
---|
88 | return n[p]; |
---|
89 | }, function(widget, type, callback){ |
---|
90 | // function to do data-dojo-attach-event to a widget |
---|
91 | if(type in widget){ |
---|
92 | // back-compat, remove for 2.0 |
---|
93 | return aspect.after(widget, type, callback, true); |
---|
94 | }else{ |
---|
95 | // 1.x may never hit this branch, but it's the default for 2.0 |
---|
96 | return widget.on(type, callback, true); |
---|
97 | } |
---|
98 | }); |
---|
99 | } |
---|
100 | } |
---|
101 | |
---|
102 | if(this.domNode){ |
---|
103 | domConstruct.place(node, this.domNode, "before"); |
---|
104 | this.destroyDescendants(); |
---|
105 | domConstruct.destroy(this.domNode); |
---|
106 | } |
---|
107 | this.domNode = node; |
---|
108 | |
---|
109 | this._fillContent(this.srcNodeRef); |
---|
110 | }, |
---|
111 | |
---|
112 | _processTemplateNode: function(/*DOMNode|Widget*/ baseNode, getAttrFunc, attachFunc){ |
---|
113 | // Override _AttachMixin._processNode to skip nodes with data-dojo-type set. They are handled separately |
---|
114 | // in the buildRendering() code above. |
---|
115 | |
---|
116 | if(this.widgetsInTemplate && (getAttrFunc(baseNode, "dojoType") || getAttrFunc(baseNode, "data-dojo-type"))){ |
---|
117 | return true; |
---|
118 | } |
---|
119 | |
---|
120 | this.inherited(arguments); |
---|
121 | }, |
---|
122 | |
---|
123 | _templateCache: {}, |
---|
124 | getCachedTemplate: function(templatePath, templateString, alwaysUseString){ |
---|
125 | // summary: |
---|
126 | // Layer for dijit._Templated.getCachedTemplate |
---|
127 | var tmplts = this._templateCache; |
---|
128 | var key = templateString || templatePath; |
---|
129 | if(tmplts[key]){ |
---|
130 | return tmplts[key]; |
---|
131 | } |
---|
132 | |
---|
133 | templateString = dString.trim(templateString || Cache(templatePath, {sanitize: true})); |
---|
134 | |
---|
135 | if( this._dijitTemplateCompat && |
---|
136 | (alwaysUseString || templateString.match(/\$\{([^\}]+)\}/g)) |
---|
137 | ){ |
---|
138 | templateString = this._stringRepl(templateString); |
---|
139 | } |
---|
140 | |
---|
141 | // If we always use a string, or find no variables, just store it as a node |
---|
142 | if(alwaysUseString || !templateString.match(/\{[{%]([^\}]+)[%}]\}/g)){ |
---|
143 | return tmplts[key] = domConstruct.toDom(templateString); |
---|
144 | }else{ |
---|
145 | return tmplts[key] = new dd.Template(templateString); |
---|
146 | } |
---|
147 | }, |
---|
148 | render: function(){ |
---|
149 | // summary: |
---|
150 | // Renders the widget. |
---|
151 | this.buildRendering(); |
---|
152 | }, |
---|
153 | startup: function(){ |
---|
154 | Array.forEach(this._startupWidgets, function(w){ |
---|
155 | if(w && !w._started && w.startup){ |
---|
156 | w.startup(); |
---|
157 | } |
---|
158 | }); |
---|
159 | this.inherited(arguments); |
---|
160 | } |
---|
161 | }); |
---|
162 | }); |
---|