summaryrefslogtreecommitdiff
path: root/includes/js/dojo/parser.js
diff options
context:
space:
mode:
Diffstat (limited to 'includes/js/dojo/parser.js')
-rw-r--r--includes/js/dojo/parser.js277
1 files changed, 277 insertions, 0 deletions
diff --git a/includes/js/dojo/parser.js b/includes/js/dojo/parser.js
new file mode 100644
index 0000000..5394338
--- /dev/null
+++ b/includes/js/dojo/parser.js
@@ -0,0 +1,277 @@
+if(!dojo._hasResource["dojo.parser"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojo.parser"] = true;
+dojo.provide("dojo.parser");
+dojo.require("dojo.date.stamp");
+
+dojo.parser = new function(){
+ // summary: The Dom/Widget parsing package
+
+ var d = dojo;
+ var dtName = d._scopeName + "Type";
+ var qry = "[" + dtName + "]";
+
+ function val2type(/*Object*/ value){
+ // summary:
+ // Returns name of type of given value.
+
+ if(d.isString(value)){ return "string"; }
+ if(typeof value == "number"){ return "number"; }
+ if(typeof value == "boolean"){ return "boolean"; }
+ if(d.isFunction(value)){ return "function"; }
+ if(d.isArray(value)){ return "array"; } // typeof [] == "object"
+ if(value instanceof Date) { return "date"; } // assume timestamp
+ if(value instanceof d._Url){ return "url"; }
+ return "object";
+ }
+
+ function str2obj(/*String*/ value, /*String*/ type){
+ // summary:
+ // Convert given string value to given type
+ switch(type){
+ case "string":
+ return value;
+ case "number":
+ return value.length ? Number(value) : NaN;
+ case "boolean":
+ // for checked/disabled value might be "" or "checked". interpret as true.
+ return typeof value == "boolean" ? value : !(value.toLowerCase()=="false");
+ case "function":
+ if(d.isFunction(value)){
+ // IE gives us a function, even when we say something like onClick="foo"
+ // (in which case it gives us an invalid function "function(){ foo }").
+ // Therefore, convert to string
+ value=value.toString();
+ value=d.trim(value.substring(value.indexOf('{')+1, value.length-1));
+ }
+ try{
+ if(value.search(/[^\w\.]+/i) != -1){
+ // TODO: "this" here won't work
+ value = d.parser._nameAnonFunc(new Function(value), this);
+ }
+ return d.getObject(value, false);
+ }catch(e){ return new Function(); }
+ case "array":
+ return value.split(/\s*,\s*/);
+ case "date":
+ switch(value){
+ case "": return new Date(""); // the NaN of dates
+ case "now": return new Date(); // current date
+ default: return d.date.stamp.fromISOString(value);
+ }
+ case "url":
+ return d.baseUrl + value;
+ default:
+ return d.fromJson(value);
+ }
+ }
+
+ var instanceClasses = {
+ // map from fully qualified name (like "dijit.Button") to structure like
+ // { cls: dijit.Button, params: {label: "string", disabled: "boolean"} }
+ };
+
+ function getClassInfo(/*String*/ className){
+ // className:
+ // fully qualified name (like "dijit.Button")
+ // returns:
+ // structure like
+ // {
+ // cls: dijit.Button,
+ // params: { label: "string", disabled: "boolean"}
+ // }
+
+ if(!instanceClasses[className]){
+ // get pointer to widget class
+ var cls = d.getObject(className);
+ if(!d.isFunction(cls)){
+ throw new Error("Could not load class '" + className +
+ "'. Did you spell the name correctly and use a full path, like 'dijit.form.Button'?");
+ }
+ var proto = cls.prototype;
+
+ // get table of parameter names & types
+ var params={};
+ for(var name in proto){
+ if(name.charAt(0)=="_"){ continue; } // skip internal properties
+ var defVal = proto[name];
+ params[name]=val2type(defVal);
+ }
+
+ instanceClasses[className] = { cls: cls, params: params };
+ }
+ return instanceClasses[className];
+ }
+
+ this._functionFromScript = function(script){
+ var preamble = "";
+ var suffix = "";
+ var argsStr = script.getAttribute("args");
+ if(argsStr){
+ d.forEach(argsStr.split(/\s*,\s*/), function(part, idx){
+ preamble += "var "+part+" = arguments["+idx+"]; ";
+ });
+ }
+ var withStr = script.getAttribute("with");
+ if(withStr && withStr.length){
+ d.forEach(withStr.split(/\s*,\s*/), function(part){
+ preamble += "with("+part+"){";
+ suffix += "}";
+ });
+ }
+ return new Function(preamble+script.innerHTML+suffix);
+ }
+
+ this.instantiate = function(/* Array */nodes){
+ // summary:
+ // Takes array of nodes, and turns them into class instances and
+ // potentially calls a layout method to allow them to connect with
+ // any children
+ var thelist = [];
+ d.forEach(nodes, function(node){
+ if(!node){ return; }
+ var type = node.getAttribute(dtName);
+ if((!type)||(!type.length)){ return; }
+ var clsInfo = getClassInfo(type);
+ var clazz = clsInfo.cls;
+ var ps = clazz._noScript||clazz.prototype._noScript;
+
+ // read parameters (ie, attributes).
+ // clsInfo.params lists expected params like {"checked": "boolean", "n": "number"}
+ var params = {};
+ var attributes = node.attributes;
+ for(var name in clsInfo.params){
+ var item = attributes.getNamedItem(name);
+ if(!item || (!item.specified && (!dojo.isIE || name.toLowerCase()!="value"))){ continue; }
+ var value = item.value;
+ // Deal with IE quirks for 'class' and 'style'
+ switch(name){
+ case "class":
+ value = node.className;
+ break;
+ case "style":
+ value = node.style && node.style.cssText; // FIXME: Opera?
+ }
+ var _type = clsInfo.params[name];
+ params[name] = str2obj(value, _type);
+ }
+
+ // Process <script type="dojo/*"> script tags
+ // <script type="dojo/method" event="foo"> tags are added to params, and passed to
+ // the widget on instantiation.
+ // <script type="dojo/method"> tags (with no event) are executed after instantiation
+ // <script type="dojo/connect" event="foo"> tags are dojo.connected after instantiation
+ // note: dojo/* script tags cannot exist in self closing widgets, like <input />
+ if(!ps){
+ var connects = [], // functions to connect after instantiation
+ calls = []; // functions to call after instantiation
+
+ d.query("> script[type^='dojo/']", node).orphan().forEach(function(script){
+ var event = script.getAttribute("event"),
+ type = script.getAttribute("type"),
+ nf = d.parser._functionFromScript(script);
+ if(event){
+ if(type == "dojo/connect"){
+ connects.push({event: event, func: nf});
+ }else{
+ params[event] = nf;
+ }
+ }else{
+ calls.push(nf);
+ }
+ });
+ }
+
+ var markupFactory = clazz["markupFactory"];
+ if(!markupFactory && clazz["prototype"]){
+ markupFactory = clazz.prototype["markupFactory"];
+ }
+ // create the instance
+ var instance = markupFactory ? markupFactory(params, node, clazz) : new clazz(params, node);
+ thelist.push(instance);
+
+ // map it to the JS namespace if that makes sense
+ var jsname = node.getAttribute("jsId");
+ if(jsname){
+ d.setObject(jsname, instance);
+ }
+
+ // process connections and startup functions
+ if(!ps){
+ d.forEach(connects, function(connect){
+ d.connect(instance, connect.event, null, connect.func);
+ });
+ d.forEach(calls, function(func){
+ func.call(instance);
+ });
+ }
+ });
+
+ // Call startup on each top level instance if it makes sense (as for
+ // widgets). Parent widgets will recursively call startup on their
+ // (non-top level) children
+ d.forEach(thelist, function(instance){
+ if( instance &&
+ instance.startup &&
+ !instance._started &&
+ (!instance.getParent || !instance.getParent())
+ ){
+ instance.startup();
+ }
+ });
+ return thelist;
+ };
+
+ this.parse = function(/*DomNode?*/ rootNode){
+ // summary:
+ // Search specified node (or root node) recursively for class instances,
+ // and instantiate them Searches for
+ // dojoType="qualified.class.name"
+ var list = d.query(qry, rootNode);
+ // go build the object instances
+ var instances = this.instantiate(list);
+ return instances;
+ };
+}();
+
+//Register the parser callback. It should be the first callback
+//after the a11y test.
+
+(function(){
+ var parseRunner = function(){
+ if(dojo.config["parseOnLoad"] == true){
+ dojo.parser.parse();
+ }
+ };
+
+ // FIXME: need to clobber cross-dependency!!
+ if(dojo.exists("dijit.wai.onload") && (dijit.wai.onload === dojo._loaders[0])){
+ dojo._loaders.splice(1, 0, parseRunner);
+ }else{
+ dojo._loaders.unshift(parseRunner);
+ }
+})();
+
+//TODO: ported from 0.4.x Dojo. Can we reduce this?
+dojo.parser._anonCtr = 0;
+dojo.parser._anon = {}; // why is this property required?
+dojo.parser._nameAnonFunc = function(/*Function*/anonFuncPtr, /*Object*/thisObj){
+ // summary:
+ // Creates a reference to anonFuncPtr in thisObj with a completely
+ // unique name. The new name is returned as a String.
+ var jpn = "$joinpoint";
+ var nso = (thisObj|| dojo.parser._anon);
+ if(dojo.isIE){
+ var cn = anonFuncPtr["__dojoNameCache"];
+ if(cn && nso[cn] === anonFuncPtr){
+ return anonFuncPtr["__dojoNameCache"];
+ }
+ }
+ var ret = "__"+dojo.parser._anonCtr++;
+ while(typeof nso[ret] != "undefined"){
+ ret = "__"+dojo.parser._anonCtr++;
+ }
+ nso[ret] = anonFuncPtr;
+ return ret; // String
+}
+
+}