0byt3m1n1
Path:
/
data
/
applications
/
aps.bak
/
phprojekt
/
6.0.6-0
/
standard
/
htdocs
/
htdocs
/
dojo
/
dojox
/
xml
/
[
Home
]
File: widgetParser.js
/* Copyright (c) 2004-2010, The Dojo Foundation All Rights Reserved. Available via Academic Free License >= 2.1 OR the modified BSD license. see: http://dojotoolkit.org/license for details */ if(!dojo._hasResource["dojox.xml.widgetParser"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. dojo._hasResource["dojox.xml.widgetParser"] = true; /** Take some sort of xml block * like <dojo.button caption="blah"/> and turn * it into a widget.. */ dojo.provide("dojox.xml.widgetParser"); dojo.require("dojox.xml.parser"); dojo.require("dojo.parser"); /** * We want to support something like: * <body> * <script> * <dijit.layout.SplitContainer> * <dijit.button/> * <div>...</div> * </dijit.layout.SplitContainer> * </body> * * This is very tricky because if we parse this as XML then the <div> tag * is actually an XML tag, not an XML tag, which is problematic in at least * IE. * * So the strategy is this, silly as it may be: Convert EVERYTHING to HTML * nodes, including the dijit.layout.SplitContainer by converting it to a * div with the dojoType. Then run it through the standard parser. * The more HTML you have relative to XML the less extra overhead this is. * * For something that is all XML we could have a different approach, * perhaps signified by a different type of script tag. In that case we * could just instantiate all the elements without a sourceNodeRef and then * add the top level components to the app. * * That is very straightforward but I haven't done it. * * Right now there is no mechanism to have an intermediary bridge between * the XML and the widget, because we are relying on dojo.parser * to do the instantiation. It isn't clear to me why we would want * those bridges in this approach and not in that approach. * */ dojox.xml.widgetParser = new function(){ var d = dojo; this.parseNode = function(node){ var toBuild = []; //TODO figure out the proper type d.query("script[type='text/xml']", node).forEach(function(script){ toBuild.push.apply(toBuild, this._processScript(script)); }, this).orphan(); //instantiate everything at the end, doing it piecewise can give ID conflicts return d.parser.instantiate(toBuild); }; this._processScript = function(script){ //the text is either loaded from a separate file by the src //attribute or underneath the src tag var text = script.src ? d._getText(script.src) : script.innerHTML || script.firstChild.nodeValue; var htmlNode = this.toHTML( dojox.xml.parser.parse(text).firstChild ); //make the list BEFORE we copy things over to keep the query scope as //small as possible var ret = d.query('[dojoType]', htmlNode); //remove the script tag and replace with new HTML block dojo.query(">", htmlNode).place(script, "before") script.parentNode.removeChild(script); return ret; }; /** * Given an XML node converts it to HTML where the existing HTML * is preserved and the dojo widget tags are converted to divs * with dojoType on them. */ this.toHTML = function (/*XmlNode*/ node){ var newNode; var nodeName = node.nodeName; var dd = dojo.doc; var type = node.nodeType; ///node type 3 and 4 are text and cdata if(type >= 3){ return dd.createTextNode( (type == 3 || type == 4) ? node.nodeValue : "" ); } var localName = node.localName||nodeName.split(":").pop(); //TODO: // only check for namespace ONCE ever, instead of each time here, // by mixing in the right check for each browser? var namespace = node.namespaceURI || (node.getNamespaceUri ? node.getNamespaceUri() : ""); //TODO check for some real namespace if(namespace == "html"){ newNode = dd.createElement(localName); }else{ var dojoType = namespace + "." + localName; /** * This is a horrible hack we need because creating a <div> * with <option> children doesn't work well. Specifically with * dojo.Declaration at some point the <option> tags get lost * entirely so we need the parent of <option> tags to be <select> * tags. (Not a problem outside of dojo.Delcaration) * There are a couple other ways we could do this: * 1. Look at the first element child to see if it is an option and * if so create a <select> here. * 2. When we add a child to parent fix up the parent then if the * child is an <option> and the parent isn't a <select>. * Both of those are a bit messy and slower than this. * * This is potentially a problem for other tag combinations as well, * such as <tr> under a <table> or <li> under a <ul>/<ol>. * (dojox.widget.SortList for example). Probably need a robust strategy for * dealing with this. Worst case scenario for now is that user has to use * html tag with dojoType for misbehaving widget. */ newNode = newNode || dd.createElement((dojoType == "dijit.form.ComboBox") ? "select" : "div"); newNode.setAttribute("dojoType", dojoType); } // TODO: // we should probably set this up different, mixin a function // depending on if it is IE rather than checking every time here // the xmlns problem and the style problem are both IE specific d.forEach(node.attributes, function(attr){ // NOTE: IE always iterates *all* properties!!! var name = attr.name || attr.nodeName; var value = attr.value || attr.nodeValue; if(name.indexOf("xmlns") != 0){ // style=blah blah blah is a problem, in IE if you use // setAttribute here you get all sorts of problems. Maybe it // would be better to just create a giant string of HTML // instead of an object graph, then set innerHTML on something // to get the object graph? That might be cleaner... that way // is uses the browser HTML parsing exactly at is and won't // cause any sort of issues. We could just special case style // as well? if(dojo.isIE && name == "style"){ newNode.style.setAttribute("cssText", value); }else{ newNode.setAttribute(name, value); } } }); d.forEach(node.childNodes, function(cn){ var childNode = this.toHTML(cn); // script tags in IE don't like appendChild, innerHTML or innerText // so if we are creating one programatically set text instead // could special case this for IE only if(localName == "script"){ newNode.text += childNode.nodeValue; }else{ newNode.appendChild(childNode); } }, this); return newNode; }; }(); }