summaryrefslogtreecommitdiff
path: root/includes/js/dijit/_Templated.js
diff options
context:
space:
mode:
Diffstat (limited to 'includes/js/dijit/_Templated.js')
-rw-r--r--includes/js/dijit/_Templated.js329
1 files changed, 329 insertions, 0 deletions
diff --git a/includes/js/dijit/_Templated.js b/includes/js/dijit/_Templated.js
new file mode 100644
index 0000000..2de10e1
--- /dev/null
+++ b/includes/js/dijit/_Templated.js
@@ -0,0 +1,329 @@
+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 widget relative to dojo.baseUrl
+ templatePath: 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 placed
+ containerNode: 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,
+
+ _stringRepl: function(tmpl){
+ var className = this.declaredClass, _this = this;
+ // Cache contains a string because we need to do property replacement
+ // do the property replacement
+ return dojo.string.substitute(tmpl, 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 aide
+ if(!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.2
+ value.toString().replace(/"/g,"""); //TODO: add &amp? use encodeXML method?
+ }, this);
+ },
+
+ // method over-ride
+ buildRendering: 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)){
+ node = dijit._Templated._createNodesFromText(this._stringRepl(cached))[0];
+ }else{
+ // if it's a node, all we have to do is clone it
+ node = 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 cw = this._supportingWidgets = dojo.parser.parse(node);
+ this._attachTemplateNodes(cw, 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 thrown
+ var dest = this.containerNode;
+ if(source && dest){
+ while(source.hasChildNodes()){
+ dest.appendChild(source.firstChild);
+ }
+ }
+ },
+
+ _attachTemplateNodes: function(rootNode, getAttrFunc){
+ // summary: Iterate through the template and attach functions and nodes accordingly.
+ // description:
+ // 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/Widget
+
+ getAttrFunc = 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 dojoAttachPoint
+ var 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 dojoAttachEvent
+ var 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 assignment
+ var 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, waiState
+ var 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 tree
+dijit._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. Takes precedence
+ // over templatePath
+ // Returns: Mixed
+ // 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 path
+ if(!templateString){
+ templateString = dijit._Templated._sanitizeTemplateString(dojo._getText(templatePath));
+ }
+
+ templateString = dojo.string.trim(templateString);
+
+ if(alwaysUseString || templateString.match(/\$\{([^\}]+)\}/g)){
+ // there are variables in the template so all we can do is cache the string
+ return (tmplts[key] = templateString); //String
+ }else{
+ // there are no variables in the template so we can cache the DOM tree
+ return (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 equivalent
+ dojo._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 created
+ var 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:""
+})
+
+}