]> git.wh0rd.org - tt-rss.git/blobdiff - lib/dojo/parser.js.uncompressed.js
update dojo to 1.7.3
[tt-rss.git] / lib / dojo / parser.js.uncompressed.js
diff --git a/lib/dojo/parser.js.uncompressed.js b/lib/dojo/parser.js.uncompressed.js
new file mode 100644 (file)
index 0000000..6d340fc
--- /dev/null
@@ -0,0 +1,594 @@
+define(
+       "dojo/parser", ["./_base/kernel", "./_base/lang", "./_base/array", "./_base/html", "./_base/window", "./_base/url",
+               "./_base/json", "./aspect", "./date/stamp", "./query", "./on", "./ready"],
+       function(dojo, dlang, darray, dhtml, dwindow, _Url, djson, aspect, dates, query, don){
+
+// module:
+//             dojo/parser
+// summary:
+//             The Dom/Widget parsing package
+
+new Date("X"); // workaround for #11279, new Date("") == NaN
+
+var features = {
+       // Feature detection for when node.attributes only lists the attributes specified in the markup
+       // rather than old IE/quirks behavior where it lists every default value too
+       "dom-attributes-explicit": document.createElement("div").attributes.length < 40
+};
+function has(feature){
+       return features[feature];
+}
+
+
+dojo.parser = new function(){
+       // summary:
+       //              The Dom/Widget parsing package
+
+       var _nameMap = {
+               // Map from widget name (ex: "dijit.form.Button") to structure mapping
+               // lowercase version of attribute names to the version in the widget ex:
+               //      {
+               //              label: "label",
+               //              onclick: "onClick"
+               //      }
+       };
+       function getNameMap(proto){
+               // summary:
+               //              Returns map from lowercase name to attribute name in class, ex: {onclick: "onClick"}
+               var map = {};
+               for(var name in proto){
+                       if(name.charAt(0)=="_"){ continue; }    // skip internal properties
+                       map[name.toLowerCase()] = name;
+               }
+               return map;
+       }
+       // Widgets like BorderContainer add properties to _Widget via dojo.extend().
+       // If BorderContainer is loaded after _Widget's parameter list has been cached,
+       // we need to refresh that parameter list (for _Widget and all widgets that extend _Widget).
+       aspect.after(dlang, "extend", function(){
+               _nameMap = {};
+       }, true);
+
+       // Map from widget name (ex: "dijit.form.Button") to constructor
+       var _ctorMap = {};
+
+       this._functionFromScript = function(script, attrData){
+               // summary:
+               //              Convert a <script type="dojo/method" args="a, b, c"> ... </script>
+               //              into a function
+               // script: DOMNode
+               //              The <script> DOMNode
+               // attrData: String
+               //              For HTML5 compliance, searches for attrData + "args" (typically
+               //              "data-dojo-args") instead of "args"
+               var preamble = "";
+               var suffix = "";
+               var argsStr = (script.getAttribute(attrData + "args") || script.getAttribute("args"));
+               if(argsStr){
+                       darray.forEach(argsStr.split(/\s*,\s*/), function(part, idx){
+                               preamble += "var "+part+" = arguments["+idx+"]; ";
+                       });
+               }
+               var withStr = script.getAttribute("with");
+               if(withStr && withStr.length){
+                       darray.forEach(withStr.split(/\s*,\s*/), function(part){
+                               preamble += "with("+part+"){";
+                               suffix += "}";
+                       });
+               }
+               return new Function(preamble+script.innerHTML+suffix);
+       };
+
+       this.instantiate = /*====== dojo.parser.instantiate= ======*/function(nodes, mixin, args){
+               // summary:
+               //              Takes array of nodes, and turns them into class instances and
+               //              potentially calls a startup method to allow them to connect with
+               //              any children.
+               // nodes: Array
+               //              Array of nodes or objects like
+               //      |               {
+               //      |                       type: "dijit.form.Button",
+               //      |                       node: DOMNode,
+               //      |                       scripts: [ ... ],       // array of <script type="dojo/..."> children of node
+               //      |                       inherited: { ... }      // settings inherited from ancestors like dir, theme, etc.
+               //      |               }
+               // mixin: Object?
+               //              An object that will be mixed in with each node in the array.
+               //              Values in the mixin will override values in the node, if they
+               //              exist.
+               // args: Object?
+               //              An object used to hold kwArgs for instantiation.
+               //              See parse.args argument for details.
+
+               var thelist = [],
+               mixin = mixin||{};
+               args = args||{};
+
+               // Precompute names of special attributes we are looking for
+               // TODO: for 2.0 default to data-dojo- regardless of scopeName (or maybe scopeName won't exist in 2.0)
+               var dojoType = (args.scope || dojo._scopeName) + "Type",                // typically "dojoType"
+                       attrData = "data-" + (args.scope || dojo._scopeName) + "-",// typically "data-dojo-"
+                       dataDojoType = attrData + "type",                                               // typically "data-dojo-type"
+                       dataDojoProps = attrData + "props",                                             // typically "data-dojo-props"
+                       dataDojoAttachPoint = attrData + "attach-point",
+                       dataDojoAttachEvent = attrData + "attach-event",
+                       dataDojoId = attrData + "id";
+
+               // And make hash to quickly check if a given attribute is special, and to map the name to something friendly
+               var specialAttrs = {};
+               darray.forEach([dataDojoProps, dataDojoType, dojoType, dataDojoId, "jsId", dataDojoAttachPoint,
+                               dataDojoAttachEvent, "dojoAttachPoint", "dojoAttachEvent", "class", "style"], function(name){
+                       specialAttrs[name.toLowerCase()] = name.replace(args.scope, "dojo");
+               });
+
+               darray.forEach(nodes, function(obj){
+                       if(!obj){ return; }
+
+                       var node = obj.node || obj,
+                               type = dojoType in mixin ? mixin[dojoType] : obj.node ? obj.type : (node.getAttribute(dataDojoType) || node.getAttribute(dojoType)),
+                               ctor = _ctorMap[type] || (_ctorMap[type] = dlang.getObject(type)),
+                               proto = ctor && ctor.prototype;
+                       if(!ctor){
+                               throw new Error("Could not load class '" + type);
+                       }
+
+                       // Setup hash to hold parameter settings for this widget.       Start with the parameter
+                       // settings inherited from ancestors ("dir" and "lang").
+                       // Inherited setting may later be overridden by explicit settings on node itself.
+                       var params = {};
+
+                       if(args.defaults){
+                               // settings for the document itself (or whatever subtree is being parsed)
+                               dlang.mixin(params, args.defaults);
+                       }
+                       if(obj.inherited){
+                               // settings from dir=rtl or lang=... on a node above this node
+                               dlang.mixin(params, obj.inherited);
+                       }
+
+                       // Get list of attributes explicitly listed in the markup
+                       var attributes;
+                       if(has("dom-attributes-explicit")){
+                               // Standard path to get list of user specified attributes
+                               attributes = node.attributes;
+                       }else{
+                               // Special path for IE, avoid (sometimes >100) bogus entries in node.attributes
+                               var clone = /^input$|^img$/i.test(node.nodeName) ? node : node.cloneNode(false),
+                                       attrs = clone.outerHTML.replace(/=[^\s"']+|="[^"]*"|='[^']*'/g, "").replace(/^\s*<[a-zA-Z0-9]*/, "").replace(/>.*$/, "");
+
+                               attributes = darray.map(attrs.split(/\s+/), function(name){
+                                       var lcName = name.toLowerCase();
+                                       return {
+                                               name: name,
+                                               // getAttribute() doesn't work for button.value, returns innerHTML of button.
+                                               // but getAttributeNode().value doesn't work for the form.encType or li.value
+                                               value: (node.nodeName == "LI" && name == "value") || lcName == "enctype" ?
+                                                               node.getAttribute(lcName) : node.getAttributeNode(lcName).value,
+                                               specified: true
+                                       };
+                               });
+                       }
+
+                       // Read in attributes and process them, including data-dojo-props, data-dojo-type,
+                       // dojoAttachPoint, etc., as well as normal foo=bar attributes.
+                       var i=0, item;
+                       while(item = attributes[i++]){
+                               if(!item || !item.specified){
+                                       continue;
+                               }
+
+                               var name = item.name,
+                                       lcName = name.toLowerCase(),
+                                       value = item.value;
+
+                               if(lcName in specialAttrs){
+                                       switch(specialAttrs[lcName]){
+
+                                       // Data-dojo-props.   Save for later to make sure it overrides direct foo=bar settings
+                                       case "data-dojo-props":
+                                               var extra = value;
+                                               break;
+
+                                       // data-dojo-id or jsId. TODO: drop jsId in 2.0
+                                       case "data-dojo-id":
+                                       case "jsId":
+                                               var jsname = value;
+                                               break;
+
+                                       // For the benefit of _Templated
+                                       case "data-dojo-attach-point":
+                                       case "dojoAttachPoint":
+                                               params.dojoAttachPoint = value;
+                                               break;
+                                       case "data-dojo-attach-event":
+                                       case "dojoAttachEvent":
+                                               params.dojoAttachEvent = value;
+                                               break;
+
+                                       // Special parameter handling needed for IE
+                                       case "class":
+                                               params["class"] = node.className;
+                                               break;
+                                       case "style":
+                                               params["style"] = node.style && node.style.cssText;
+                                               break;
+                                       }
+                               }else{
+                                       // Normal attribute, ex: value="123"
+
+                                       // Find attribute in widget corresponding to specified name.
+                                       // May involve case conversion, ex: onclick --> onClick
+                                       if(!(name in proto)){
+                                               var map = (_nameMap[type] || (_nameMap[type] = getNameMap(proto)));
+                                               name = map[lcName] || name;
+                                       }
+
+                                       // Set params[name] to value, doing type conversion
+                                       if(name in proto){
+                                               switch(typeof proto[name]){
+                                               case "string":
+                                                       params[name] = value;
+                                                       break;
+                                               case "number":
+                                                       params[name] = value.length ? Number(value) : NaN;
+                                                       break;
+                                               case "boolean":
+                                                       // for checked/disabled value might be "" or "checked".  interpret as true.
+                                                       params[name] = value.toLowerCase() != "false";
+                                                       break;
+                                               case "function":
+                                                       if(value === "" || value.search(/[^\w\.]+/i) != -1){
+                                                               // The user has specified some text for a function like "return x+5"
+                                                               params[name] = new Function(value);
+                                                       }else{
+                                                               // The user has specified the name of a function like "myOnClick"
+                                                               // or a single word function "return"
+                                                               params[name] = dlang.getObject(value, false) || new Function(value);
+                                                       }
+                                                       break;
+                                               default:
+                                                       var pVal = proto[name];
+                                                       params[name] =
+                                                               (pVal && "length" in pVal) ? (value ? value.split(/\s*,\s*/) : []) :    // array
+                                                                       (pVal instanceof Date) ?
+                                                                               (value == "" ? new Date("") :   // the NaN of dates
+                                                                               value == "now" ? new Date() :   // current date
+                                                                               dates.fromISOString(value)) :
+                                                               (pVal instanceof dojo._Url) ? (dojo.baseUrl + value) :
+                                                               djson.fromJson(value);
+                                               }
+                                       }else{
+                                               params[name] = value;
+                                       }
+                               }
+                       }
+
+                       // Mix things found in data-dojo-props into the params, overriding any direct settings
+                       if(extra){
+                               try{
+                                       extra = djson.fromJson.call(args.propsThis, "{" + extra + "}");
+                                       dlang.mixin(params, extra);
+                               }catch(e){
+                                       // give the user a pointer to their invalid parameters. FIXME: can we kill this in production?
+                                       throw new Error(e.toString() + " in data-dojo-props='" + extra + "'");
+                               }
+                       }
+
+                       // Any parameters specified in "mixin" override everything else.
+                       dlang.mixin(params, mixin);
+
+                       var scripts = obj.node ? obj.scripts : (ctor && (ctor._noScript || proto._noScript) ? [] :
+                                               query("> script[type^='dojo/']", node));
+
+                       // 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" data-dojo-event="foo"> tags are dojo.connected after instantiation
+                       // <script type="dojo/watch" data-dojo-prop="foo"> tags are dojo.watch after instantiation
+                       // <script type="dojo/on" data-dojo-event="foo"> tags are dojo.on after instantiation
+                       // note: dojo/* script tags cannot exist in self closing widgets, like <input />
+                       var connects = [],      // functions to connect after instantiation
+                               calls = [],             // functions to call after instantiation
+                               watch = [],  //functions to watch after instantiation
+                               on = []; //functions to on after instantiation
+
+                       if(scripts){
+                               for(i=0; i<scripts.length; i++){
+                                       var script = scripts[i];
+                                       node.removeChild(script);
+                                       // FIXME: drop event="" support in 2.0. use data-dojo-event="" instead
+                                       var event = (script.getAttribute(attrData + "event") || script.getAttribute("event")),
+                                               prop = script.getAttribute(attrData + "prop"),
+                                               type = script.getAttribute("type"),
+                                               nf = this._functionFromScript(script, attrData);
+                                       if(event){
+                                               if(type == "dojo/connect"){
+                                                       connects.push({event: event, func: nf});
+                                               }else if(type == "dojo/on"){
+                                                       on.push({event: event, func: nf});
+                                               }else{
+                                                       params[event] = nf;
+                                               }
+                                       }else if(type == "dojo/watch"){
+                                               watch.push({prop: prop, func: nf});
+                                       }else{
+                                               calls.push(nf);
+                                       }
+                               }
+                       }
+
+                       // create the instance
+                       var markupFactory = ctor.markupFactory || proto.markupFactory;
+                       var instance = markupFactory ? markupFactory(params, node, ctor) : new ctor(params, node);
+                       thelist.push(instance);
+
+                       // map it to the JS namespace if that makes sense
+                       if(jsname){
+                               dlang.setObject(jsname, instance);
+                       }
+
+                       // process connections and startup functions
+                       for(i=0; i<connects.length; i++){
+                               aspect.after(instance, connects[i].event, dojo.hitch(instance, connects[i].func), true);
+                       }
+                       for(i=0; i<calls.length; i++){
+                               calls[i].call(instance);
+                       }
+                       for(i=0; i<watch.length; i++){
+                               instance.watch(watch[i].prop, watch[i].func);
+                       }
+                       for(i=0; i<on.length; i++){
+                               don(instance, on[i].event, on[i].func);
+                       }
+               }, this);
+
+               // 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
+               if(!mixin._started){
+                       darray.forEach(thelist, function(instance){
+                               if( !args.noStart && instance  &&
+                                       dlang.isFunction(instance.startup) &&
+                                       !instance._started
+                               ){
+                                       instance.startup();
+                               }
+                       });
+               }
+               return thelist;
+       };
+
+       this.parse = /*====== dojo.parser.parse= ======*/ function(rootNode, args){
+               // summary:
+               //              Scan the DOM for class instances, and instantiate them.
+               //
+               // description:
+               //              Search specified node (or root node) recursively for class instances,
+               //              and instantiate them. Searches for either data-dojo-type="Class" or
+               //              dojoType="Class" where "Class" is a a fully qualified class name,
+               //              like `dijit.form.Button`
+               //
+               //              Using `data-dojo-type`:
+               //              Attributes using can be mixed into the parameters used to instantiate the
+               //              Class by using a `data-dojo-props` attribute on the node being converted.
+               //              `data-dojo-props` should be a string attribute to be converted from JSON.
+               //
+               //              Using `dojoType`:
+               //              Attributes are read from the original domNode and converted to appropriate
+               //              types by looking up the Class prototype values. This is the default behavior
+               //              from Dojo 1.0 to Dojo 1.5. `dojoType` support is deprecated, and will
+               //              go away in Dojo 2.0.
+               //
+               // rootNode: DomNode?
+               //              A default starting root node from which to start the parsing. Can be
+               //              omitted, defaulting to the entire document. If omitted, the `args`
+               //              object can be passed in this place. If the `args` object has a
+               //              `rootNode` member, that is used.
+               //
+               // args: Object
+               //              a kwArgs object passed along to instantiate()
+               //
+               //                      * noStart: Boolean?
+               //                              when set will prevent the parser from calling .startup()
+               //                              when locating the nodes.
+               //                      * rootNode: DomNode?
+               //                              identical to the function's `rootNode` argument, though
+               //                              allowed to be passed in via this `args object.
+               //                      * template: Boolean
+               //                              If true, ignores ContentPane's stopParser flag and parses contents inside of
+               //                              a ContentPane inside of a template.   This allows dojoAttachPoint on widgets/nodes
+               //                              nested inside the ContentPane to work.
+               //                      * inherited: Object
+               //                              Hash possibly containing dir and lang settings to be applied to
+               //                              parsed widgets, unless there's another setting on a sub-node that overrides
+               //                      * scope: String
+               //                              Root for attribute names to search for.   If scopeName is dojo,
+               //                              will search for data-dojo-type (or dojoType).   For backwards compatibility
+               //                              reasons defaults to dojo._scopeName (which is "dojo" except when
+               //                              multi-version support is used, when it will be something like dojo16, dojo20, etc.)
+               //                      * propsThis: Object
+               //                              If specified, "this" referenced from data-dojo-props will refer to propsThis.
+               //                              Intended for use from the widgets-in-template feature of `dijit._WidgetsInTemplateMixin`
+               //
+               // example:
+               //              Parse all widgets on a page:
+               //      |               dojo.parser.parse();
+               //
+               // example:
+               //              Parse all classes within the node with id="foo"
+               //      |               dojo.parser.parse(dojo.byId('foo'));
+               //
+               // example:
+               //              Parse all classes in a page, but do not call .startup() on any
+               //              child
+               //      |               dojo.parser.parse({ noStart: true })
+               //
+               // example:
+               //              Parse all classes in a node, but do not call .startup()
+               //      |               dojo.parser.parse(someNode, { noStart:true });
+               //      |               // or
+               //      |               dojo.parser.parse({ noStart:true, rootNode: someNode });
+
+               // determine the root node based on the passed arguments.
+               var root;
+               if(!args && rootNode && rootNode.rootNode){
+                       args = rootNode;
+                       root = args.rootNode;
+               }else{
+                       root = rootNode;
+               }
+               root = root ? dhtml.byId(root) : dwindow.body();
+               args = args || {};
+
+               var dojoType = (args.scope || dojo._scopeName) + "Type",                // typically "dojoType"
+                       attrData = "data-" + (args.scope || dojo._scopeName) + "-",     // typically "data-dojo-"
+                       dataDojoType = attrData + "type",                                               // typically "data-dojo-type"
+                       dataDojoTextDir = attrData + "textdir";                                 // typically "data-dojo-textdir"
+
+               // List of all nodes on page w/dojoType specified
+               var list = [];
+
+               // Info on DOMNode currently being processed
+               var node = root.firstChild;
+
+               // Info on parent of DOMNode currently being processed
+               //      - inherited: dir, lang, and textDir setting of parent, or inherited by parent
+               //      - parent: pointer to identical structure for my parent (or null if no parent)
+               //      - scripts: if specified, collects <script type="dojo/..."> type nodes from children
+               var inherited = args && args.inherited;
+               if(!inherited){
+                       function findAncestorAttr(node, attr){
+                               return (node.getAttribute && node.getAttribute(attr)) ||
+                                       (node !== dwindow.doc && node !== dwindow.doc.documentElement && node.parentNode ? findAncestorAttr(node.parentNode, attr) : null);
+                       }
+                       inherited = {
+                               dir: findAncestorAttr(root, "dir"),
+                               lang: findAncestorAttr(root, "lang"),
+                               textDir: findAncestorAttr(root, dataDojoTextDir)
+                       };
+                       for(var key in inherited){
+                               if(!inherited[key]){ delete inherited[key]; }
+                       }
+               }
+               var parent = {
+                       inherited: inherited
+               };
+
+               // For collecting <script type="dojo/..."> type nodes (when null, we don't need to collect)
+               var scripts;
+
+               // when true, only look for <script type="dojo/..."> tags, and don't recurse to children
+               var scriptsOnly;
+
+               function getEffective(parent){
+                       // summary:
+                       //              Get effective dir, lang, textDir settings for specified obj
+                       //              (matching "parent" object structure above), and do caching.
+                       //              Take care not to return null entries.
+                       if(!parent.inherited){
+                               parent.inherited = {};
+                               var node = parent.node,
+                                       grandparent = getEffective(parent.parent);
+                               var inherited  = {
+                                       dir: node.getAttribute("dir") || grandparent.dir,
+                                       lang: node.getAttribute("lang") || grandparent.lang,
+                                       textDir: node.getAttribute(dataDojoTextDir) || grandparent.textDir
+                               };
+                               for(var key in inherited){
+                                       if(inherited[key]){
+                                               parent.inherited[key] = inherited[key];
+                                       }
+                               }
+                       }
+                       return parent.inherited;
+               }
+
+               // DFS on DOM tree, collecting nodes with data-dojo-type specified.
+               while(true){
+                       if(!node){
+                               // Finished this level, continue to parent's next sibling
+                               if(!parent || !parent.node){
+                                       break;
+                               }
+                               node = parent.node.nextSibling;
+                               scripts = parent.scripts;
+                               scriptsOnly = false;
+                               parent = parent.parent;
+                               continue;
+                       }
+
+                       if(node.nodeType != 1){
+                               // Text or comment node, skip to next sibling
+                               node = node.nextSibling;
+                               continue;
+                       }
+
+                       if(scripts && node.nodeName.toLowerCase() == "script"){
+                               // Save <script type="dojo/..."> for parent, then continue to next sibling
+                               type = node.getAttribute("type");
+                               if(type && /^dojo\/\w/i.test(type)){
+                                       scripts.push(node);
+                               }
+                               node = node.nextSibling;
+                               continue;
+                       }
+                       if(scriptsOnly){
+                               node = node.nextSibling;
+                               continue;
+                       }
+
+                       // Check for data-dojo-type attribute, fallback to backward compatible dojoType
+                       var type = node.getAttribute(dataDojoType) || node.getAttribute(dojoType);
+
+                       // Short circuit for leaf nodes containing nothing [but text]
+                       var firstChild = node.firstChild;
+                       if(!type && (!firstChild || (firstChild.nodeType == 3 && !firstChild.nextSibling))){
+                               node = node.nextSibling;
+                               continue;
+                       }
+
+                       // Setup data structure to save info on current node for when we return from processing descendant nodes
+                       var current = {
+                               node: node,
+                               scripts: scripts,
+                               parent: parent
+                       };
+
+                       // If dojoType/data-dojo-type specified, add to output array of nodes to instantiate
+                       var ctor = type && (_ctorMap[type] || (_ctorMap[type] = dlang.getObject(type))), // note: won't find classes declared via dojo.Declaration
+                               childScripts = ctor && !ctor.prototype._noScript ? [] : null; // <script> nodes that are parent's children
+                       if(type){
+                               list.push({
+                                       "type": type,
+                                       node: node,
+                                       scripts: childScripts,
+                                       inherited: getEffective(current) // dir & lang settings for current node, explicit or inherited
+                               });
+                       }
+
+                       // Recurse, collecting <script type="dojo/..."> children, and also looking for
+                       // descendant nodes with dojoType specified (unless the widget has the stopParser flag).
+                       // When finished with children, go to my next sibling.
+                       node = firstChild;
+                       scripts = childScripts;
+                       scriptsOnly = ctor && ctor.prototype.stopParser && !(args && args.template);
+                       parent = current;
+
+               }
+
+               // go build the object instances
+               var mixin = args && args.template ? {template: true} : null;
+               return this.instantiate(list, mixin, args); // Array
+       };
+}();
+
+
+//Register the parser callback. It should be the first callback
+//after the a11y test.
+if(dojo.config.parseOnLoad){
+       dojo.ready(100, dojo.parser, "parse");
+}
+
+return dojo.parser;
+});