You are viewing a plain text version of this content. The canonical link for it is here.
Posted to xap-commits@incubator.apache.org by jm...@apache.org on 2006/06/27 22:49:06 UTC

svn commit: r417618 [7/19] - in /incubator/xap/trunk/src/dojo/src: ./ lfx/ logging/ rpc/ selection/ storage/ string/ text/ undo/ uri/ uuid/ widget/ widget/html/ widget/svg/ widget/templates/ widget/templates/buttons/ widget/templates/images/ widget/tem...

Added: incubator/xap/trunk/src/dojo/src/style.js
URL: http://svn.apache.org/viewvc/incubator/xap/trunk/src/dojo/src/style.js?rev=417618&view=auto
==============================================================================
--- incubator/xap/trunk/src/dojo/src/style.js (added)
+++ incubator/xap/trunk/src/dojo/src/style.js Tue Jun 27 15:48:54 2006
@@ -0,0 +1,782 @@
+/*
+	Copyright (c) 2004-2006, The Dojo Foundation
+	All Rights Reserved.
+
+	Licensed under the Academic Free License version 2.1 or above OR the
+	modified BSD license. For more information on Dojo licensing, see:
+
+		http://dojotoolkit.org/community/licensing.shtml
+*/
+
+dojo.provide("dojo.style");
+dojo.require("dojo.graphics.color");
+dojo.require("dojo.uri.Uri");
+dojo.require("dojo.lang.common");
+
+(function(){
+	var h = dojo.render.html;
+	var ds = dojo.style;
+	var db = document["body"]||document["documentElement"];
+
+	ds.boxSizing = {
+		MARGIN_BOX: "margin-box",
+		BORDER_BOX: "border-box",
+		PADDING_BOX: "padding-box",
+		CONTENT_BOX: "content-box"
+	};
+	var bs = ds.boxSizing;
+	
+	ds.getBoxSizing = function(node){
+		if((h.ie)||(h.opera)){ 
+			var cm = document["compatMode"];
+			if((cm == "BackCompat")||(cm == "QuirksMode")){ 
+				return bs.BORDER_BOX; 
+			}else{
+				return bs.CONTENT_BOX; 
+			}
+		}else{
+			if(arguments.length == 0){ node = document.documentElement; }
+			var sizing = ds.getStyle(node, "-moz-box-sizing");
+			if(!sizing){ sizing = ds.getStyle(node, "box-sizing"); }
+			return (sizing ? sizing : bs.CONTENT_BOX);
+		}
+	}
+
+	/*
+
+	The following several function use the dimensions shown below
+
+		+-------------------------+
+		|  margin                 |
+		| +---------------------+ |
+		| |  border             | |
+		| | +-----------------+ | |
+		| | |  padding        | | |
+		| | | +-------------+ | | |
+		| | | |   content   | | | |
+		| | | +-------------+ | | |
+		| | +-|-------------|-+ | |
+		| +-|-|-------------|-|-+ |
+		+-|-|-|-------------|-|-|-+
+		| | | |             | | | |
+		| | | |<- content ->| | | |
+		| |<------ inner ------>| |
+		|<-------- outer -------->|
+		+-------------------------+
+
+		* content-box
+
+		|m|b|p|             |p|b|m|
+		| |<------ offset ----->| |
+		| | |<---- client --->| | |
+		| | | |<-- width -->| | | |
+
+		* border-box
+
+		|m|b|p|             |p|b|m|
+		| |<------ offset ----->| |
+		| | |<---- client --->| | |
+		| |<------ width ------>| |
+	*/
+
+	/*
+		Notes:
+
+		General:
+			- Uncomputable values are returned as NaN.
+			- setOuterWidth/Height return *false* if the outer size could not
+			  be computed, otherwise *true*.
+			- (sjmiles) knows no way to find the calculated values for auto-margins. 
+			- All returned values are floating point in 'px' units. If a
+			  non-zero computed style value is not specified in 'px', NaN is
+			  returned.
+
+		FF:
+			- styles specified as '0' (unitless 0) show computed as '0pt'.
+
+		IE:
+			- clientWidth/Height are unreliable (0 unless the object has 'layout').
+			- margins must be specified in px, or 0 (in any unit) for any
+			  sizing function to work. Otherwise margins detect as 'auto'.
+			- padding can be empty or, if specified, must be in px, or 0 (in
+			  any unit) for any sizing function to work.
+
+		Safari:
+			- Safari defaults padding values to 'auto'.
+
+		See the unit tests for examples of (un)computable values in a given browser.
+
+	*/
+
+	// FIXME: these work for some elements (e.g. DIV) but not others (e.g. TABLE, TEXTAREA)
+
+	ds.isBorderBox = function(node){
+		return (ds.getBoxSizing(node) == bs.BORDER_BOX);
+	}
+
+	ds.getUnitValue = function(node, cssSelector, autoIsZero){
+		var s = ds.getComputedStyle(node, cssSelector);
+		if((!s)||((s == 'auto')&&(autoIsZero))){ return { value: 0, units: 'px' }; }
+		if(dojo.lang.isUndefined(s)){return ds.getUnitValue.bad;}
+		// FIXME: is regex inefficient vs. parseInt or some manual test? 
+		var match = s.match(/(\-?[\d.]+)([a-z%]*)/i);
+		if (!match){return ds.getUnitValue.bad;}
+		return { value: Number(match[1]), units: match[2].toLowerCase() };
+	}
+	// FIXME: 'bad' value should be 0?
+	ds.getUnitValue.bad = { value: NaN, units: '' };
+	
+	ds.getPixelValue = function(node, cssSelector, autoIsZero){
+		var result = ds.getUnitValue(node, cssSelector, autoIsZero);
+		// FIXME: there is serious debate as to whether or not this is the right solution
+		if(isNaN(result.value)){ return 0; }
+		// FIXME: code exists for converting other units to px (see Dean Edward's IE7) 
+		// but there are cross-browser complexities
+		if((result.value)&&(result.units != 'px')){ return NaN; }
+		return result.value;
+	}
+	
+	// FIXME: deprecated
+	ds.getNumericStyle = function() {
+		dojo.deprecated('dojo.(style|html).getNumericStyle', 'in favor of dojo.(style|html).getPixelValue', '0.4');
+		return ds.getPixelValue.apply(this, arguments); 
+	}
+
+	ds.setPositivePixelValue = function(node, selector, value){
+		if(isNaN(value)){return false;}
+		node.style[selector] = Math.max(0, value) + 'px'; 
+		return true;
+	}
+	
+	ds._sumPixelValues = function(node, selectors, autoIsZero){
+		var total = 0;
+		for(x=0; x<selectors.length; x++){
+			total += ds.getPixelValue(node, selectors[x], autoIsZero);
+		}
+		return total;
+	}
+
+	ds.isPositionAbsolute = function(node){
+		return (ds.getComputedStyle(node, 'position') == 'absolute');
+	}
+
+	ds.getBorderExtent = function(node, side){
+		return (ds.getStyle(node, 'border-' + side + '-style') == 'none' ? 0 : ds.getPixelValue(node, 'border-' + side + '-width'));
+	}
+
+	ds.getMarginWidth = function(node){
+		return ds._sumPixelValues(node, ["margin-left", "margin-right"], ds.isPositionAbsolute(node));
+	}
+
+	ds.getBorderWidth = function(node){
+		return ds.getBorderExtent(node, 'left') + ds.getBorderExtent(node, 'right');
+	}
+
+	ds.getPaddingWidth = function(node){
+		return ds._sumPixelValues(node, ["padding-left", "padding-right"], true);
+	}
+
+	ds.getPadBorderWidth = function(node) {
+		return ds.getPaddingWidth(node) + ds.getBorderWidth(node);
+	}
+	
+	ds.getContentBoxWidth = function(node){
+		node = dojo.byId(node);
+		return node.offsetWidth - ds.getPadBorderWidth(node);
+	}
+
+	ds.getBorderBoxWidth = function(node){
+		node = dojo.byId(node);
+		return node.offsetWidth;
+	}
+
+	ds.getMarginBoxWidth = function(node){
+		return ds.getInnerWidth(node) + ds.getMarginWidth(node);
+	}
+
+	ds.setContentBoxWidth = function(node, pxWidth){
+		node = dojo.byId(node);
+		if (ds.isBorderBox(node)){
+			pxWidth += ds.getPadBorderWidth(node);
+		}
+		return ds.setPositivePixelValue(node, "width", pxWidth);
+	}
+
+	ds.setMarginBoxWidth = function(node, pxWidth){
+		node = dojo.byId(node);
+		if (!ds.isBorderBox(node)){
+			pxWidth -= ds.getPadBorderWidth(node);
+		}
+		pxWidth -= ds.getMarginWidth(node);
+		return ds.setPositivePixelValue(node, "width", pxWidth);
+	}
+
+	// FIXME: deprecate and remove
+	ds.getContentWidth = ds.getContentBoxWidth;
+	ds.getInnerWidth = ds.getBorderBoxWidth;
+	ds.getOuterWidth = ds.getMarginBoxWidth;
+	ds.setContentWidth = ds.setContentBoxWidth;
+	ds.setOuterWidth = ds.setMarginBoxWidth;
+
+	ds.getMarginHeight = function(node){
+		return ds._sumPixelValues(node, ["margin-top", "margin-bottom"], ds.isPositionAbsolute(node));
+	}
+
+	ds.getBorderHeight = function(node){
+		return ds.getBorderExtent(node, 'top') + ds.getBorderExtent(node, 'bottom');
+	}
+
+	ds.getPaddingHeight = function(node){
+		return ds._sumPixelValues(node, ["padding-top", "padding-bottom"], true);
+	}
+
+	ds.getPadBorderHeight = function(node) {
+		return ds.getPaddingHeight(node) + ds.getBorderHeight(node);
+	}
+	
+	ds.getContentBoxHeight = function(node){
+		node = dojo.byId(node);
+		return node.offsetHeight - ds.getPadBorderHeight(node);
+	}
+
+	ds.getBorderBoxHeight = function(node){
+		node = dojo.byId(node);
+		return node.offsetHeight; // FIXME: does this work?
+	}
+
+	ds.getMarginBoxHeight = function(node){
+		return ds.getInnerHeight(node) + ds.getMarginHeight(node);
+	}
+
+	ds.setContentBoxHeight = function(node, pxHeight){
+		node = dojo.byId(node);
+		if (ds.isBorderBox(node)){
+			pxHeight += ds.getPadBorderHeight(node);
+		}
+		return ds.setPositivePixelValue(node, "height", pxHeight);
+	}
+
+	ds.setMarginBoxHeight = function(node, pxHeight){
+		node = dojo.byId(node);
+		if (!ds.isBorderBox(node)){
+			pxHeight -= ds.getPadBorderHeight(node);
+		}
+		pxHeight -= ds.getMarginHeight(node);
+		return ds.setPositivePixelValue(node, "height", pxHeight);
+	}
+
+	// FIXME: deprecate and remove
+	ds.getContentHeight = ds.getContentBoxHeight;
+	ds.getInnerHeight = ds.getBorderBoxHeight;
+	ds.getOuterHeight = ds.getMarginBoxHeight;
+	ds.setContentHeight = ds.setContentBoxHeight;
+	ds.setOuterHeight = ds.setMarginBoxHeight;
+
+	/**
+	 * dojo.style.getAbsolutePosition(xyz, true) returns xyz's position relative to the document.
+	 * Itells you where you would position a node
+	 * inside document.body such that it was on top of xyz.  Most people set the flag to true when calling
+	 * getAbsolutePosition().
+	 *
+	 * dojo.style.getAbsolutePosition(xyz, false) returns xyz's position relative to the viewport.
+	 * It returns the position that would be returned
+	 * by event.clientX/Y if the mouse were directly over the top/left of this node.
+	 */
+	ds.getAbsolutePosition = ds.abs = function(node, includeScroll){
+		var ret = [];
+		ret.x = ret.y = 0;
+		var st = dojo.html.getScrollTop();
+		var sl = dojo.html.getScrollLeft();
+
+		if(h.ie){
+			with(node.getBoundingClientRect()){
+				ret.x = left-2;
+				ret.y = top-2;
+			}
+/**
+		}else if(document.getBoxObjectFor){
+			// mozilla
+			var bo=document.getBoxObjectFor(node);
+			ret.x=bo.x-sl;
+			ret.y=bo.y-st;
+**/		}else{
+			if(node["offsetParent"]){
+				var endNode;		
+				// in Safari, if the node is an absolutely positioned child of
+				// the body and the body has a margin the offset of the child
+				// and the body contain the body's margins, so we need to end
+				// at the body
+				if(	(h.safari)&&
+					(node.style.getPropertyValue("position") == "absolute")&&
+					(node.parentNode == db)){
+					endNode = db;
+				}else{
+					endNode = db.parentNode;
+				}
+				
+				if(node.parentNode != db){
+					ret.x -= ds.sumAncestorProperties(node, "scrollLeft");
+					ret.y -= ds.sumAncestorProperties(node, "scrollTop");
+				}
+				do{
+					var n = node["offsetLeft"];
+					ret.x += isNaN(n) ? 0 : n;
+					var m = node["offsetTop"];
+					ret.y += isNaN(m) ? 0 : m;
+					node = node.offsetParent;
+				}while((node != endNode)&&(node != null));
+			}else if(node["x"]&&node["y"]){
+				ret.x += isNaN(node.x) ? 0 : node.x;
+				ret.y += isNaN(node.y) ? 0 : node.y;
+			}
+		}
+
+		// account for document scrolling!
+		if(includeScroll){
+			ret.y += st;
+			ret.x += sl;
+		}
+
+		ret[0] = ret.x;
+		ret[1] = ret.y;
+		return ret;
+	}
+
+	ds.sumAncestorProperties = function(node, prop){
+		node = dojo.byId(node);
+		if(!node){ return 0; } // FIXME: throw an error?
+		
+		var retVal = 0;
+		while(node){
+			var val = node[prop];
+			if(val){
+				retVal += val - 0;
+			}
+			node = node.parentNode;
+		}
+		return retVal;
+	}
+
+	ds.getTotalOffset = function(node, type, includeScroll){
+		node = dojo.byId(node);
+		return ds.abs(node, includeScroll)[(type == "top") ? "y" : "x"];
+	}
+
+	ds.getAbsoluteX = ds.totalOffsetLeft = function(node, includeScroll){
+		return ds.getTotalOffset(node, "left", includeScroll);
+	}
+
+	ds.getAbsoluteY = ds.totalOffsetTop = function(node, includeScroll){
+		return ds.getTotalOffset(node, "top", includeScroll);
+	}
+
+	ds.styleSheet = null;
+
+	// FIXME: this is a really basic stub for adding and removing cssRules, but
+	// it assumes that you know the index of the cssRule that you want to add 
+	// or remove, making it less than useful.  So we need something that can 
+	// search for the selector that you you want to remove.
+	ds.insertCssRule = function(selector, declaration, index) {
+		if (!ds.styleSheet) {
+			if (document.createStyleSheet) { // IE
+				ds.styleSheet = document.createStyleSheet();
+			} else if (document.styleSheets[0]) { // rest
+				// FIXME: should create a new style sheet here
+				// fall back on an exsiting style sheet
+				ds.styleSheet = document.styleSheets[0];
+			} else { return null; } // fail
+		}
+
+		if (arguments.length < 3) { // index may == 0
+			if (ds.styleSheet.cssRules) { // W3
+				index = ds.styleSheet.cssRules.length;
+			} else if (ds.styleSheet.rules) { // IE
+				index = ds.styleSheet.rules.length;
+			} else { return null; } // fail
+		}
+
+		if (ds.styleSheet.insertRule) { // W3
+			var rule = selector + " { " + declaration + " }";
+			return ds.styleSheet.insertRule(rule, index);
+		} else if (ds.styleSheet.addRule) { // IE
+			return ds.styleSheet.addRule(selector, declaration, index);
+		} else { return null; } // fail
+	}
+
+	ds.removeCssRule = function(index){
+		if(!ds.styleSheet){
+			dojo.debug("no stylesheet defined for removing rules");
+			return false;
+		}
+		if(h.ie){
+			if(!index){
+				index = ds.styleSheet.rules.length;
+				ds.styleSheet.removeRule(index);
+			}
+		}else if(document.styleSheets[0]){
+			if(!index){
+				index = ds.styleSheet.cssRules.length;
+			}
+			ds.styleSheet.deleteRule(index);
+		}
+		return true;
+	}
+
+	// calls css by XmlHTTP and inserts it into DOM as <style [widgetType="widgetType"]> *downloaded cssText*</style>
+	ds.insertCssFile = function(URI, doc, checkDuplicates){
+		if(!URI){ return; }
+		if(!doc){ doc = document; }
+		var cssStr = dojo.hostenv.getText(URI);
+		cssStr = ds.fixPathsInCssText(cssStr, URI);
+
+		if(checkDuplicates){
+			var styles = doc.getElementsByTagName("style");
+			var cssText = "";
+			for(var i = 0; i<styles.length; i++){
+				cssText = (styles[i].styleSheet && styles[i].styleSheet.cssText) ? styles[i].styleSheet.cssText : styles[i].innerHTML;
+				if(cssStr == cssText){ return; }
+			}
+		}
+
+		var style = ds.insertCssText(cssStr);
+		// insert custom attribute ex dbgHref="../foo.css" usefull when debugging in DOM inspectors, no?
+		if(style && djConfig.isDebug){
+			style.setAttribute("dbgHref", URI);
+		}
+		return style
+	}
+
+	// DomNode Style  = insertCssText(String ".dojoMenu {color: green;}"[, DomDoc document, dojo.uri.Uri Url ])
+	ds.insertCssText = function(cssStr, doc, URI){
+		if(!cssStr){ return; }
+		if(!doc){ doc = document; }
+		if(URI){// fix paths in cssStr
+			cssStr = ds.fixPathsInCssText(cssStr, URI);
+		}
+		var style = doc.createElement("style");
+		style.setAttribute("type", "text/css");
+		if(style.styleSheet){// IE
+			style.styleSheet.cssText = cssStr;
+		} else {// w3c
+			var cssText = doc.createTextNode(cssStr);
+			style.appendChild(cssText);
+		}
+		var head = doc.getElementsByTagName("head")[0];
+		if(!head){ // must have a head tag 
+			dojo.debug("No head tag in document, aborting styles");
+		}else{
+			head.appendChild(style);
+		}
+		return style;
+	}
+
+	// String cssText = fixPathsInCssText(String cssStr, dojo.uri.Uri URI)
+	// usage: cssText comes from dojoroot/src/widget/templates/HtmlFoobar.css
+	// 	it has .dojoFoo { background-image: url(images/bar.png);} 
+	//	then uri should point to dojoroot/src/widget/templates/
+	ds.fixPathsInCssText = function(cssStr, URI){
+		if(!cssStr || !URI){ return; }
+		var pos = 0; var str = ""; var url = "";
+		while(pos!=-1){
+			pos = 0;url = "";
+			pos = cssStr.indexOf("url(", pos);
+			if(pos<0){ break; }
+			str += cssStr.slice(0,pos+4);
+			cssStr = cssStr.substring(pos+4, cssStr.length);
+			url += cssStr.match(/^[\t\s\w()\/.\\'"-:#=&?]*\)/)[0]; // url string
+			cssStr = cssStr.substring(url.length-1, cssStr.length); // remove url from css string til next loop
+			url = url.replace(/^[\s\t]*(['"]?)([\w()\/.\\'"-:#=&?]*)\1[\s\t]*?\)/,"$2"); // clean string
+			if(url.search(/(file|https?|ftps?):\/\//)==-1){
+				url = (new dojo.uri.Uri(URI,url).toString());
+			}
+			str += url;
+		};
+		return str+cssStr;
+	}
+
+	ds.getBackgroundColor = function(node) {
+		node = dojo.byId(node);
+		var color;
+		do{
+			color = ds.getStyle(node, "background-color");
+			// Safari doesn't say "transparent"
+			if(color.toLowerCase() == "rgba(0, 0, 0, 0)") { color = "transparent"; }
+			if(node == document.getElementsByTagName("body")[0]) { node = null; break; }
+			node = node.parentNode;
+		}while(node && dojo.lang.inArray(color, ["transparent", ""]));
+		if(color == "transparent"){
+			color = [255, 255, 255, 0];
+		}else{
+			color = dojo.graphics.color.extractRGB(color);
+		}
+		return color;
+	}
+
+	ds.getComputedStyle = function(node, cssSelector, inValue){
+		node = dojo.byId(node);
+		// cssSelector may actually be in camel case, so force selector version
+		var cssSelector = ds.toSelectorCase(cssSelector);
+		var property = ds.toCamelCase(cssSelector);
+		if(!node || !node.style){
+			return inValue;
+		}else if(document.defaultView){ // W3, gecko, KHTML
+			try{			
+				var cs = document.defaultView.getComputedStyle(node, "");
+				if (cs){ 
+					return cs.getPropertyValue(cssSelector);
+				} 
+			}catch(e){ // reports are that Safari can throw an exception above
+				if (node.style.getPropertyValue){ // W3
+					return node.style.getPropertyValue(cssSelector);
+				}else return inValue;
+			}
+		}else if(node.currentStyle){ // IE
+			return node.currentStyle[property];
+		}if(node.style.getPropertyValue){ // W3
+			return node.style.getPropertyValue(cssSelector);
+		}else{
+			return inValue;
+		}
+	}
+
+	/** 
+	 * Retrieve a property value from a node's style object.
+	 */
+	ds.getStyleProperty = function(node, cssSelector){
+		node = dojo.byId(node);
+		// FIXME: should we use node.style.getPropertyValue over style[property]?
+		// style[property] works in all (modern) browsers, getPropertyValue is W3 but not supported in IE
+		// FIXME: what about runtimeStyle?
+		return (node && node.style ? node.style[ds.toCamelCase(cssSelector)] : undefined);
+	}
+
+	/** 
+	 * Retrieve a property value from a node's style object.
+	 */
+	ds.getStyle = function(node, cssSelector){
+		var value = ds.getStyleProperty(node, cssSelector);
+		return (value ? value : ds.getComputedStyle(node, cssSelector));
+	}
+
+	ds.setStyle = function(node, cssSelector, value){
+		node = dojo.byId(node);
+		if(node && node.style){
+			var camelCased = ds.toCamelCase(cssSelector);
+			node.style[camelCased] = value;
+		}
+	}
+
+	ds.toCamelCase = function(selector) {
+		var arr = selector.split('-'), cc = arr[0];
+		for(var i = 1; i < arr.length; i++) {
+			cc += arr[i].charAt(0).toUpperCase() + arr[i].substring(1);
+		}
+		return cc;		
+	}
+
+	ds.toSelectorCase = function(selector) {
+		return selector.replace(/([A-Z])/g, "-$1" ).toLowerCase() ;
+	}
+
+	/* float between 0.0 (transparent) and 1.0 (opaque) */
+	ds.setOpacity = function setOpacity(node, opacity, dontFixOpacity) {
+		node = dojo.byId(node);
+		if(!dontFixOpacity){
+			if( opacity >= 1.0){
+				if(h.ie){
+					ds.clearOpacity(node);
+					return;
+				}else{
+					opacity = 0.999999;
+				}
+			}else if( opacity < 0.0){ opacity = 0; }
+		}
+		if(h.ie){
+			if(node.nodeName.toLowerCase() == "tr"){
+				// FIXME: is this too naive? will we get more than we want?
+				var tds = node.getElementsByTagName("td");
+				for(var x=0; x<tds.length; x++){
+					tds[x].style.filter = "Alpha(Opacity="+opacity*100+")";
+				}
+			}
+			node.style.filter = "Alpha(Opacity="+opacity*100+")";
+		}else if(h.moz){
+			node.style.opacity = opacity; // ffox 1.0 directly supports "opacity"
+			node.style.MozOpacity = opacity;
+		}else if(h.safari){
+			node.style.opacity = opacity; // 1.3 directly supports "opacity"
+			node.style.KhtmlOpacity = opacity;
+		}else{
+			node.style.opacity = opacity;
+		}
+	}
+		
+	ds.getOpacity = function getOpacity (node){
+		node = dojo.byId(node);
+		if(h.ie){
+			var opac = (node.filters && node.filters.alpha &&
+				typeof node.filters.alpha.opacity == "number"
+				? node.filters.alpha.opacity : 100) / 100;
+		}else{
+			var opac = node.style.opacity || node.style.MozOpacity ||
+				node.style.KhtmlOpacity || 1;
+		}
+		return opac >= 0.999999 ? 1.0 : Number(opac);
+	}
+
+	ds.clearOpacity = function clearOpacity(node){
+		node = dojo.byId(node);
+		var ns = node.style;
+		if(h.ie){
+			try {
+				if( node.filters && node.filters.alpha ){
+					ns.filter = ""; // FIXME: may get rid of other filter effects
+				}
+			} catch(e) {
+				/*
+				 * IE7 gives error if node.filters not set;
+				 * don't know why or how to workaround (other than this)
+				 */
+			}
+		}else if(h.moz){
+			ns.opacity = 1;
+			ns.MozOpacity = 1;
+		}else if(h.safari){
+			ns.opacity = 1;
+			ns.KhtmlOpacity = 1;
+		}else{
+			ns.opacity = 1;
+		}
+	}
+
+	ds._toggle = function(node, tester, setter){
+		node = dojo.byId(node);
+		setter(node, !tester(node));
+		return tester(node);
+	}
+
+	// show/hide are library constructs
+
+	// show() 
+	// if the node.style.display == 'none' then 
+	// set style.display to '' or the value cached by hide()
+	ds.show = function(node){
+		node = dojo.byId(node);
+		if(ds.getStyleProperty(node, 'display')=='none'){
+			ds.setStyle(node, 'display', (node.dojoDisplayCache||''));
+			node.dojoDisplayCache = undefined;	// cannot use delete on a node in IE6
+		}
+	}
+
+	// if the node.style.display == 'none' then 
+	// set style.display to '' or the value cached by hide()
+	ds.hide = function(node){
+		node = dojo.byId(node);
+		if(typeof node["dojoDisplayCache"] == "undefined"){ // it could == '', so we cannot say !node.dojoDisplayCount
+			var d = ds.getStyleProperty(node, 'display')
+			if(d!='none'){
+				node.dojoDisplayCache = d;
+			}
+		}
+		ds.setStyle(node, 'display', 'none');
+	}
+
+	// setShowing() calls show() if showing is true, hide() otherwise
+	ds.setShowing = function(node, showing){
+		ds[(showing ? 'show' : 'hide')](node);
+	}
+
+	// isShowing() is true if the node.style.display is not 'none'
+	// FIXME: returns true if node is bad, isHidden would be easier to make correct
+	ds.isShowing = function(node){
+		return (ds.getStyleProperty(node, 'display') != 'none');
+	}
+
+	// Call setShowing() on node with the complement of isShowing(), then return the new value of isShowing()
+	ds.toggleShowing = function(node){
+		return ds._toggle(node, ds.isShowing, ds.setShowing);
+	}
+
+	// display is a CSS concept
+
+	// Simple mapping of tag names to display values
+	// FIXME: simplistic 
+	ds.displayMap = { tr: '', td: '', th: '', img: 'inline', span: 'inline', input: 'inline', button: 'inline' };
+
+	// Suggest a value for the display property that will show 'node' based on it's tag
+	ds.suggestDisplayByTagName = function(node)
+	{
+		node = dojo.byId(node);
+		if(node && node.tagName){
+			var tag = node.tagName.toLowerCase();
+			return (tag in ds.displayMap ? ds.displayMap[tag] : 'block');
+		}
+	}
+
+	// setDisplay() sets the value of style.display to value of 'display' parameter if it is a string.
+	// Otherwise, if 'display' is false, set style.display to 'none'.
+	// Finally, set 'display' to a suggested display value based on the node's tag
+	ds.setDisplay = function(node, display){
+		ds.setStyle(node, 'display', (dojo.lang.isString(display) ? display : (display ? ds.suggestDisplayByTagName(node) : 'none')));
+	}
+
+	// isDisplayed() is true if the the computed display style for node is not 'none'
+	// FIXME: returns true if node is bad, isNotDisplayed would be easier to make correct
+	ds.isDisplayed = function(node){
+		return (ds.getComputedStyle(node, 'display') != 'none');
+	}
+
+	// Call setDisplay() on node with the complement of isDisplayed(), then
+	// return the new value of isDisplayed()
+	ds.toggleDisplay = function(node){
+		return ds._toggle(node, ds.isDisplayed, ds.setDisplay);
+	}
+
+	// visibility is a CSS concept
+
+	// setVisibility() sets the value of style.visibility to value of
+	// 'visibility' parameter if it is a string.
+	// Otherwise, if 'visibility' is false, set style.visibility to 'hidden'.
+	// Finally, set style.visibility to 'visible'.
+	ds.setVisibility = function(node, visibility){
+		ds.setStyle(node, 'visibility', (dojo.lang.isString(visibility) ? visibility : (visibility ? 'visible' : 'hidden')));
+	}
+
+	// isVisible() is true if the the computed visibility style for node is not 'hidden'
+	// FIXME: returns true if node is bad, isInvisible would be easier to make correct
+	ds.isVisible = function(node){
+		return (ds.getComputedStyle(node, 'visibility') != 'hidden');
+	}
+
+	// Call setVisibility() on node with the complement of isVisible(), then
+	// return the new value of isVisible()
+	ds.toggleVisibility = function(node){
+		return ds._toggle(node, ds.isVisible, ds.setVisibility);
+	}
+
+	// in: coordinate array [x,y,w,h] or dom node
+	// return: coordinate array
+	ds.toCoordinateArray = function(coords, includeScroll) {
+		if(dojo.lang.isArray(coords)){
+			// coords is already an array (of format [x,y,w,h]), just return it
+			while ( coords.length < 4 ) { coords.push(0); }
+			while ( coords.length > 4 ) { coords.pop(); }
+			var ret = coords;
+		} else {
+			// coords is an dom object (or dom object id); return it's coordinates
+			var node = dojo.byId(coords);
+			var pos = ds.getAbsolutePosition(node, includeScroll);
+			var ret = [
+				pos.x,
+				pos.y,
+				ds.getBorderBoxWidth(node),
+				ds.getBorderBoxHeight(node)
+			];
+		}
+		ret.x = ret[0];
+		ret.y = ret[1];
+		ret.w = ret[2];
+		ret.h = ret[3];
+		return ret;
+	};
+})();

Added: incubator/xap/trunk/src/dojo/src/svg.js
URL: http://svn.apache.org/viewvc/incubator/xap/trunk/src/dojo/src/svg.js?rev=417618&view=auto
==============================================================================
--- incubator/xap/trunk/src/dojo/src/svg.js (added)
+++ incubator/xap/trunk/src/dojo/src/svg.js Tue Jun 27 15:48:54 2006
@@ -0,0 +1,279 @@
+/*
+	Copyright (c) 2004-2006, The Dojo Foundation
+	All Rights Reserved.
+
+	Licensed under the Academic Free License version 2.1 or above OR the
+	modified BSD license. For more information on Dojo licensing, see:
+
+		http://dojotoolkit.org/community/licensing.shtml
+*/
+
+dojo.provide("dojo.svg");
+dojo.require("dojo.lang");
+dojo.require("dojo.dom");
+
+dojo.lang.mixin(dojo.svg, dojo.dom);
+
+dojo.svg.graphics=dojo.svg.g=new function(/* DomDocument */ d){
+	//	summary
+	//	Singleton to encapsulate SVG rendering functions.
+	this.suspend=function(){
+		//	summary
+		//	Suspend the rendering engine
+		try { d.documentElement.suspendRedraw(0); } catch(e){ }
+	};
+	this.resume=function(){
+		//	summary
+		//	Resume the rendering engine
+		try { d.documentElement.unsuspendRedraw(0); } catch(e){ }
+	};
+	this.force=function(){
+		//	summary
+		//	Force the render engine to redraw
+		try { d.documentElement.forceRedraw(); } catch(e){ }
+	};
+}(document);
+
+dojo.svg.animations=dojo.svg.anim=new function(/* DOMDocument */ d){
+	//	summary
+	//	Singleton to encapsulate SVG animation functionality.
+	this.arePaused=function(){
+		//	summary
+		//	check to see if all animations are paused
+		try {
+			return d.documentElement.animationsPaused();	//	bool
+		} catch(e){
+			return false;	//	bool
+		}
+	} ;
+	this.pause=function(){
+		//	summary
+		//	pause all animations
+		try { d.documentElement.pauseAnimations(); } catch(e){ }
+	};
+	this.resume=function(){
+		//	summary
+		//	resume all animations
+		try { d.documentElement.unpauseAnimations(); } catch(e){ }
+	};
+}(document);
+
+//	fixme: these functions should be mixed in from dojo.style, but dojo.style is HTML-centric and needs to change.
+dojo.svg.toCamelCase=function(/* string */ selector){
+	//	summary
+	//	converts a CSS-style selector to a camelCased one
+	var arr=selector.split('-'), cc=arr[0];
+	for(var i=1; i < arr.length; i++) {
+		cc += arr[i].charAt(0).toUpperCase() + arr[i].substring(1);
+	}
+	return cc;	// string
+};
+dojo.svg.toSelectorCase=function(/* string */ selector) {
+	//	summary
+	//	converts a camelCased selector to a CSS style one
+	return selector.replace(/([A-Z])/g, "-$1" ).toLowerCase();	//	string
+};
+dojo.svg.getStyle=function(/* SVGElement */ node, /* string */ cssSelector){
+	//	summary
+	//	get the computed style of selector for node.
+	return document.defaultView.getComputedStyle(node, cssSelector);	//	object
+};
+dojo.svg.getNumericStyle=function(/* SVGElement */ node, /* string */ cssSelector){
+	//	summary
+	//	return the numeric version of the computed style of selector on node.
+	return parseFloat(dojo.svg.getStyle(node, cssSelector));
+};
+
+//	fixme: there are different ways of doing the following, need to take into account
+dojo.svg.getOpacity=function(/* SVGElement */node){
+	//	summary
+	//	Return the opacity of the passed element
+	return Math.min(1.0, dojo.svg.getNumericStyle(node, "fill-opacity"));	//	float
+};
+dojo.svg.setOpacity=function(/* SVGElement */ node, /* float */ opacity){
+	//	summary
+	//	set the opacity of node using attributes.
+	node.setAttributeNS(this.xmlns.svg, "fill-opacity", opacity);
+	node.setAttributeNS(this.xmlns.svg, "stroke-opacity", opacity);
+};
+dojo.svg.clearOpacity=function(/* SVGElement */ node){
+	//	summary
+	//	Set any attributes setting opacity to opaque (1.0)
+	node.setAttributeNS(this.xmlns.svg, "fill-opacity", "1.0");
+	node.setAttributeNS(this.xmlns.svg, "stroke-opacity", "1.0");
+};
+
+/**
+ *	Coordinates and dimensions.
+ */
+
+// TODO ////////////////////////////////////////////////////////// TODO
+dojo.svg.getCoords=function(/* SVGElement */ node){
+	if (node.getBBox) {
+		var box=node.getBBox();
+		return { x: box.x, y: box.y };
+	}
+	return null;
+};
+dojo.svg.setCoords=function(node, coords){
+	var p=dojo.svg.getCoords();
+	if (!p) return;
+	var dx=p.x - coords.x;
+	var dy=p.y - coords.y;
+	dojo.svg.translate(node, dx, dy);
+};
+dojo.svg.getDimensions=function(node){
+	if (node.getBBox){
+		var box=node.getBBox();
+		return { width: box.width, height : box.height };
+	}
+	return null;
+};
+dojo.svg.setDimensions=function(node, dim){
+	//	will only support shape-based and container elements; path-based elements are ignored.
+	if (node.width){
+		node.width.baseVal.value=dim.width;
+		node.height.baseVal.value=dim.height;
+	}
+	else if (node.r){
+		node.r.baseVal.value=Math.min(dim.width, dim.height)/2;
+	}
+	else if (node.rx){
+		node.rx.baseVal.value=dim.width/2;
+		node.ry.baseVal.value=dim.height/2;
+	}
+};
+
+/**
+ *	Transformations.
+ */
+dojo.svg.translate=function(node, dx, dy){
+	if (node.transform && node.ownerSVGElement && node.ownerSVGElement.createSVGTransform){
+		var t=node.ownerSVGElement.createSVGTransform();
+		t.setTranslate(dx, dy);
+		node.transform.baseVal.appendItem(t);
+	}
+};
+dojo.svg.scale=function(node, scaleX, scaleY){
+	if (!scaleY) var scaleY=scaleX;
+	if (node.transform && node.ownerSVGElement && node.ownerSVGElement.createSVGTransform){
+		var t=node.ownerSVGElement.createSVGTransform();
+		t.setScale(scaleX, scaleY);
+		node.transform.baseVal.appendItem(t);
+	}
+};
+dojo.svg.rotate=function(node, ang, cx, cy){
+	if (node.transform && node.ownerSVGElement && node.ownerSVGElement.createSVGTransform){
+		var t=node.ownerSVGElement.createSVGTransform();
+		if (!cx) t.setMatrix(t.matrix.rotate(ang));
+		else t.setRotate(ang, cx, cy);
+		node.transform.baseVal.appendItem(t);
+	}
+};
+dojo.svg.skew=function(node, ang, axis){
+	var dir=axis || "x";
+	if (node.transform && node.ownerSVGElement && node.ownerSVGElement.createSVGTransform){
+		var t=node.ownerSVGElement.createSVGTransform();
+		if (dir != "x") t.setSkewY(ang);
+		else t.setSkewX(ang);
+		node.transform.baseVal.appendItem(t);
+	}
+};
+dojo.svg.flip=function(node, axis){
+	var dir=axis || "x";
+	if (node.transform && node.ownerSVGElement && node.ownerSVGElement.createSVGTransform){
+		var t=node.ownerSVGElement.createSVGTransform();
+		t.setMatrix((dir != "x") ? t.matrix.flipY() : t.matrix.flipX());
+		node.transform.baseVal.appendItem(t);
+	}
+};
+dojo.svg.invert=function(node){
+	if (node.transform && node.ownerSVGElement && node.ownerSVGElement.createSVGTransform){
+		var t=node.ownerSVGElement.createSVGTransform();
+		t.setMatrix(t.matrix.inverse());
+		node.transform.baseVal.appendItem(t);
+	}
+};
+dojo.svg.applyMatrix=function(node, a, b, c, d, e, f){
+	if (node.transform && node.ownerSVGElement && node.ownerSVGElement.createSVGTransform){
+		var m;
+		if (b){
+			var m=node.ownerSVGElement.createSVGMatrix();
+			m.a=a;
+			m.b=b;
+			m.c=c;
+			m.d=d;
+			m.e=e;
+			m.f=f;
+		} else m=a;
+		var t=node.ownerSVGElement.createSVGTransform();
+		t.setMatrix(m);
+		node.transform.baseVal.appendItem(t);
+	}
+};
+
+/**
+ *	Grouping and z-index operations.
+ */
+dojo.svg.group=function(nodes){
+	//	expect an array of nodes, attaches the group to the parent of the first node.
+	var p=nodes.item(0).parentNode;
+	var g=document.createElementNS(this.xmlns.svg, "g");
+	for (var i=0; i < nodes.length; i++) g.appendChild(nodes.item(i));
+	p.appendChild(g);
+	return g;
+};
+dojo.svg.ungroup=function(g){
+	//	puts the children of the group on the same level as group was.
+	var p=g.parentNode;
+	while (g.childNodes.length > 0) p.appendChild(g.childNodes.item(0));
+	p.removeChild(g);
+};
+//	if the node is part of a group, return the group, else return null.
+dojo.svg.getGroup=function(node){
+	//	if the node is part of a group, return the group, else return null.
+	var a=this.getAncestors(node);
+	for (var i=0; i < a.length; i++){
+		if (a[i].nodeType == this.ELEMENT_NODE && a[i].nodeName.toLowerCase() == "g")
+			return a[i];
+	}
+	return null;
+};
+dojo.svg.bringToFront=function(node){
+	var n=this.getGroup(node) || node;
+	n.ownerSVGElement.appendChild(n);
+};
+dojo.svg.sendToBack=function(node){
+	var n=this.getGroup(node) || node;
+	n.ownerSVGElement.insertBefore(n, n.ownerSVGElement.firstChild);
+};
+
+//	TODO: possibly push node up a level in the DOM if it's at the beginning or end of the childNodes list.
+dojo.svg.bringForward=function(node){
+	var n=this.getGroup(node) || node;
+	if (this.getLastChildElement(n.parentNode) != n){
+		this.insertAfter(n, this.getNextSiblingElement(n), true);
+	}
+};
+dojo.svg.sendBackward=function(node){
+	var n=this.getGroup(node) || node;
+	if (this.getFirstChildElement(n.parentNode) != n){
+		this.insertBefore(n, this.getPreviousSiblingElement(n), true);
+	}
+};
+// END TODO ////////////////////////////////////////////////////// TODO
+
+dojo.svg.createNodesFromText=function(/* string */ txt, /* bool? */ wrap){
+	//	summary
+	//	Create a list of nodes from text
+	var docFrag=(new DOMParser()).parseFromString(txt, "text/xml").normalize();
+	if(wrap){ 
+		return [docFrag.firstChild.cloneNode(true)];	//	array
+	}
+	var nodes=[];
+	for(var x=0; x<docFrag.childNodes.length; x++){
+		nodes.push(docFrag.childNodes.item(x).cloneNode(true));
+	}
+	return nodes;	// array
+}
+// vim:ts=4:noet:tw=0:

Added: incubator/xap/trunk/src/dojo/src/text/Builder.js
URL: http://svn.apache.org/viewvc/incubator/xap/trunk/src/dojo/src/text/Builder.js?rev=417618&view=auto
==============================================================================
--- incubator/xap/trunk/src/dojo/src/text/Builder.js (added)
+++ incubator/xap/trunk/src/dojo/src/text/Builder.js Tue Jun 27 15:48:54 2006
@@ -0,0 +1,16 @@
+/*
+	Copyright (c) 2004-2006, The Dojo Foundation
+	All Rights Reserved.
+
+	Licensed under the Academic Free License version 2.1 or above OR the
+	modified BSD license. For more information on Dojo licensing, see:
+
+		http://dojotoolkit.org/community/licensing.shtml
+*/
+
+dojo.provide("dojo.text.Builder");
+dojo.require("dojo.string.Builder");
+
+dojo.deprecated("dojo.text.Builder is deprecated, use dojo.string.Builder instead");
+
+dojo.text.Builder = dojo.string.Builder;

Propchange: incubator/xap/trunk/src/dojo/src/text/Builder.js
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/xap/trunk/src/dojo/src/text/String.js
URL: http://svn.apache.org/viewvc/incubator/xap/trunk/src/dojo/src/text/String.js?rev=417618&view=auto
==============================================================================
--- incubator/xap/trunk/src/dojo/src/text/String.js (added)
+++ incubator/xap/trunk/src/dojo/src/text/String.js Tue Jun 27 15:48:54 2006
@@ -0,0 +1,15 @@
+/*
+	Copyright (c) 2004-2006, The Dojo Foundation
+	All Rights Reserved.
+
+	Licensed under the Academic Free License version 2.1 or above OR the
+	modified BSD license. For more information on Dojo licensing, see:
+
+		http://dojotoolkit.org/community/licensing.shtml
+*/
+
+dojo.deprecated("dojo.text.String is being replaced by dojo.string");
+dojo.require("dojo.string");
+
+dojo.text = dojo.string;
+dojo.provide("dojo.text.String");

Added: incubator/xap/trunk/src/dojo/src/text/Text.js
URL: http://svn.apache.org/viewvc/incubator/xap/trunk/src/dojo/src/text/Text.js?rev=417618&view=auto
==============================================================================
--- incubator/xap/trunk/src/dojo/src/text/Text.js (added)
+++ incubator/xap/trunk/src/dojo/src/text/Text.js Tue Jun 27 15:48:54 2006
@@ -0,0 +1,15 @@
+/*
+	Copyright (c) 2004-2006, The Dojo Foundation
+	All Rights Reserved.
+
+	Licensed under the Academic Free License version 2.1 or above OR the
+	modified BSD license. For more information on Dojo licensing, see:
+
+		http://dojotoolkit.org/community/licensing.shtml
+*/
+
+dojo.deprecated("dojo.text.Text is being replaced by dojo.string");
+dojo.require("dojo.string");
+
+dojo.text = dojo.string;
+dojo.provide("dojo.text.Text");

Added: incubator/xap/trunk/src/dojo/src/text/__package__.js
URL: http://svn.apache.org/viewvc/incubator/xap/trunk/src/dojo/src/text/__package__.js?rev=417618&view=auto
==============================================================================
--- incubator/xap/trunk/src/dojo/src/text/__package__.js (added)
+++ incubator/xap/trunk/src/dojo/src/text/__package__.js Tue Jun 27 15:48:54 2006
@@ -0,0 +1,17 @@
+/*
+	Copyright (c) 2004-2006, The Dojo Foundation
+	All Rights Reserved.
+
+	Licensed under the Academic Free License version 2.1 or above OR the
+	modified BSD license. For more information on Dojo licensing, see:
+
+		http://dojotoolkit.org/community/licensing.shtml
+*/
+
+dojo.kwCompoundRequire({
+	common: [
+		"dojo.text.String",
+		"dojo.text.Builder"
+	]
+});
+dojo.provide("dojo.text.*");

Added: incubator/xap/trunk/src/dojo/src/text/textDirectory.js
URL: http://svn.apache.org/viewvc/incubator/xap/trunk/src/dojo/src/text/textDirectory.js?rev=417618&view=auto
==============================================================================
--- incubator/xap/trunk/src/dojo/src/text/textDirectory.js (added)
+++ incubator/xap/trunk/src/dojo/src/text/textDirectory.js Tue Jun 27 15:48:54 2006
@@ -0,0 +1,81 @@
+/*
+	Copyright (c) 2004-2006, The Dojo Foundation
+	All Rights Reserved.
+
+	Licensed under the Academic Free License version 2.1 or above OR the
+	modified BSD license. For more information on Dojo licensing, see:
+
+		http://dojotoolkit.org/community/licensing.shtml
+*/
+
+dojo.provide("dojo.text.textDirectory");
+dojo.provide("dojo.text.textDirectory.Property");
+dojo.provide("dojo.text.textDirectory.tokenise");
+dojo.require("dojo.string");
+
+/* adapted from Paul Sowden's iCalendar work */
+
+dojo.textDirectoryTokeniser = function () {}
+
+/*
+ * This class parses a single line from a text/directory file
+ * and returns an object with four named values; name, group, params
+ * and value. name, group and value are strings containing the original
+ * tokens unaltered and values is an array containing name/value pairs
+ * or a single name token packed into arrays.
+ */
+dojo.textDirectoryTokeniser.Property = function (line) {
+	// split into name/value pair
+	var left = dojo.string.trim(line.substring(0, line.indexOf(':')));
+	var right = dojo.string.trim(line.substr(line.indexOf(':') + 1));
+
+	// seperate name and paramters	
+	var parameters = dojo.string.splitEscaped(left,';');
+	this.name = parameters[0]
+	parameters.splice(0, 1);
+
+	// parse paramters
+	this.params = [];
+	for (var i = 0; i < parameters.length; i++) {
+		var arr = parameters[i].split("=");
+		var key = dojo.string.trim(arr[0].toUpperCase());
+		
+		if (arr.length == 1) { this.params.push([key]); continue; }
+		
+		var values = dojo.string.splitEscaped(arr[1],',');
+		for (var j = 0; j < values.length; j++) {
+			if (dojo.string.trim(values[j]) != '') {
+				this.params.push([key, dojo.string.trim(values[j])]);
+			}
+		}
+	}
+
+	// seperate group
+	if (this.name.indexOf('.') > 0) {
+		var arr = this.name.split('.');
+		this.group = arr[0];
+		this.name = arr[1];
+	}
+	
+	// don't do any parsing, leave to implementation
+	this.value = right;
+}
+
+
+// tokeniser, parses into an array of properties.
+dojo.textDirectoryTokeniser.tokenise = function (text) {
+	// normlize to one propterty per line and parse
+	nText = dojo.string.normalizeNewlines(text,"\n");
+	nText = nText.replace(/\n[ \t]/g, '');
+	nText = nText.replace(/\x00/g, '');
+		
+	var lines = nText.split("\n");
+	var properties = []
+
+	for (var i = 0; i < lines.length; i++) {
+		if (dojo.string.trim(lines[i]) == '') { continue; }
+		var prop = new dojo.textDirectoryTokeniser.Property(lines[i]);
+		properties.push(prop);
+	}
+	return properties;
+}

Propchange: incubator/xap/trunk/src/dojo/src/text/textDirectory.js
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/xap/trunk/src/dojo/src/undo/Manager.js
URL: http://svn.apache.org/viewvc/incubator/xap/trunk/src/dojo/src/undo/Manager.js?rev=417618&view=auto
==============================================================================
--- incubator/xap/trunk/src/dojo/src/undo/Manager.js (added)
+++ incubator/xap/trunk/src/dojo/src/undo/Manager.js Tue Jun 27 15:48:54 2006
@@ -0,0 +1,196 @@
+/*
+	Copyright (c) 2004-2006, The Dojo Foundation
+	All Rights Reserved.
+
+	Licensed under the Academic Free License version 2.1 or above OR the
+	modified BSD license. For more information on Dojo licensing, see:
+
+		http://dojotoolkit.org/community/licensing.shtml
+*/
+
+dojo.provide("dojo.undo.Manager");
+dojo.require("dojo.lang");
+
+dojo.undo.Manager = function(parent) {
+	this.clear();
+	this._parent = parent;
+};
+dojo.lang.extend(dojo.undo.Manager, {
+	_parent: null,
+	_undoStack: null,
+	_redoStack: null,
+	_currentManager: null,
+
+	canUndo: false,
+	canRedo: false,
+
+	isUndoing: false,
+	isRedoing: false,
+
+	// these events allow you to hook in and update your code (UI?) as necessary
+	onUndo: function(manager, item) {},
+	onRedo: function(manager, item) {},
+
+	// fired when you do *any* undo action, which means you'll have one for every item
+	// in a transaction. this is usually only useful for debugging
+	onUndoAny: function(manager, item) {},
+	onRedoAny: function(manager, item) {},
+
+	_updateStatus: function() {
+		this.canUndo = this._undoStack.length > 0;
+		this.canRedo = this._redoStack.length > 0;
+	},
+
+	clear: function() {
+		this._undoStack = [];
+		this._redoStack = [];
+		this._currentManager = this;
+
+		this.isUndoing = false;
+		this.isRedoing = false;
+
+		this._updateStatus();
+	},
+
+	undo: function() {
+		if(!this.canUndo) { return false; }
+
+		this.endAllTransactions();
+
+		this.isUndoing = true;
+		var top = this._undoStack.pop();
+		if(top instanceof this.constructor) {
+			top.undoAll();
+		} else {
+			top.undo();
+		}
+		if(top.redo) {
+			this._redoStack.push(top);
+		}
+		this.isUndoing = false;
+
+		this._updateStatus();
+		this.onUndo(this, top);
+		if(!(top instanceof this.constructor)) {
+			this.getTop().onUndoAny(this, top);
+		}
+		return true;
+	},
+
+	redo: function() {
+		if(!this.canRedo) { return false; }
+
+		this.isRedoing = true;
+		var top = this._redoStack.pop();
+		if(top instanceof this.constructor) {
+			top.redoAll();
+		} else {
+			top.redo();
+		}
+		this._undoStack.push(top);
+		this.isRedoing = false;
+
+		this._updateStatus();
+		this.onRedo(this, top);
+		if(!(top instanceof this.constructor)) {
+			this.getTop().onRedoAny(this, top);
+		}
+		return true;
+	},
+
+	undoAll: function() {
+		while(this._undoStack.length > 0) {
+			this.undo();
+		}
+	},
+
+	redoAll: function() {
+		while(this._redoStack.length > 0) {
+			this.redo();
+		}
+	},
+
+	push: function(undo, redo /* optional */, description /* optional */) {
+		if(!undo) { return; }
+
+		if(this._currentManager == this) {
+			this._undoStack.push({
+				undo: undo,
+				redo: redo,
+				description: description
+			});
+		} else {
+			this._currentManager.push.apply(this._currentManager, arguments);
+		}
+		// adding a new undo-able item clears out the redo stack
+		this._redoStack = [];
+		this._updateStatus();
+	},
+
+	concat: function(manager) {
+		if ( !manager ) { return; }
+
+		if (this._currentManager == this ) {
+			for(var x=0; x < manager._undoStack.length; x++) {
+				this._undoStack.push(manager._undoStack[x]);
+			}
+			this._updateStatus();
+		} else {
+			this._currentManager.concat.apply(this._currentManager, arguments);
+		}
+	},
+
+	beginTransaction: function(description /* optional */) {
+		if(this._currentManager == this) {
+			var mgr = new dojo.undo.Manager(this);
+			mgr.description = description ? description : "";
+			this._undoStack.push(mgr);
+			this._currentManager = mgr;
+			return mgr;
+		} else {
+			//for nested transactions need to make sure the top level _currentManager is set
+			this._currentManager = this._currentManager.beginTransaction.apply(this._currentManager, arguments);
+		}
+	},
+
+	endTransaction: function(flatten /* optional */) {
+		if(this._currentManager == this) {
+			if(this._parent) {
+				this._parent._currentManager = this._parent;
+				// don't leave empty transactions hangin' around
+				if(this._undoStack.length == 0 || flatten) {
+					var idx = dojo.lang.find(this._parent._undoStack, this);
+					if (idx >= 0) {
+						this._parent._undoStack.splice(idx, 1);
+						//add the current transaction to parents undo stack
+						if (flatten) {
+							for(var x=0; x < this._undoStack.length; x++){
+								this._parent._undoStack.splice(idx++, 0, this._undoStack[x]);
+							}
+							this._updateStatus();
+						}
+					}
+				}
+				return this._parent;
+			}
+		} else {
+			//for nested transactions need to make sure the top level _currentManager is set
+			this._currentManager = this._currentManager.endTransaction.apply(this._currentManager, arguments);
+		}
+	},
+
+	endAllTransactions: function() {
+		while(this._currentManager != this) {
+			this.endTransaction();
+		}
+	},
+
+	// find the top parent of an undo manager
+	getTop: function() {
+		if(this._parent) {
+			return this._parent.getTop();
+		} else {
+			return this;
+		}
+	}
+});

Added: incubator/xap/trunk/src/dojo/src/undo/__package__.js
URL: http://svn.apache.org/viewvc/incubator/xap/trunk/src/dojo/src/undo/__package__.js?rev=417618&view=auto
==============================================================================
--- incubator/xap/trunk/src/dojo/src/undo/__package__.js (added)
+++ incubator/xap/trunk/src/dojo/src/undo/__package__.js Tue Jun 27 15:48:54 2006
@@ -0,0 +1,12 @@
+/*
+	Copyright (c) 2004-2006, The Dojo Foundation
+	All Rights Reserved.
+
+	Licensed under the Academic Free License version 2.1 or above OR the
+	modified BSD license. For more information on Dojo licensing, see:
+
+		http://dojotoolkit.org/community/licensing.shtml
+*/
+
+dojo.require("dojo.undo.Manager");
+dojo.provide("dojo.undo.*");

Propchange: incubator/xap/trunk/src/dojo/src/undo/__package__.js
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/xap/trunk/src/dojo/src/undo/browser.js
URL: http://svn.apache.org/viewvc/incubator/xap/trunk/src/dojo/src/undo/browser.js?rev=417618&view=auto
==============================================================================
--- incubator/xap/trunk/src/dojo/src/undo/browser.js (added)
+++ incubator/xap/trunk/src/dojo/src/undo/browser.js Tue Jun 27 15:48:54 2006
@@ -0,0 +1,273 @@
+/*
+	Copyright (c) 2004-2006, The Dojo Foundation
+	All Rights Reserved.
+
+	Licensed under the Academic Free License version 2.1 or above OR the
+	modified BSD license. For more information on Dojo licensing, see:
+
+		http://dojotoolkit.org/community/licensing.shtml
+*/
+
+dojo.provide("dojo.undo.browser");
+dojo.require("dojo.io");
+
+try{
+	if((!djConfig["preventBackButtonFix"])&&(!dojo.hostenv.post_load_)){
+		document.write("<iframe style='border: 0px; width: 1px; height: 1px; position: absolute; bottom: 0px; right: 0px; visibility: visible;' name='djhistory' id='djhistory' src='"+(dojo.hostenv.getBaseScriptUri()+'iframe_history.html')+"'></iframe>");
+	}
+}catch(e){/* squelch */}
+
+/* NOTES:
+ *  Safari 1.2: 
+ *	back button "works" fine, however it's not possible to actually
+ *	DETECT that you've moved backwards by inspecting window.location.
+ *	Unless there is some other means of locating.
+ *	FIXME: perhaps we can poll on history.length?
+ *  Safari 2.0.3+ (and probably 1.3.2+):
+ *	works fine, except when changeUrl is used. When changeUrl is used,
+ *	Safari jumps all the way back to whatever page was shown before
+ *	the page that uses dojo.undo.browser support.
+ *  IE 5.5 SP2:
+ *	back button behavior is macro. It does not move back to the
+ *	previous hash value, but to the last full page load. This suggests
+ *	that the iframe is the correct way to capture the back button in
+ *	these cases.
+ *	Don't test this page using local disk for MSIE. MSIE will not create 
+ *	a history list for iframe_history.html if served from a file: URL. 
+ *	The XML served back from the XHR tests will also not be properly 
+ *	created if served from local disk. Serve the test pages from a web 
+ *	server to test in that browser.
+ *  IE 6.0:
+ *	same behavior as IE 5.5 SP2
+ * Firefox 1.0:
+ *	the back button will return us to the previous hash on the same
+ *	page, thereby not requiring an iframe hack, although we do then
+ *	need to run a timer to detect inter-page movement.
+ */
+dojo.undo.browser = {
+	initialHref: window.location.href,
+	initialHash: window.location.hash,
+
+	moveForward: false,
+	historyStack: [],
+	forwardStack: [],
+	historyIframe: null,
+	bookmarkAnchor: null,
+	locationTimer: null,
+
+	/**
+	 * setInitialState sets the state object and back callback for the very first page that is loaded.
+	 * It is recommended that you call this method as part of an event listener that is registered via
+	 * dojo.addOnLoad().
+	 */
+	setInitialState: function(args){
+		this.initialState = {"url": this.initialHref, "kwArgs": args, "urlHash": this.initialHash};
+	},
+
+	//FIXME: Would like to support arbitrary back/forward jumps. Have to rework iframeLoaded among other things.
+	//FIXME: is there a slight race condition in moz using change URL with the timer check and when
+	//       the hash gets set? I think I have seen a back/forward call in quick succession, but not consistent.
+	/**
+	 * addToHistory takes one argument, and it is an object that defines the following functions:
+	 * - To support getting back button notifications, the object argument should implement a
+	 *   function called either "back", "backButton", or "handle". The string "back" will be
+	 *   passed as the first and only argument to this callback.
+	 * - To support getting forward button notifications, the object argument should implement a
+	 *   function called either "forward", "forwardButton", or "handle". The string "forward" will be
+	 *   passed as the first and only argument to this callback.
+	 * - If you want the browser location string to change, define "changeUrl" on the object. If the
+	 *   value of "changeUrl" is true, then a unique number will be appended to the URL as a fragment
+	 *   identifier (http://some.domain.com/path#uniquenumber). If it is any other value that does
+	 *   not evaluate to false, that value will be used as the fragment identifier. For example,
+	 *   if changeUrl: 'page1', then the URL will look like: http://some.domain.com/path#page1
+	 *   
+	 * Full example:
+	 * 
+	 * dojo.undo.browser.addToHistory({
+	 *   back: function() { alert('back pressed'); },
+	 *   forward: function() { alert('forward pressed'); },
+	 *   changeUrl: true
+	 * });
+	 */
+	addToHistory: function(args){
+		var hash = null;
+		if(!this.historyIframe){
+			this.historyIframe = window.frames["djhistory"];
+		}
+		if(!this.bookmarkAnchor){
+			this.bookmarkAnchor = document.createElement("a");
+			(document.body||document.getElementsByTagName("body")[0]).appendChild(this.bookmarkAnchor);
+			this.bookmarkAnchor.style.display = "none";
+		}
+		if((!args["changeUrl"])||(dojo.render.html.ie)){
+			var url = dojo.hostenv.getBaseScriptUri()+"iframe_history.html?"+(new Date()).getTime();
+			this.moveForward = true;
+			dojo.io.setIFrameSrc(this.historyIframe, url, false);
+		}
+		if(args["changeUrl"]){
+			this.changingUrl = true;
+			hash = "#"+ ((args["changeUrl"]!==true) ? args["changeUrl"] : (new Date()).getTime());
+			setTimeout("window.location.href = '"+hash+"'; dojo.undo.browser.changingUrl = false;", 1);
+			this.bookmarkAnchor.href = hash;
+			
+			if(dojo.render.html.ie){
+				var oldCB = args["back"]||args["backButton"]||args["handle"];
+
+				//The function takes handleName as a parameter, in case the
+				//callback we are overriding was "handle". In that case,
+				//we will need to pass the handle name to handle.
+				var tcb = function(handleName){
+					if(window.location.hash != ""){
+						setTimeout("window.location.href = '"+hash+"';", 1);
+					}
+					//Use apply to set "this" to args, and to try to avoid memory leaks.
+					oldCB.apply(this, [handleName]);
+				}
+		
+				//Set interceptor function in the right place.
+				if(args["back"]){
+					args.back = tcb;
+				}else if(args["backButton"]){
+					args.backButton = tcb;
+				}else if(args["handle"]){
+					args.handle = tcb;
+				}
+		
+				//If addToHistory is called, then that means we prune the
+				//forward stack -- the user went back, then wanted to
+				//start a new forward path.
+				this.forwardStack = []; 
+				var oldFW = args["forward"]||args["forwardButton"]||args["handle"];
+		
+				//The function takes handleName as a parameter, in case the
+				//callback we are overriding was "handle". In that case,
+				//we will need to pass the handle name to handle.
+				var tfw = function(handleName){
+					if(window.location.hash != ""){
+						window.location.href = hash;
+					}
+					if(oldFW){ // we might not actually have one
+						//Use apply to set "this" to args, and to try to avoid memory leaks.
+						oldFW.apply(this, [handleName]);
+					}
+				}
+
+				//Set interceptor function in the right place.
+				if(args["forward"]){
+					args.forward = tfw;
+				}else if(args["forwardButton"]){
+					args.forwardButton = tfw;
+				}else if(args["handle"]){
+					args.handle = tfw;
+				}
+
+			}else if(dojo.render.html.moz){
+				// start the timer
+				if(!this.locationTimer){
+					this.locationTimer = setInterval("dojo.undo.browser.checkLocation();", 200);
+				}
+			}
+		}
+
+		this.historyStack.push({"url": url, "kwArgs": args, "urlHash": hash});
+	},
+
+	checkLocation: function(){
+		if (!this.changingUrl){
+			var hsl = this.historyStack.length;
+	
+			if((window.location.hash == this.initialHash)||(window.location.href == this.initialHref)&&(hsl == 1)){
+				// FIXME: could this ever be a forward button?
+				// we can't clear it because we still need to check for forwards. Ugg.
+				// clearInterval(this.locationTimer);
+				this.handleBackButton();
+				return;
+			}
+			// first check to see if we could have gone forward. We always halt on
+			// a no-hash item.
+			if(this.forwardStack.length > 0){
+				if(this.forwardStack[this.forwardStack.length-1].urlHash == window.location.hash){
+					this.handleForwardButton();
+					return;
+				}
+			}
+	
+			// ok, that didn't work, try someplace back in the history stack
+			if((hsl >= 2)&&(this.historyStack[hsl-2])){
+				if(this.historyStack[hsl-2].urlHash==window.location.hash){
+					this.handleBackButton();
+					return;
+				}
+			}
+		}
+	},
+
+	iframeLoaded: function(evt, ifrLoc){
+		var query = this._getUrlQuery(ifrLoc.href);
+		if(query == null){ 
+			// alert("iframeLoaded");
+			// we hit the end of the history, so we should go back
+			if(this.historyStack.length == 1){
+				this.handleBackButton();
+			}
+			return;
+		}
+		if(this.moveForward){
+			// we were expecting it, so it's not either a forward or backward movement
+			this.moveForward = false;
+			return;
+		}
+
+		//Check the back stack first, since it is more likely.
+		//Note that only one step back or forward is supported.
+		if(this.historyStack.length >= 2 && query == this._getUrlQuery(this.historyStack[this.historyStack.length-2].url)){
+			this.handleBackButton();
+		}
+		else if(this.forwardStack.length > 0 && query == this._getUrlQuery(this.forwardStack[this.forwardStack.length-1].url)){
+			this.handleForwardButton();
+		}
+	},
+
+	handleBackButton: function(){
+		//The "current" page is always at the top of the history stack.
+		var current = this.historyStack.pop();
+		if(!current){ return; }
+		var last = this.historyStack[this.historyStack.length-1];
+		if(!last && this.historyStack.length == 0){
+			last = this.initialState;
+		}
+		if (last){
+			if(last.kwArgs["back"]){
+				last.kwArgs["back"]();
+			}else if(last.kwArgs["backButton"]){
+				last.kwArgs["backButton"]();
+			}else if(last.kwArgs["handle"]){
+				last.kwArgs.handle("back");
+			}
+		}
+		this.forwardStack.push(current);
+	},
+
+	handleForwardButton: function(){
+		var last = this.forwardStack.pop();
+		if(!last){ return; }
+		if(last.kwArgs["forward"]){
+			last.kwArgs.forward();
+		}else if(last.kwArgs["forwardButton"]){
+			last.kwArgs.forwardButton();
+		}else if(last.kwArgs["handle"]){
+			last.kwArgs.handle("forward");
+		}
+		this.historyStack.push(last);
+	},
+
+	_getUrlQuery: function(url){
+		var segments = url.split("?");
+		if (segments.length < 2){
+			return null;
+		}
+		else{
+			return segments[1];
+		}
+	}
+}

Propchange: incubator/xap/trunk/src/dojo/src/undo/browser.js
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/xap/trunk/src/dojo/src/uri/Uri.js
URL: http://svn.apache.org/viewvc/incubator/xap/trunk/src/dojo/src/uri/Uri.js?rev=417618&view=auto
==============================================================================
--- incubator/xap/trunk/src/dojo/src/uri/Uri.js (added)
+++ incubator/xap/trunk/src/dojo/src/uri/Uri.js Tue Jun 27 15:48:54 2006
@@ -0,0 +1,108 @@
+/*
+	Copyright (c) 2004-2006, The Dojo Foundation
+	All Rights Reserved.
+
+	Licensed under the Academic Free License version 2.1 or above OR the
+	modified BSD license. For more information on Dojo licensing, see:
+
+		http://dojotoolkit.org/community/licensing.shtml
+*/
+
+dojo.provide("dojo.uri.Uri");
+
+dojo.uri = new function() {
+	this.joinPath = function() {
+		// DEPRECATED: use the dojo.uri.Uri object instead
+		var arr = [];
+		for(var i = 0; i < arguments.length; i++) { arr.push(arguments[i]); }
+		return arr.join("/").replace(/\/{2,}/g, "/").replace(/((https*|ftps*):)/i, "$1/");
+	}
+	
+	this.dojoUri = function (uri) {
+		// returns a Uri object resolved relative to the dojo root
+		return new dojo.uri.Uri(dojo.hostenv.getBaseScriptUri(), uri);
+	}
+		
+	this.Uri = function (/*uri1, uri2, [...]*/) {
+		// An object representing a Uri.
+		// Each argument is evaluated in order relative to the next until
+		// a conanical uri is producued. To get an absolute Uri relative
+		// to the current document use
+		//      new dojo.uri.Uri(document.baseURI, uri)
+
+		// TODO: support for IPv6, see RFC 2732
+
+		// resolve uri components relative to each other
+		var uri = arguments[0];
+		for (var i = 1; i < arguments.length; i++) {
+			if(!arguments[i]) { continue; }
+
+			// Safari doesn't support this.constructor so we have to be explicit
+			var relobj = new dojo.uri.Uri(arguments[i].toString());
+			var uriobj = new dojo.uri.Uri(uri.toString());
+
+			if (relobj.path == "" && relobj.scheme == null &&
+				relobj.authority == null && relobj.query == null) {
+				if (relobj.fragment != null) { uriobj.fragment = relobj.fragment; }
+				relobj = uriobj;
+			} else if (relobj.scheme == null) {
+				relobj.scheme = uriobj.scheme;
+			
+				if (relobj.authority == null) {
+					relobj.authority = uriobj.authority;
+					
+					if (relobj.path.charAt(0) != "/") {
+						var path = uriobj.path.substring(0,
+							uriobj.path.lastIndexOf("/") + 1) + relobj.path;
+
+						var segs = path.split("/");
+						for (var j = 0; j < segs.length; j++) {
+							if (segs[j] == ".") {
+								if (j == segs.length - 1) { segs[j] = ""; }
+								else { segs.splice(j, 1); j--; }
+							} else if (j > 0 && !(j == 1 && segs[0] == "") &&
+								segs[j] == ".." && segs[j-1] != "..") {
+
+								if (j == segs.length - 1) { segs.splice(j, 1); segs[j - 1] = ""; }
+								else { segs.splice(j - 1, 2); j -= 2; }
+							}
+						}
+						relobj.path = segs.join("/");
+					}
+				}
+			}
+
+			uri = "";
+			if (relobj.scheme != null) { uri += relobj.scheme + ":"; }
+			if (relobj.authority != null) { uri += "//" + relobj.authority; }
+			uri += relobj.path;
+			if (relobj.query != null) { uri += "?" + relobj.query; }
+			if (relobj.fragment != null) { uri += "#" + relobj.fragment; }
+		}
+
+		this.uri = uri.toString();
+
+		// break the uri into its main components
+		var regexp = "^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\\?([^#]*))?(#(.*))?$";
+	    var r = this.uri.match(new RegExp(regexp));
+
+		this.scheme = r[2] || (r[1] ? "" : null);
+		this.authority = r[4] || (r[3] ? "" : null);
+		this.path = r[5]; // can never be undefined
+		this.query = r[7] || (r[6] ? "" : null);
+		this.fragment  = r[9] || (r[8] ? "" : null);
+		
+		if (this.authority != null) {
+			// server based naming authority
+			regexp = "^((([^:]+:)?([^@]+))@)?([^:]*)(:([0-9]+))?$";
+			r = this.authority.match(new RegExp(regexp));
+			
+			this.user = r[3] || null;
+			this.password = r[4] || null;
+			this.host = r[5];
+			this.port = r[7] || null;
+		}
+	
+		this.toString = function(){ return this.uri; }
+	}
+};

Propchange: incubator/xap/trunk/src/dojo/src/uri/Uri.js
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/xap/trunk/src/dojo/src/uri/__package__.js
URL: http://svn.apache.org/viewvc/incubator/xap/trunk/src/dojo/src/uri/__package__.js?rev=417618&view=auto
==============================================================================
--- incubator/xap/trunk/src/dojo/src/uri/__package__.js (added)
+++ incubator/xap/trunk/src/dojo/src/uri/__package__.js Tue Jun 27 15:48:54 2006
@@ -0,0 +1,14 @@
+/*
+	Copyright (c) 2004-2006, The Dojo Foundation
+	All Rights Reserved.
+
+	Licensed under the Academic Free License version 2.1 or above OR the
+	modified BSD license. For more information on Dojo licensing, see:
+
+		http://dojotoolkit.org/community/licensing.shtml
+*/
+
+dojo.kwCompoundRequire({
+	common: ["dojo.uri.Uri", false, false]
+});
+dojo.provide("dojo.uri.*");

Propchange: incubator/xap/trunk/src/dojo/src/uri/__package__.js
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/xap/trunk/src/dojo/src/uuid/LightweightGenerator.js
URL: http://svn.apache.org/viewvc/incubator/xap/trunk/src/dojo/src/uuid/LightweightGenerator.js?rev=417618&view=auto
==============================================================================
--- incubator/xap/trunk/src/dojo/src/uuid/LightweightGenerator.js (added)
+++ incubator/xap/trunk/src/dojo/src/uuid/LightweightGenerator.js Tue Jun 27 15:48:54 2006
@@ -0,0 +1,82 @@
+/*
+	Copyright (c) 2004-2006, The Dojo Foundation
+	All Rights Reserved.
+
+	Licensed under the Academic Free License version 2.1 or above OR the
+	modified BSD license. For more information on Dojo licensing, see:
+
+		http://dojotoolkit.org/community/licensing.shtml
+*/
+
+dojo.provide("dojo.uuid.LightweightGenerator");
+
+/**
+ * The LightweightGenerator is intended to be small and fast,
+ * but not necessarily good.
+ * 
+ * Small: The LightweightGenerator has a small footprint. 
+ * Once comments are stripped, it's only about 25 lines of 
+ * code, and it doesn't dojo.require() any other packages.
+ *
+ * Fast: The LightweightGenerator can generate lots of new 
+ * UUIDs fairly quickly (at least, more quickly than the other 
+ * dojo UUID generators).
+ *
+ * Not necessarily good: We use Math.random() as our source
+ * of randomness, which may or may not provide much randomness. 
+ */
+dojo.uuid.LightweightGenerator = new function() {
+
+	var HEX_RADIX = 16;
+
+// --------------------------------------------------
+// Private functions
+// --------------------------------------------------
+	function _generateRandomEightCharacterHexString() {
+		// Make random32bitNumber be a randomly generated floating point number
+		// between 0 and (4,294,967,296 - 1), inclusive.
+		var random32bitNumber = Math.floor( (Math.random() % 1) * Math.pow(2, 32) );
+		var eightCharacterHexString = random32bitNumber.toString(HEX_RADIX);
+		while (eightCharacterHexString.length < 8) {
+			eightCharacterHexString = "0" + eightCharacterHexString;
+		}
+		return eightCharacterHexString; // for example: "3B12F1DF"
+	}
+
+// --------------------------------------------------
+// Public functions
+// --------------------------------------------------
+
+/**
+ * This function generates random UUIDs, meaning "version 4" UUIDs.
+ * For example, a typical generated value would be something like
+ * "3b12f1df-5232-4804-897e-917bf397618a".
+ *
+ * Examples:
+ * <pre>
+ *   var string = dojo.uuid.LightweightGenerator.generate();
+ *   var string = dojo.uuid.LightweightGenerator.generate(String);
+ *   var uuid   = dojo.uuid.LightweightGenerator.generate(dojo.uuid.Uuid);
+ * </pre>
+ *
+ * @param	returnType	Optional. The type of instance to return.
+ * @return	A newly generated version 4 UUID.
+ */
+	this.generate = function(returnType) {
+		var hyphen = "-";
+		var versionCodeForRandomlyGeneratedUuids = "4"; // 8 == binary2hex("0100")
+		var variantCodeForDCEUuids = "8"; // 8 == binary2hex("1000")
+		var a = _generateRandomEightCharacterHexString();
+		var b = _generateRandomEightCharacterHexString();
+		b = b.substring(0, 4) + hyphen + versionCodeForRandomlyGeneratedUuids + b.substring(5, 8);
+		var c = _generateRandomEightCharacterHexString();
+		c = variantCodeForDCEUuids + c.substring(1, 4) + hyphen + c.substring(4, 8);
+		var d = _generateRandomEightCharacterHexString();
+		var returnValue = a + hyphen + b + hyphen + c + d;
+		returnValue = returnValue.toLowerCase();
+		if (returnType && (returnType != String)) {
+			returnValue = new returnType(returnValue);
+		}
+		return returnValue;
+	};
+}();

Propchange: incubator/xap/trunk/src/dojo/src/uuid/LightweightGenerator.js
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/xap/trunk/src/dojo/src/uuid/NameBasedGenerator.js
URL: http://svn.apache.org/viewvc/incubator/xap/trunk/src/dojo/src/uuid/NameBasedGenerator.js?rev=417618&view=auto
==============================================================================
--- incubator/xap/trunk/src/dojo/src/uuid/NameBasedGenerator.js (added)
+++ incubator/xap/trunk/src/dojo/src/uuid/NameBasedGenerator.js Tue Jun 27 15:48:54 2006
@@ -0,0 +1,43 @@
+/*
+	Copyright (c) 2004-2006, The Dojo Foundation
+	All Rights Reserved.
+
+	Licensed under the Academic Free License version 2.1 or above OR the
+	modified BSD license. For more information on Dojo licensing, see:
+
+		http://dojotoolkit.org/community/licensing.shtml
+*/
+
+dojo.provide("dojo.uuid.NameBasedGenerator");
+
+dojo.uuid.NameBasedGenerator = new function() {
+
+/**
+ * This function generates name-based UUIDs, meaning "version 3" 
+ * and "version 5" UUIDs.
+ *
+ * Examples:
+ * <pre>
+ *   var string = dojo.uuid.NameBasedGenerator.generate();
+ *   var string = dojo.uuid.NameBasedGenerator.generate(String);
+ *   var uuid   = dojo.uuid.NameBasedGenerator.generate(dojo.uuid.Uuid);
+ * </pre>
+ *
+ * @param	returnType	Optional. The type of instance to return.
+ * @return	A newly generated version 3 or version 5 UUID.
+ */
+	this.generate = function(returnType) {
+		dojo.unimplemented('dojo.uuid.NameBasedGenerator.generate');
+		
+		// FIXME:
+		// For an algorithm to generate name-based UUIDs, 
+		// see sections 4.3 of RFC 4122:
+		//  http://www.ietf.org/rfc/rfc4122.txt
+		
+		var returnValue = "00000000-0000-0000-0000-000000000000"; // FIXME
+		if (returnType && (returnType != String)) {
+			returnValue = new returnType(returnValue);
+		}
+		return returnValue;
+	};
+}();
\ No newline at end of file

Propchange: incubator/xap/trunk/src/dojo/src/uuid/NameBasedGenerator.js
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/xap/trunk/src/dojo/src/uuid/NilGenerator.js
URL: http://svn.apache.org/viewvc/incubator/xap/trunk/src/dojo/src/uuid/NilGenerator.js?rev=417618&view=auto
==============================================================================
--- incubator/xap/trunk/src/dojo/src/uuid/NilGenerator.js (added)
+++ incubator/xap/trunk/src/dojo/src/uuid/NilGenerator.js Tue Jun 27 15:48:54 2006
@@ -0,0 +1,38 @@
+/*
+	Copyright (c) 2004-2006, The Dojo Foundation
+	All Rights Reserved.
+
+	Licensed under the Academic Free License version 2.1 or above OR the
+	modified BSD license. For more information on Dojo licensing, see:
+
+		http://dojotoolkit.org/community/licensing.shtml
+*/
+
+dojo.provide("dojo.uuid.NilGenerator");
+
+dojo.uuid.NilGenerator = new function() {
+
+/**
+ * This function returns the Nil UUID: 
+ * "00000000-0000-0000-0000-000000000000".
+ * The Nil UUID is described in section 4.1.7 of
+ * RFC 4122: http://www.ietf.org/rfc/rfc4122.txt
+ *
+ * Examples:
+ * <pre>
+ *   var string = dojo.uuid.NilGenerator.generate();
+ *   var string = dojo.uuid.NilGenerator.generate(String);
+ *   var uuid   = dojo.uuid.NilGenerator.generate(dojo.uuid.Uuid);
+ * </pre>
+ *
+ * @param	returnType	Optional. The type of instance to return.
+ * @return	The nil UUID.
+ */
+	this.generate = function(returnType) {
+		var returnValue = "00000000-0000-0000-0000-000000000000";
+		if (returnType && (returnType != String)) {
+			returnValue = new returnType(returnValue);
+		}
+		return returnValue;
+	};
+}();
\ No newline at end of file

Added: incubator/xap/trunk/src/dojo/src/uuid/RandomGenerator.js
URL: http://svn.apache.org/viewvc/incubator/xap/trunk/src/dojo/src/uuid/RandomGenerator.js?rev=417618&view=auto
==============================================================================
--- incubator/xap/trunk/src/dojo/src/uuid/RandomGenerator.js (added)
+++ incubator/xap/trunk/src/dojo/src/uuid/RandomGenerator.js Tue Jun 27 15:48:54 2006
@@ -0,0 +1,44 @@
+/*
+	Copyright (c) 2004-2006, The Dojo Foundation
+	All Rights Reserved.
+
+	Licensed under the Academic Free License version 2.1 or above OR the
+	modified BSD license. For more information on Dojo licensing, see:
+
+		http://dojotoolkit.org/community/licensing.shtml
+*/
+
+dojo.provide("dojo.uuid.RandomGenerator");
+
+dojo.uuid.RandomGenerator = new function() {
+
+/**
+ * This function generates random UUIDs, meaning "version 4" UUIDs.
+ * For example, a typical generated value would be something like
+ * "3b12f1df-5232-4804-897e-917bf397618a".
+ *
+ * Examples:
+ * <pre>
+ *   var string = dojo.uuid.RandomGenerator.generate();
+ *   var string = dojo.uuid.RandomGenerator.generate(String);
+ *   var uuid   = dojo.uuid.RandomGenerator.generate(dojo.uuid.Uuid);
+ * </pre>
+ *
+ * @param	returnType	Optional. The type of instance to return.
+ * @return	A newly generated version 4 UUID.
+ */
+	this.generate = function(returnType) {
+		dojo.unimplemented('dojo.uuid.RandomGenerator.generate');
+		
+		// FIXME:
+		// For an algorithm to generate a random UUID, see
+		// sections 4.4 and 4.5 of RFC 4122:
+		//  http://www.ietf.org/rfc/rfc4122.txt
+		
+		var returnValue = "00000000-0000-0000-0000-000000000000"; // FIXME
+		if (returnType && (returnType != String)) {
+			returnValue = new returnType(returnValue);
+		}
+		return returnValue;
+	};
+}();

Added: incubator/xap/trunk/src/dojo/src/uuid/TimeBasedGenerator.js
URL: http://svn.apache.org/viewvc/incubator/xap/trunk/src/dojo/src/uuid/TimeBasedGenerator.js?rev=417618&view=auto
==============================================================================
--- incubator/xap/trunk/src/dojo/src/uuid/TimeBasedGenerator.js (added)
+++ incubator/xap/trunk/src/dojo/src/uuid/TimeBasedGenerator.js Tue Jun 27 15:48:54 2006
@@ -0,0 +1,391 @@
+/*
+	Copyright (c) 2004-2006, The Dojo Foundation
+	All Rights Reserved.
+
+	Licensed under the Academic Free License version 2.1 or above OR the
+	modified BSD license. For more information on Dojo licensing, see:
+
+		http://dojotoolkit.org/community/licensing.shtml
+*/
+
+dojo.provide("dojo.uuid.TimeBasedGenerator");
+dojo.require("dojo.lang.*");
+
+dojo.uuid.TimeBasedGenerator = new function() {
+
+// --------------------------------------------------
+// Public constants
+// --------------------------------------------------
+	// Number of hours between October 15, 1582 and January 1, 1970:
+	this.GREGORIAN_CHANGE_OFFSET_IN_HOURS = 3394248;
+	
+	// Number of seconds between October 15, 1582 and January 1, 1970:
+	//   this.GREGORIAN_CHANGE_OFFSET_IN_SECONDS = 12219292800;	
+	
+// --------------------------------------------------
+// Private variables
+// --------------------------------------------------
+	var _uuidPseudoNodeString = null;
+	var _uuidClockSeqString = null;
+	var _dateValueOfPreviousUuid = null;
+	var _nextIntraMillisecondIncrement = 0;
+	var _cachedMillisecondsBetween1582and1970 = null;
+	var _cachedHundredNanosecondIntervalsPerMillisecond = null;
+	var _uniformNode = null;
+	var HEX_RADIX = 16;
+
+// --------------------------------------------------
+// Private functions
+// --------------------------------------------------
+
+/**
+ * Given an array which holds a 64-bit number broken into 4 16-bit elements,
+ * this method carries any excess bits (greater than 16-bits) from each array
+ * element into the next.
+ *
+ * @param	arrayA	An array with 4 elements, each of which is a 16-bit number.
+ */
+	function _carry(arrayA) {
+		arrayA[2] += arrayA[3] >>> 16;
+		arrayA[3] &= 0xFFFF;
+		arrayA[1] += arrayA[2] >>> 16;
+		arrayA[2] &= 0xFFFF;
+		arrayA[0] += arrayA[1] >>> 16;
+		arrayA[1] &= 0xFFFF;
+		dojo.lang.assert((arrayA[0] >>> 16) === 0);
+	}
+
+/**
+ * Given a floating point number, this method returns an array which holds a
+ * 64-bit number broken into 4 16-bit elements.
+ *
+ * @param	x	A floating point number.
+ * @return   An array with 4 elements, each of which is a 16-bit number.
+ */
+	function _get64bitArrayFromFloat(x) {
+		var result = new Array(0, 0, 0, 0);
+		result[3] = x % 0x10000;
+		x -= result[3];
+		x /= 0x10000;
+		result[2] = x % 0x10000;
+		x -= result[2];
+		x /= 0x10000;
+		result[1] = x % 0x10000;
+		x -= result[1];
+		x /= 0x10000;
+		result[0] = x;
+		return result;
+	}
+
+/**
+ * Takes two arrays, each of which holds a 64-bit number broken into 4
+ * 16-bit elements, and returns a new array that holds a 64-bit number
+ * that is the sum of the two original numbers.
+ *
+ * @param	arrayA	An array with 4 elements, each of which is a 16-bit number.
+ * @param	arrayB	An array with 4 elements, each of which is a 16-bit number.
+ * @return   An array with 4 elements, each of which is a 16-bit number.
+ */
+	function _addTwo64bitArrays(arrayA, arrayB) {
+		dojo.lang.assertType(arrayA, Array);
+		dojo.lang.assertType(arrayB, Array);
+		dojo.lang.assert(arrayA.length == 4);
+		dojo.lang.assert(arrayB.length == 4);
+	
+		var result = new Array(0, 0, 0, 0);
+		result[3] = arrayA[3] + arrayB[3];
+		result[2] = arrayA[2] + arrayB[2];
+		result[1] = arrayA[1] + arrayB[1];
+		result[0] = arrayA[0] + arrayB[0];
+		_carry(result);
+		return result;
+	}
+
+/**
+ * Takes two arrays, each of which holds a 64-bit number broken into 4
+ * 16-bit elements, and returns a new array that holds a 64-bit number
+ * that is the product of the two original numbers.
+ *
+ * @param	arrayA	An array with 4 elements, each of which is a 16-bit number.
+ * @param	arrayB	An array with 4 elements, each of which is a 16-bit number.
+ * @return   An array with 4 elements, each of which is a 16-bit number.
+ */
+	function _multiplyTwo64bitArrays(arrayA, arrayB) {
+		dojo.lang.assertType(arrayA, Array);
+		dojo.lang.assertType(arrayB, Array);
+		dojo.lang.assert(arrayA.length == 4);
+		dojo.lang.assert(arrayB.length == 4);
+	
+		var overflow = false;
+		if (arrayA[0] * arrayB[0] !== 0) { overflow = true; }
+		if (arrayA[0] * arrayB[1] !== 0) { overflow = true; }
+		if (arrayA[0] * arrayB[2] !== 0) { overflow = true; }
+		if (arrayA[1] * arrayB[0] !== 0) { overflow = true; }
+		if (arrayA[1] * arrayB[1] !== 0) { overflow = true; }
+		if (arrayA[2] * arrayB[0] !== 0) { overflow = true; }
+		dojo.lang.assert(!overflow);
+	
+		var result = new Array(0, 0, 0, 0);
+		result[0] += arrayA[0] * arrayB[3];
+		_carry(result);
+		result[0] += arrayA[1] * arrayB[2];
+		_carry(result);
+		result[0] += arrayA[2] * arrayB[1];
+		_carry(result);
+		result[0] += arrayA[3] * arrayB[0];
+		_carry(result);
+		result[1] += arrayA[1] * arrayB[3];
+		_carry(result);
+		result[1] += arrayA[2] * arrayB[2];
+		_carry(result);
+		result[1] += arrayA[3] * arrayB[1];
+		_carry(result);
+		result[2] += arrayA[2] * arrayB[3];
+		_carry(result);
+		result[2] += arrayA[3] * arrayB[2];
+		_carry(result);
+		result[3] += arrayA[3] * arrayB[3];
+		_carry(result);
+		return result;
+	}
+
+/**
+ * Pads a string with leading zeros and returns the result.
+ * For example:
+ * <pre>
+ *   result = _padWithLeadingZeros("abc", 6);
+ *   dojo.lang.assert(result == "000abc");
+ * </pre>
+ *
+ * @param	string	A string to add padding to.
+ * @param	desiredLength	The number of characters the return string should have.
+ * @return   A string.
+ */
+	function _padWithLeadingZeros(string, desiredLength) {
+		while (string.length < desiredLength) {
+			string = "0" + string;
+		}
+		return string;
+	}
+
+/**
+ * Returns a randomly generated 8-character string of hex digits.
+ *
+ * @return   An 8-character hex string.
+ */
+	function _generateRandomEightCharacterHexString() {
+		// FIXME: This probably isn't a very high quality random number.
+	
+		// Make random32bitNumber be a randomly generated floating point number
+		// between 0 and (4,294,967,296 - 1), inclusive.
+		var random32bitNumber = Math.floor( (Math.random() % 1) * Math.pow(2, 32) );
+	
+		var eightCharacterString = random32bitNumber.toString(HEX_RADIX);
+		while (eightCharacterString.length < 8) {
+			eightCharacterString = "0" + eightCharacterString;
+		}
+		return eightCharacterString;
+	}
+
+/**
+ * Generates a time-based UUID, meaning a version 1 UUID.  JavaScript
+ * code running in a browser doesn't have access to the IEEE 802.3 address
+ * of the computer, so if a node value isn't supplied, we generate a random 
+ * pseudonode value instead.
+ *
+ * @param	node	Optional. A 12-character string to use as the node in the new UUID.
+ * @return   Returns a 36 character string, which will look something like "b4308fb0-86cd-11da-a72b-0800200c9a66".
+ */
+	function _generateUuidString(node) {
+		dojo.lang.assertType(node, [String, "optional"]);
+		if (node) {
+			dojo.lang.assert(node.length == 12);
+		} else {
+			if (_uniformNode) {
+				node = _uniformNode;
+			} else {
+				if (!_uuidPseudoNodeString) {
+					var pseudoNodeIndicatorBit = 0x8000;
+					var random15bitNumber = Math.floor( (Math.random() % 1) * Math.pow(2, 15) );
+					var leftmost4HexCharacters = (pseudoNodeIndicatorBit | random15bitNumber).toString(HEX_RADIX);
+					_uuidPseudoNodeString = leftmost4HexCharacters + _generateRandomEightCharacterHexString();
+				}
+				node = _uuidPseudoNodeString;
+			}
+		}
+		if (!_uuidClockSeqString) {
+			var variantCodeForDCEUuids = 0x8000; // 10--------------, i.e. uses only first two of 16 bits.
+			var random14bitNumber = Math.floor( (Math.random() % 1) * Math.pow(2, 14) );
+			_uuidClockSeqString = (variantCodeForDCEUuids | random14bitNumber).toString(HEX_RADIX);
+		}
+	
+		// Maybe we should think about trying to make the code more readable to
+		// newcomers by creating a class called "WholeNumber" that encapsulates
+		// the methods and data structures for working with these arrays that
+		// hold 4 16-bit numbers?  And then these variables below have names
+		// like "wholeSecondsPerHour" rather than "arraySecondsPerHour"?
+		var now = new Date();
+		var millisecondsSince1970 = now.valueOf(); // milliseconds since midnight 01 January, 1970 UTC.
+		var nowArray = _get64bitArrayFromFloat(millisecondsSince1970);
+		if (!_cachedMillisecondsBetween1582and1970) {
+			var arraySecondsPerHour = _get64bitArrayFromFloat(60 * 60);
+			var arrayHoursBetween1582and1970 = _get64bitArrayFromFloat(dojo.uuid.TimeBasedGenerator.GREGORIAN_CHANGE_OFFSET_IN_HOURS);
+			var arraySecondsBetween1582and1970 = _multiplyTwo64bitArrays(arrayHoursBetween1582and1970, arraySecondsPerHour);
+			var arrayMillisecondsPerSecond = _get64bitArrayFromFloat(1000);
+			_cachedMillisecondsBetween1582and1970 = _multiplyTwo64bitArrays(arraySecondsBetween1582and1970, arrayMillisecondsPerSecond);
+			_cachedHundredNanosecondIntervalsPerMillisecond = _get64bitArrayFromFloat(10000);
+		}
+		var arrayMillisecondsSince1970 = nowArray;
+		var arrayMillisecondsSince1582 = _addTwo64bitArrays(_cachedMillisecondsBetween1582and1970, arrayMillisecondsSince1970);
+		var arrayHundredNanosecondIntervalsSince1582 = _multiplyTwo64bitArrays(arrayMillisecondsSince1582, _cachedHundredNanosecondIntervalsPerMillisecond);
+	
+		if (now.valueOf() == _dateValueOfPreviousUuid) {
+			arrayHundredNanosecondIntervalsSince1582[3] += _nextIntraMillisecondIncrement;
+			_carry(arrayHundredNanosecondIntervalsSince1582);
+			_nextIntraMillisecondIncrement += 1;
+			if (_nextIntraMillisecondIncrement == 10000) {
+				// If we've gotten to here, it means we've already generated 10,000
+				// UUIDs in this single millisecond, which is the most that the UUID
+				// timestamp field allows for.  So now we'll just sit here and wait
+				// for a fraction of a millisecond, so as to ensure that the next
+				// time this method is called there will be a different millisecond
+				// value in the timestamp field.
+				while (now.valueOf() == _dateValueOfPreviousUuid) {
+					now = new Date();
+				}
+			}
+		} else {
+			_dateValueOfPreviousUuid = now.valueOf();
+			_nextIntraMillisecondIncrement = 1;
+		}
+	
+		var hexTimeLowLeftHalf  = arrayHundredNanosecondIntervalsSince1582[2].toString(HEX_RADIX);
+		var hexTimeLowRightHalf = arrayHundredNanosecondIntervalsSince1582[3].toString(HEX_RADIX);
+		var hexTimeLow = _padWithLeadingZeros(hexTimeLowLeftHalf, 4) + _padWithLeadingZeros(hexTimeLowRightHalf, 4);
+		var hexTimeMid = arrayHundredNanosecondIntervalsSince1582[1].toString(HEX_RADIX);
+		hexTimeMid = _padWithLeadingZeros(hexTimeMid, 4);
+		var hexTimeHigh = arrayHundredNanosecondIntervalsSince1582[0].toString(HEX_RADIX);
+		hexTimeHigh = _padWithLeadingZeros(hexTimeHigh, 3);
+		var hyphen = "-";
+		var versionCodeForTimeBasedUuids = "1"; // binary2hex("0001")
+		var resultUuid = hexTimeLow + hyphen + hexTimeMid + hyphen +
+					versionCodeForTimeBasedUuids + hexTimeHigh + hyphen +
+					_uuidClockSeqString + hyphen + node;
+		resultUuid = resultUuid.toLowerCase();
+		return resultUuid;
+	}
+
+// --------------------------------------------------
+// Public functions
+// --------------------------------------------------
+
+/**
+ * Sets the 'node' value that will be included in generated UUIDs.
+ *
+ * @param	node	A 12-character hex string representing a pseudoNode or hardwareNode.
+ */
+	this.setNode = function(node) {
+		dojo.lang.assert((node === null) || (node.length == 12));
+		_uniformNode = node;
+	};
+
+/**
+ * Returns the 'node' value that will be included in generated UUIDs.
+ *
+ * @return	A 12-character hex string representing a pseudoNode or hardwareNode.
+ */
+	this.getNode = function() {
+		return _uniformNode;
+	};
+
+/**
+ * This function generates time-based UUIDs, meaning "version 1" UUIDs.
+ *
+ * For more info, see
+ *   http://www.webdav.org/specs/draft-leach-uuids-guids-01.txt
+ *   http://www.infonuovo.com/dma/csdocs/sketch/instidid.htm
+ *   http://kruithof.xs4all.nl/uuid/uuidgen
+ *   http://www.opengroup.org/onlinepubs/009629399/apdxa.htm#tagcjh_20
+ *   http://jakarta.apache.org/commons/sandbox/id/apidocs/org/apache/commons/id/uuid/clock/Clock.html
+ *
+ * Examples:
+ * <pre>
+ *   var generate = dojo.uuid.TimeBasedGenerator.generate;
+ *   var uuid;   // an instance of dojo.uuid.Uuid
+ *   var string; // a simple string literal
+ *   string = generate();
+ *   string = generate(String);
+ *   uuid   = generate(dojo.uuid.Uuid);
+ *   string = generate("017bf397618a");
+ *   string = generate({node: "017bf397618a"});         // hardwareNode
+ *   string = generate({node: "f17bf397618a"});         // pseudoNode
+ *   string = generate({hardwareNode: "017bf397618a"});
+ *   string = generate({pseudoNode:   "f17bf397618a"});
+ *   string = generate({node: "017bf397618a", returnType: String});
+ *   uuid   = generate({node: "017bf397618a", returnType: dojo.uuid.Uuid});
+ *   dojo.uuid.TimeBasedGenerator.setNode("017bf397618a");
+ *   string = generate(); // the generated UUID has node == "017bf397618a"
+ *   uuid   = generate(dojo.uuid.Uuid); // the generated UUID has node == "017bf397618a"
+ * </pre>
+ *
+ * @param	class	The type of instance to return.
+ * @param	node	A 12-character hex string representing a pseudoNode or hardwareNode.
+ * @namedParam	node	A 12-character hex string representing a pseudoNode or hardwareNode.
+ * @namedParam	hardwareNode	A 12-character hex string containing an IEEE 802.3 network node identificator.
+ * @namedParam	pseudoNode	A 12-character hex string representing a pseudoNode.
+ * @namedParam	returnType	The type of instance to return.
+ * @return	A newly generated version 1 UUID.
+ */
+	this.generate = function(input) {
+		var nodeString = null;
+		var returnType = null;
+		
+		if (input) {
+			if (dojo.lang.isObject(input) && !dojo.lang.isBuiltIn(input)) {
+				var namedParameters = input;
+				dojo.lang.assertValidKeywords(namedParameters, ["node", "hardwareNode", "pseudoNode", "returnType"]);
+				var node = namedParameters["node"];
+				var hardwareNode = namedParameters["hardwareNode"];
+				var pseudoNode = namedParameters["pseudoNode"];
+				nodeString = (node || pseudoNode || hardwareNode);
+				if (nodeString) {
+					var firstCharacter = nodeString.charAt(0);
+					var firstDigit = parseInt(firstCharacter, HEX_RADIX);
+					if (hardwareNode) {
+						dojo.lang.assert((firstDigit >= 0x0) && (firstDigit <= 0x7));
+					}
+					if (pseudoNode) {
+						dojo.lang.assert((firstDigit >= 0x8) && (firstDigit <= 0xF));
+					}
+				}
+				returnType = namedParameters["returnType"];
+				dojo.lang.assertType(returnType, [Function, "optional"]);
+			} else {
+				if (dojo.lang.isString(input)) {
+					nodeString = input;
+					returnType = null;
+				} else {
+					if (dojo.lang.isFunction(input)) {
+						nodeString = null;
+						returnType = input;
+					}
+				}
+			}
+			if (nodeString) {
+				dojo.lang.assert(nodeString.length == 12);
+				var integer = parseInt(nodeString, HEX_RADIX);
+				dojo.lang.assert(isFinite(integer));
+			}
+			dojo.lang.assertType(returnType, [Function, "optional"]);
+		}
+		
+		var uuidString = _generateUuidString(nodeString);
+		var returnValue;
+		if (returnType && (returnType != String)) {
+			returnValue = new returnType(uuidString);
+		} else {
+			returnValue = uuidString;
+		}
+		return returnValue;
+	};
+}();