Blame | Last modification | View Log | RSS feed
if(!dojo._hasResource["dijit._Templated"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.dojo._hasResource["dijit._Templated"] = true;dojo.provide("dijit._Templated");dojo.require("dijit._Widget");dojo.require("dojo.string");dojo.require("dojo.parser");dojo.declare("dijit._Templated",null,{// summary:// mixin for widgets that are instantiated from a template// templateNode: DomNode// a node that represents the widget template. Pre-empts both templateString and templatePath.templateNode: null,// templateString String:// a string that represents the widget template. Pre-empts the// templatePath. In builds that have their strings "interned", the// templatePath is converted to an inline templateString, thereby// preventing a synchronous network call.templateString: null,// templatePath: String// Path to template (HTML file) for this widgettemplatePath: null,// widgetsInTemplate Boolean:// should we parse the template to find widgets that might be// declared in markup inside it? false by default.widgetsInTemplate: false,// containerNode DomNode:// holds child elements. "containerNode" is generally set via a// dojoAttachPoint assignment and it designates where children of// the src dom node will be placedcontainerNode: null,// skipNodeCache Boolean:// if using a cached widget template node poses issues for a// particular widget class, it can set this property to ensure// that its template is always re-built from a string_skipNodeCache: false,// method over-ridebuildRendering: function(){// summary:// Construct the UI for this widget from a template, setting this.domNode.// Lookup cached version of template, and download to cache if it// isn't there already. Returns either a DomNode or a string, depending on// whether or not the template contains ${foo} replacement parameters.var cached = dijit._Templated.getCachedTemplate(this.templatePath, this.templateString, this._skipNodeCache);var node;if(dojo.isString(cached)){var className = this.declaredClass, _this = this;// Cache contains a string because we need to do property replacement// do the property replacementvar tstr = dojo.string.substitute(cached, this, function(value, key){if(key.charAt(0) == '!'){ value = _this[key.substr(1)]; }if(typeof value == "undefined"){ throw new Error(className+" template:"+key); } // a debugging aideif(!value){ return ""; }// Substitution keys beginning with ! will skip the transform step,// in case a user wishes to insert unescaped markup, e.g. ${!foo}return key.charAt(0) == "!" ? value :// Safer substitution, see heading "Attribute values" in// http://www.w3.org/TR/REC-html40/appendix/notes.html#h-B.3.2value.toString().replace(/"/g,"""); //TODO: add &? use encodeXML method?}, this);node = dijit._Templated._createNodesFromText(tstr)[0];}else{// if it's a node, all we have to do is clone itnode = cached.cloneNode(true);}// recurse through the node, looking for, and attaching to, our// attachment points which should be defined on the template node.this._attachTemplateNodes(node);var source = this.srcNodeRef;if(source && source.parentNode){source.parentNode.replaceChild(node, source);}this.domNode = node;if(this.widgetsInTemplate){var childWidgets = dojo.parser.parse(node);this._attachTemplateNodes(childWidgets, function(n,p){return n[p];});}this._fillContent(source);},_fillContent: function(/*DomNode*/ source){// summary:// relocate source contents to templated container node// this.containerNode must be able to receive children, or exceptions will be thrownvar dest = this.containerNode;if(source && dest){while(source.hasChildNodes()){dest.appendChild(source.firstChild);}}},_attachTemplateNodes: function(rootNode, getAttrFunc){// summary:// map widget properties and functions to the handlers specified in// the dom node and it's descendants. This function iterates over all// nodes and looks for these properties:// * dojoAttachPoint// * dojoAttachEvent// * waiRole// * waiState// rootNode: DomNode|Array[Widgets]// the node to search for properties. All children will be searched.// getAttrFunc: function?// a function which will be used to obtain property for a given// DomNode/WidgetgetAttrFunc = getAttrFunc || function(n,p){ return n.getAttribute(p); };var nodes = dojo.isArray(rootNode) ? rootNode : (rootNode.all || rootNode.getElementsByTagName("*"));var x=dojo.isArray(rootNode)?0:-1;for(; x<nodes.length; x++){var baseNode = (x == -1) ? rootNode : nodes[x];if(this.widgetsInTemplate && getAttrFunc(baseNode,'dojoType')){continue;}// Process dojoAttachPointvar attachPoint = getAttrFunc(baseNode, "dojoAttachPoint");if(attachPoint){var point, points = attachPoint.split(/\s*,\s*/);while(point=points.shift()){if(dojo.isArray(this[point])){this[point].push(baseNode);}else{this[point]=baseNode;}}}// Process dojoAttachEventvar attachEvent = getAttrFunc(baseNode, "dojoAttachEvent");if(attachEvent){// NOTE: we want to support attributes that have the form// "domEvent: nativeEvent; ..."var event, events = attachEvent.split(/\s*,\s*/);var trim = dojo.trim;while(event=events.shift()){if(event){var thisFunc = null;if(event.indexOf(":") != -1){// oh, if only JS had tuple assignmentvar funcNameArr = event.split(":");event = trim(funcNameArr[0]);thisFunc = trim(funcNameArr[1]);}else{event = trim(event);}if(!thisFunc){thisFunc = event;}this.connect(baseNode, event, thisFunc);}}}// waiRole, waiStatevar role = getAttrFunc(baseNode, "waiRole");if(role){dijit.setWaiRole(baseNode, role);}var values = getAttrFunc(baseNode, "waiState");if(values){dojo.forEach(values.split(/\s*,\s*/), function(stateValue){if(stateValue.indexOf('-') != -1){var pair = stateValue.split('-');dijit.setWaiState(baseNode, pair[0], pair[1]);}});}}}});// key is either templatePath or templateString; object is either string or DOM treedijit._Templated._templateCache = {};dijit._Templated.getCachedTemplate = function(templatePath, templateString, alwaysUseString){// summary:// static method to get a template based on the templatePath or// templateString key// templatePath: String// the URL to get the template from. dojo.uri.Uri is often passed as well.// templateString: String?// a string to use in lieu of fetching the template from a URL// Returns:// Either string (if there are ${} variables that need to be replaced) or just// a DOM tree (if the node can be cloned directly)// is it already cached?var tmplts = dijit._Templated._templateCache;var key = templateString || templatePath;var cached = tmplts[key];if(cached){return cached;}// If necessary, load template string from template pathif(!templateString){templateString = dijit._Templated._sanitizeTemplateString(dojo._getText(templatePath));}templateString = dojo.string.trim(templateString);if(templateString.match(/\$\{([^\}]+)\}/g) || alwaysUseString){// there are variables in the template so all we can do is cache the stringreturn (tmplts[key] = templateString); //String}else{// there are no variables in the template so we can cache the DOM treereturn (tmplts[key] = dijit._Templated._createNodesFromText(templateString)[0]); //Node}};dijit._Templated._sanitizeTemplateString = function(/*String*/tString){// summary:// Strips <?xml ...?> declarations so that external SVG and XML// documents can be added to a document without worry. Also, if the string// is an HTML document, only the part inside the body tag is returned.if(tString){tString = tString.replace(/^\s*<\?xml(\s)+version=[\'\"](\d)*.(\d)*[\'\"](\s)*\?>/im, "");var matches = tString.match(/<body[^>]*>\s*([\s\S]+)\s*<\/body>/im);if(matches){tString = matches[1];}}else{tString = "";}return tString; //String};if(dojo.isIE){dojo.addOnUnload(function(){var cache = dijit._Templated._templateCache;for(var key in cache){var value = cache[key];if(!isNaN(value.nodeType)){ // isNode equivalentdojo._destroyElement(value);}delete cache[key];}});}(function(){var tagMap = {cell: {re: /^<t[dh][\s\r\n>]/i, pre: "<table><tbody><tr>", post: "</tr></tbody></table>"},row: {re: /^<tr[\s\r\n>]/i, pre: "<table><tbody>", post: "</tbody></table>"},section: {re: /^<(thead|tbody|tfoot)[\s\r\n>]/i, pre: "<table>", post: "</table>"}};// dummy container node used temporarily to hold nodes being createdvar tn;dijit._Templated._createNodesFromText = function(/*String*/text){// summary:// Attempts to create a set of nodes based on the structure of the passed text.if(!tn){tn = dojo.doc.createElement("div");tn.style.display="none";dojo.body().appendChild(tn);}var tableType = "none";var rtext = text.replace(/^\s+/, "");for(var type in tagMap){var map = tagMap[type];if(map.re.test(rtext)){tableType = type;text = map.pre + text + map.post;break;}}tn.innerHTML = text;if(tn.normalize){tn.normalize();}var tag = { cell: "tr", row: "tbody", section: "table" }[tableType];var _parent = (typeof tag != "undefined") ?tn.getElementsByTagName(tag)[0] :tn;var nodes = [];while(_parent.firstChild){nodes.push(_parent.removeChild(_parent.firstChild));}tn.innerHTML="";return nodes; // Array}})();// These arguments can be specified for widgets which are used in templates.// Since any widget can be specified as sub widgets in template, mix it// into the base widget class. (This is a hack, but it's effective.)dojo.extend(dijit._Widget,{dojoAttachEvent: "",dojoAttachPoint: "",waiRole: "",waiState:""})}