You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by we...@apache.org on 2006/10/18 22:37:06 UTC

svn commit: r465364 [3/4] - in /myfaces/tomahawk/trunk/core/src/main/resources/org/apache/myfaces/custom/dojo/resource: build.txt dojo.js dojo.js.uncompressed.js version.txt

Modified: myfaces/tomahawk/trunk/core/src/main/resources/org/apache/myfaces/custom/dojo/resource/dojo.js.uncompressed.js
URL: http://svn.apache.org/viewvc/myfaces/tomahawk/trunk/core/src/main/resources/org/apache/myfaces/custom/dojo/resource/dojo.js.uncompressed.js?view=diff&rev=465364&r1=465363&r2=465364
==============================================================================
--- myfaces/tomahawk/trunk/core/src/main/resources/org/apache/myfaces/custom/dojo/resource/dojo.js.uncompressed.js (original)
+++ myfaces/tomahawk/trunk/core/src/main/resources/org/apache/myfaces/custom/dojo/resource/dojo.js.uncompressed.js Wed Oct 18 13:37:05 2006
@@ -1480,6 +1480,152 @@
 
 // end Crockford functions
 
+dojo.provide("dojo.lang");
+dojo.provide("dojo.lang.Lang");
+
+dojo.require("dojo.lang.common");
+
+dojo.provide("dojo.lang.func");
+
+dojo.require("dojo.lang.common");
+
+/**
+ * Runs a function in a given scope (thisObject), can
+ * also be used to preserve scope.
+ *
+ * hitch(foo, "bar"); // runs foo.bar() in the scope of foo
+ * hitch(foo, myFunction); // runs myFunction in the scope of foo
+ */
+dojo.lang.hitch = function(thisObject, method) {
+	if(dojo.lang.isString(method)) {
+		var fcn = thisObject[method];
+	} else {
+		var fcn = method;
+	}
+
+	return function() {
+		return fcn.apply(thisObject, arguments);
+	}
+}
+
+dojo.lang.anonCtr = 0;
+dojo.lang.anon = {};
+dojo.lang.nameAnonFunc = function(anonFuncPtr, namespaceObj, searchForNames){
+	var nso = (namespaceObj || dojo.lang.anon);
+	if( (searchForNames) ||
+		((dj_global["djConfig"])&&(djConfig["slowAnonFuncLookups"] == true)) ){
+		for(var x in nso){
+			if(nso[x] === anonFuncPtr){
+				return x;
+			}
+		}
+	}
+	var ret = "__"+dojo.lang.anonCtr++;
+	while(typeof nso[ret] != "undefined"){
+		ret = "__"+dojo.lang.anonCtr++;
+	}
+	nso[ret] = anonFuncPtr;
+	return ret;
+}
+
+dojo.lang.forward = function(funcName){
+	// Returns a function that forwards a method call to this.func(...)
+	return function(){
+		return this[funcName].apply(this, arguments);
+	};
+}
+
+dojo.lang.curry = function(ns, func /* args ... */){
+	var outerArgs = [];
+	ns = ns||dj_global;
+	if(dojo.lang.isString(func)){
+		func = ns[func];
+	}
+	for(var x=2; x<arguments.length; x++){
+		outerArgs.push(arguments[x]);
+	}
+	// since the event system replaces the original function with a new
+	// join-point runner with an arity of 0, we check to see if it's left us
+	// any clues about the original arity in lieu of the function's actual
+	// length property
+	var ecount = (func["__preJoinArity"]||func.length) - outerArgs.length;
+	// borrowed from svend tofte
+	function gather(nextArgs, innerArgs, expected){
+		var texpected = expected;
+		var totalArgs = innerArgs.slice(0); // copy
+		for(var x=0; x<nextArgs.length; x++){
+			totalArgs.push(nextArgs[x]);
+		}
+		// check the list of provided nextArgs to see if it, plus the
+		// number of innerArgs already supplied, meets the total
+		// expected.
+		expected = expected-nextArgs.length;
+		if(expected<=0){
+			var res = func.apply(ns, totalArgs);
+			expected = texpected;
+			return res;
+		}else{
+			return function(){
+				return gather(arguments,// check to see if we've been run
+										// with enough args
+							totalArgs,	// a copy
+							expected);	// how many more do we need to run?;
+			}
+		}
+	}
+	return gather([], outerArgs, ecount);
+}
+
+dojo.lang.curryArguments = function(ns, func, args, offset){
+	var targs = [];
+	var x = offset||0;
+	for(x=offset; x<args.length; x++){
+		targs.push(args[x]); // ensure that it's an arr
+	}
+	return dojo.lang.curry.apply(dojo.lang, [ns, func].concat(targs));
+}
+
+dojo.lang.tryThese = function(){
+	for(var x=0; x<arguments.length; x++){
+		try{
+			if(typeof arguments[x] == "function"){
+				var ret = (arguments[x]());
+				if(ret){
+					return ret;
+				}
+			}
+		}catch(e){
+			dojo.debug(e);
+		}
+	}
+}
+
+dojo.lang.delayThese = function(farr, cb, delay, onend){
+	/**
+	 * alternate: (array funcArray, function callback, function onend)
+	 * alternate: (array funcArray, function callback)
+	 * alternate: (array funcArray)
+	 */
+	if(!farr.length){ 
+		if(typeof onend == "function"){
+			onend();
+		}
+		return;
+	}
+	if((typeof delay == "undefined")&&(typeof cb == "number")){
+		delay = cb;
+		cb = function(){};
+	}else if(!cb){
+		cb = function(){};
+		if(!delay){ delay = 0; }
+	}
+	setTimeout(function(){
+		(farr.shift())();
+		cb();
+		dojo.lang.delayThese(farr, cb, delay, onend);
+	}, delay);
+}
+
 dojo.provide("dojo.lang.array");
 
 dojo.require("dojo.lang.common");
@@ -2119,5220 +2265,11733 @@
 	return "";
 }
 
-dojo.provide("dojo.xml.Parse");
+dojo.provide("dojo.graphics.color");
+dojo.require("dojo.lang.array");
 
-dojo.require("dojo.dom");
+// TODO: rewrite the "x2y" methods to take advantage of the parsing
+//       abilities of the Color object. Also, beef up the Color
+//       object (as possible) to parse most common formats
 
-//TODO: determine dependencies
-// currently has dependency on dojo.xml.DomUtil nodeTypes constants...
+// takes an r, g, b, a(lpha) value, [r, g, b, a] array, "rgb(...)" string, hex string (#aaa, #aaaaaa, aaaaaaa)
+dojo.graphics.color.Color = function(r, g, b, a) {
+	// dojo.debug("r:", r[0], "g:", r[1], "b:", r[2]);
+	if(dojo.lang.isArray(r)) {
+		this.r = r[0];
+		this.g = r[1];
+		this.b = r[2];
+		this.a = r[3]||1.0;
+	} else if(dojo.lang.isString(r)) {
+		var rgb = dojo.graphics.color.extractRGB(r);
+		this.r = rgb[0];
+		this.g = rgb[1];
+		this.b = rgb[2];
+		this.a = g||1.0;
+	} else if(r instanceof dojo.graphics.color.Color) {
+		this.r = r.r;
+		this.b = r.b;
+		this.g = r.g;
+		this.a = r.a;
+	} else {
+		this.r = r;
+		this.g = g;
+		this.b = b;
+		this.a = a;
+	}
+}
 
-/* generic method for taking a node and parsing it into an object
+dojo.graphics.color.Color.fromArray = function(arr) {
+	return new dojo.graphics.color.Color(arr[0], arr[1], arr[2], arr[3]);
+}
 
-TODO: WARNING: This comment is wrong!
+dojo.lang.extend(dojo.graphics.color.Color, {
+	toRgb: function(includeAlpha) {
+		if(includeAlpha) {
+			return this.toRgba();
+		} else {
+			return [this.r, this.g, this.b];
+		}
+	},
 
-For example, the following xml fragment
+	toRgba: function() {
+		return [this.r, this.g, this.b, this.a];
+	},
 
-<foo bar="bar">
-	<baz xyzzy="xyzzy"/>
-</foo>
+	toHex: function() {
+		return dojo.graphics.color.rgb2hex(this.toRgb());
+	},
 
-can be described as:
+	toCss: function() {
+		return "rgb(" + this.toRgb().join() + ")";
+	},
 
-dojo.???.foo = {}
-dojo.???.foo.bar = {}
-dojo.???.foo.bar.value = "bar";
-dojo.???.foo.baz = {}
-dojo.???.foo.baz.xyzzy = {}
-dojo.???.foo.baz.xyzzy.value = "xyzzy"
+	toString: function() {
+		return this.toHex(); // decent default?
+	},
 
-*/
-// using documentFragment nomenclature to generalize in case we don't want to require passing a collection of nodes with a single parent
-dojo.xml.Parse = function(){
+	blend: function(color, weight) {
+		return dojo.graphics.color.blend(this.toRgb(), new dojo.graphics.color.Color(color).toRgb(), weight);
+	}
+});
 
-	function getDojoTagName (node) {
-		var tagName = node.tagName;
-		if (tagName.substr(0,5).toLowerCase() != "dojo:") {
-			
-			if (tagName.substr(0,4).toLowerCase() == "dojo") {
-				// FIXME: this assuumes tag names are always lower case
-				return "dojo:" + tagName.substring(4).toLowerCase();
-			}
-		
-			// allow lower-casing
-			var djt = node.getAttribute("dojoType") || node.getAttribute("dojotype");
-			if (djt) { return "dojo:" + djt.toLowerCase(); }
-			
-			if (node.getAttributeNS && node.getAttributeNS(dojo.dom.dojoml,"type")) {
-				return "dojo:" + node.getAttributeNS(dojo.dom.dojoml,"type").toLowerCase();
-			}
-			try {
-				// FIXME: IE really really doesn't like this, so we squelch
-				// errors for it
-				djt = node.getAttribute("dojo:type");
-			} catch (e) { /* FIXME: log? */ }
+dojo.graphics.color.named = {
+	white:      [255,255,255],
+	black:      [0,0,0],
+	red:        [255,0,0],
+	green:	    [0,255,0],
+	blue:       [0,0,255],
+	navy:       [0,0,128],
+	gray:       [128,128,128],
+	silver:     [192,192,192]
+};
 
-			if (djt) { return "dojo:"+djt.toLowerCase(); }
-		
-			if (!dj_global["djConfig"] || !djConfig["ignoreClassNames"]) {
-				// FIXME: should we make this optionally enabled via djConfig?
-				var classes = node.className||node.getAttribute("class");
-				// FIXME: following line, without check for existence of classes.indexOf
-				// breaks firefox 1.5's svg widgets
-				if (classes && classes.indexOf && classes.indexOf("dojo-") != -1) {
-					var aclasses = classes.split(" ");
-					for(var x=0; x<aclasses.length; x++){
-						if (aclasses[x].length > 5 && aclasses[x].indexOf("dojo-") >= 0) {
-							return "dojo:"+aclasses[x].substr(5).toLowerCase();
-						}
-					}
-				}
-			}
-		
-		}
-		return tagName.toLowerCase();
+// blend colors a and b (both as RGB array or hex strings) with weight from -1 to +1, 0 being a 50/50 blend
+dojo.graphics.color.blend = function(a, b, weight) {
+	if(typeof a == "string") { return dojo.graphics.color.blendHex(a, b, weight); }
+	if(!weight) { weight = 0; }
+	else if(weight > 1) { weight = 1; }
+	else if(weight < -1) { weight = -1; }
+	var c = new Array(3);
+	for(var i = 0; i < 3; i++) {
+		var half = Math.abs(a[i] - b[i])/2;
+		c[i] = Math.floor(Math.min(a[i], b[i]) + half + (half * weight));
 	}
+	return c;
+}
 
-	this.parseElement = function(node, hasParentNodeSet, optimizeForDojoML, thisIdx){
-
-        // if parseWidgets="false" don't search inside this node for widgets
-        if (node.getAttribute("parseWidgets") == "false") {
-            return {};
-        }
-
-		// TODO: make this namespace aware
-		var parsedNodeSet = {};
-
-		var tagName = getDojoTagName(node);
-		parsedNodeSet[tagName] = [];
-		if((!optimizeForDojoML)||(tagName.substr(0,4).toLowerCase()=="dojo")){
-			var attributeSet = parseAttributes(node);
-			for(var attr in attributeSet){
-				if((!parsedNodeSet[tagName][attr])||(typeof parsedNodeSet[tagName][attr] != "array")){
-					parsedNodeSet[tagName][attr] = [];
-				}
-				parsedNodeSet[tagName][attr].push(attributeSet[attr]);
-			}
-	
-			// FIXME: we might want to make this optional or provide cloning instead of
-			// referencing, but for now, we include a node reference to allow
-			// instantiated components to figure out their "roots"
-			parsedNodeSet[tagName].nodeRef = node;
-			parsedNodeSet.tagName = tagName;
-			parsedNodeSet.index = thisIdx||0;
-		}
-	
-		var count = 0;
-		var tcn, i = 0, nodes = node.childNodes;
-		while(tcn = nodes[i++]){
-			switch(tcn.nodeType){
-				case  dojo.dom.ELEMENT_NODE: // element nodes, call this function recursively
-					count++;
-					var ctn = getDojoTagName(tcn);
-					if(!parsedNodeSet[ctn]){
-						parsedNodeSet[ctn] = [];
-					}
-					parsedNodeSet[ctn].push(this.parseElement(tcn, true, optimizeForDojoML, count));
-					if(	(tcn.childNodes.length == 1)&&
-						(tcn.childNodes.item(0).nodeType == dojo.dom.TEXT_NODE)){
-						parsedNodeSet[ctn][parsedNodeSet[ctn].length-1].value = tcn.childNodes.item(0).nodeValue;
-					}
-					break;
-				case  dojo.dom.TEXT_NODE: // if a single text node is the child, treat it as an attribute
-					if(node.childNodes.length == 1) {
-						parsedNodeSet[tagName].push({ value: node.childNodes.item(0).nodeValue });
-					}
-					break;
-				default: break;
-				/*
-				case  dojo.dom.ATTRIBUTE_NODE: // attribute node... not meaningful here
-					break;
-				case  dojo.dom.CDATA_SECTION_NODE: // cdata section... not sure if this would ever be meaningful... might be...
-					break;
-				case  dojo.dom.ENTITY_REFERENCE_NODE: // entity reference node... not meaningful here
-					break;
-				case  dojo.dom.ENTITY_NODE: // entity node... not sure if this would ever be meaningful
-					break;
-				case  dojo.dom.PROCESSING_INSTRUCTION_NODE: // processing instruction node... not meaningful here
-					break;
-				case  dojo.dom.COMMENT_NODE: // comment node... not not sure if this would ever be meaningful 
-					break;
-				case  dojo.dom.DOCUMENT_NODE: // document node... not sure if this would ever be meaningful
-					break;
-				case  dojo.dom.DOCUMENT_TYPE_NODE: // document type node... not meaningful here
-					break;
-				case  dojo.dom.DOCUMENT_FRAGMENT_NODE: // document fragment node... not meaningful here
-					break;
-				case  dojo.dom.NOTATION_NODE:// notation node... not meaningful here
-					break;
-				*/
-			}
-		}
-		//return (hasParentNodeSet) ? parsedNodeSet[node.tagName] : parsedNodeSet;
-		return parsedNodeSet;
-	}
+// very convenient blend that takes and returns hex values
+// (will get called automatically by blend when blend gets strings)
+dojo.graphics.color.blendHex = function(a, b, weight) {
+	return dojo.graphics.color.rgb2hex(dojo.graphics.color.blend(dojo.graphics.color.hex2rgb(a), dojo.graphics.color.hex2rgb(b), weight));
+}
 
-	/* parses a set of attributes on a node into an object tree */
-	function parseAttributes(node) {
-		// TODO: make this namespace aware
-		var parsedAttributeSet = {};
-		var atts = node.attributes;
-		// TODO: should we allow for duplicate attributes at this point...
-		// would any of the relevant dom implementations even allow this?
-		var attnode, i=0;
-		while(attnode=atts[i++]) {
-			if((dojo.render.html.capable)&&(dojo.render.html.ie)){
-				if(!attnode){ continue; }
-				if(	(typeof attnode == "object")&&
-					(typeof attnode.nodeValue == 'undefined')||
-					(attnode.nodeValue == null)||
-					(attnode.nodeValue == '')){ 
-					continue; 
-				}
-			}
-			var nn = (attnode.nodeName.indexOf("dojo:") == -1) ? attnode.nodeName : attnode.nodeName.split("dojo:")[1];
-			parsedAttributeSet[nn] = { 
-				value: attnode.nodeValue 
-			};
+// get RGB array from css-style color declarations
+dojo.graphics.color.extractRGB = function(color) {
+	var hex = "0123456789abcdef";
+	color = color.toLowerCase();
+	if( color.indexOf("rgb") == 0 ) {
+		var matches = color.match(/rgba*\((\d+), *(\d+), *(\d+)/i);
+		var ret = matches.splice(1, 3);
+		return ret;
+	} else {
+		var colors = dojo.graphics.color.hex2rgb(color);
+		if(colors) {
+			return colors;
+		} else {
+			// named color (how many do we support?)
+			return dojo.graphics.color.named[color] || [255, 255, 255];
 		}
-		return parsedAttributeSet;
 	}
 }
 
-dojo.provide("dojo.lang.func");
-
-dojo.require("dojo.lang.common");
-
-/**
- * Runs a function in a given scope (thisObject), can
- * also be used to preserve scope.
- *
- * hitch(foo, "bar"); // runs foo.bar() in the scope of foo
- * hitch(foo, myFunction); // runs myFunction in the scope of foo
- */
-dojo.lang.hitch = function(thisObject, method) {
-	if(dojo.lang.isString(method)) {
-		var fcn = thisObject[method];
+dojo.graphics.color.hex2rgb = function(hex) {
+	var hexNum = "0123456789ABCDEF";
+	var rgb = new Array(3);
+	if( hex.indexOf("#") == 0 ) { hex = hex.substring(1); }
+	hex = hex.toUpperCase();
+	if(hex.replace(new RegExp("["+hexNum+"]", "g"), "") != "") {
+		return null;
+	}
+	if( hex.length == 3 ) {
+		rgb[0] = hex.charAt(0) + hex.charAt(0)
+		rgb[1] = hex.charAt(1) + hex.charAt(1)
+		rgb[2] = hex.charAt(2) + hex.charAt(2);
 	} else {
-		var fcn = method;
+		rgb[0] = hex.substring(0, 2);
+		rgb[1] = hex.substring(2, 4);
+		rgb[2] = hex.substring(4);
 	}
-
-	return function() {
-		return fcn.apply(thisObject, arguments);
+	for(var i = 0; i < rgb.length; i++) {
+		rgb[i] = hexNum.indexOf(rgb[i].charAt(0)) * 16 + hexNum.indexOf(rgb[i].charAt(1));
 	}
+	return rgb;
 }
 
-dojo.lang.anonCtr = 0;
-dojo.lang.anon = {};
-dojo.lang.nameAnonFunc = function(anonFuncPtr, namespaceObj, searchForNames){
-	var nso = (namespaceObj || dojo.lang.anon);
-	if( (searchForNames) ||
-		((dj_global["djConfig"])&&(djConfig["slowAnonFuncLookups"] == true)) ){
-		for(var x in nso){
-			if(nso[x] === anonFuncPtr){
-				return x;
-			}
-		}
-	}
-	var ret = "__"+dojo.lang.anonCtr++;
-	while(typeof nso[ret] != "undefined"){
-		ret = "__"+dojo.lang.anonCtr++;
+dojo.graphics.color.rgb2hex = function(r, g, b) {
+	if(dojo.lang.isArray(r)) {
+		g = r[1] || 0;
+		b = r[2] || 0;
+		r = r[0] || 0;
 	}
-	nso[ret] = anonFuncPtr;
-	return ret;
+	var ret = dojo.lang.map([r, g, b], function(x) {
+		x = new Number(x);
+		var s = x.toString(16);
+		while(s.length < 2) { s = "0" + s; }
+		return s;
+	});
+	ret.unshift("#");
+	return ret.join("");
 }
 
-dojo.lang.forward = function(funcName){
-	// Returns a function that forwards a method call to this.func(...)
-	return function(){
-		return this[funcName].apply(this, arguments);
-	};
-}
+dojo.provide("dojo.uri.Uri");
 
-dojo.lang.curry = function(ns, func /* args ... */){
-	var outerArgs = [];
-	ns = ns||dj_global;
-	if(dojo.lang.isString(func)){
-		func = ns[func];
+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/");
 	}
-	for(var x=2; x<arguments.length; x++){
-		outerArgs.push(arguments[x]);
+	
+	this.dojoUri = function (uri) {
+		// returns a Uri object resolved relative to the dojo root
+		return new dojo.uri.Uri(dojo.hostenv.getBaseScriptUri(), uri);
 	}
-	// since the event system replaces the original function with a new
-	// join-point runner with an arity of 0, we check to see if it's left us
-	// any clues about the original arity in lieu of the function's actual
-	// length property
-	var ecount = (func["__preJoinArity"]||func.length) - outerArgs.length;
-	// borrowed from svend tofte
-	function gather(nextArgs, innerArgs, expected){
-		var texpected = expected;
-		var totalArgs = innerArgs.slice(0); // copy
-		for(var x=0; x<nextArgs.length; x++){
-			totalArgs.push(nextArgs[x]);
-		}
-		// check the list of provided nextArgs to see if it, plus the
-		// number of innerArgs already supplied, meets the total
-		// expected.
-		expected = expected-nextArgs.length;
-		if(expected<=0){
-			var res = func.apply(ns, totalArgs);
-			expected = texpected;
-			return res;
-		}else{
-			return function(){
-				return gather(arguments,// check to see if we've been run
-										// with enough args
-							totalArgs,	// a copy
-							expected);	// how many more do we need to run?;
-			}
-		}
-	}
-	return gather([], outerArgs, ecount);
-}
+		
+	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)
 
-dojo.lang.curryArguments = function(ns, func, args, offset){
-	var targs = [];
-	var x = offset||0;
-	for(x=offset; x<args.length; x++){
-		targs.push(args[x]); // ensure that it's an arr
-	}
-	return dojo.lang.curry.apply(dojo.lang, [ns, func].concat(targs));
-}
+		// TODO: support for IPv6, see RFC 2732
 
-dojo.lang.tryThese = function(){
-	for(var x=0; x<arguments.length; x++){
-		try{
-			if(typeof arguments[x] == "function"){
-				var ret = (arguments[x]());
-				if(ret){
-					return ret;
-				}
-			}
-		}catch(e){
-			dojo.debug(e);
-		}
-	}
-}
+		// resolve uri components relative to each other
+		var uri = arguments[0];
+		for (var i = 1; i < arguments.length; i++) {
+			if(!arguments[i]) { continue; }
 
-dojo.lang.delayThese = function(farr, cb, delay, onend){
-	/**
-	 * alternate: (array funcArray, function callback, function onend)
-	 * alternate: (array funcArray, function callback)
-	 * alternate: (array funcArray)
-	 */
-	if(!farr.length){ 
-		if(typeof onend == "function"){
-			onend();
-		}
-		return;
-	}
-	if((typeof delay == "undefined")&&(typeof cb == "number")){
-		delay = cb;
-		cb = function(){};
-	}else if(!cb){
-		cb = function(){};
-		if(!delay){ delay = 0; }
-	}
-	setTimeout(function(){
-		(farr.shift())();
-		cb();
-		dojo.lang.delayThese(farr, cb, delay, onend);
-	}, delay);
-}
+			// 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());
 
-dojo.provide("dojo.lang.extras");
+			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;
 
-dojo.require("dojo.lang.common");
+						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] != "..") {
 
-/**
- * Sets a timeout in milliseconds to execute a function in a given context
- * with optional arguments.
- *
- * setTimeout (Object context, function func, number delay[, arg1[, ...]]);
- * setTimeout (function func, number delay[, arg1[, ...]]);
- */
-dojo.lang.setTimeout = function(func, delay){
-	var context = window, argsStart = 2;
-	if(!dojo.lang.isFunction(func)){
-		context = func;
-		func = delay;
-		delay = arguments[2];
-		argsStart++;
-	}
+								if (j == segs.length - 1) { segs.splice(j, 1); segs[j - 1] = ""; }
+								else { segs.splice(j - 1, 2); j -= 2; }
+							}
+						}
+						relobj.path = segs.join("/");
+					}
+				}
+			}
 
-	if(dojo.lang.isString(func)){
-		func = context[func];
-	}
-	
-	var args = [];
-	for (var i = argsStart; i < arguments.length; i++) {
-		args.push(arguments[i]);
-	}
-	return setTimeout(function () { func.apply(context, args); }, delay);
-}
+			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; }
+		}
 
-dojo.lang.getNameInObj = function(ns, item){
-	if(!ns){ ns = dj_global; }
+		this.uri = uri.toString();
 
-	for(var x in ns){
-		if(ns[x] === item){
-			return new String(x);
-		}
-	}
-	return null;
-}
+		// break the uri into its main components
+		var regexp = "^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\\?([^#]*))?(#(.*))?$";
+	    var r = this.uri.match(new RegExp(regexp));
 
-dojo.lang.shallowCopy = function(obj) {
-	var ret = {}, key;
-	for(key in obj) {
-		if(dojo.lang.isUndefined(ret[key])) {
-			ret[key] = obj[key];
+		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; }
 	}
-	return ret;
-}
+};
 
-/**
- * Return the first argument that isn't undefined
- */
-dojo.lang.firstValued = function(/* ... */) {
-	for(var i = 0; i < arguments.length; i++) {
-		if(typeof arguments[i] != "undefined") {
-			return arguments[i];
-		}
-	}
-	return undefined;
-}
+dojo.provide("dojo.style");
+dojo.require("dojo.graphics.color");
+dojo.require("dojo.uri.Uri");
+dojo.require("dojo.lang.common");
 
-/**
- * Get a value from a reference specified as a string descriptor,
- * (e.g. "A.B") in the given context.
- * 
- * getObjPathValue(String objpath [, Object context, Boolean create])
- *
- * If context is not specified, dj_global is used
- * If create is true, undefined objects in the path are created.
- */
-dojo.lang.getObjPathValue = function(objpath, context, create){
-	with(dojo.parseObjPath(objpath, context, create)){
-		return dojo.evalProp(prop, obj, create);
-	}
-}
+(function(){
+	var h = dojo.render.html;
+	var ds = dojo.style;
+	var db = document["body"]||document["documentElement"];
 
-/**
- * Set a value on a reference specified as a string descriptor. 
- * (e.g. "A.B") in the given context.
- * 
- * setObjPathValue(String objpath, value [, Object context, Boolean create])
- *
- * If context is not specified, dj_global is used
- * If create is true, undefined objects in the path are created.
- */
-dojo.lang.setObjPathValue = function(objpath, value, context, create){
-	if(arguments.length < 4){
-		create = true;
-	}
-	with(dojo.parseObjPath(objpath, context, create)){
-		if(obj && (create || (prop in obj))){
-			obj[prop] = value;
+	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);
 		}
 	}
-}
 
-dojo.provide("dojo.lang.declare");
+	/*
 
-dojo.require("dojo.lang.common");
-dojo.require("dojo.lang.extras");
+	The following several function use the dimensions shown below
 
-/*
- * Creates a constructor: inherit and extend
- *
- * - inherits from "superclass(es)" 
- *
- *   "superclass" argument may be a Function, or an array of 
- *   Functions. 
- *
- *   If "superclass" is an array, the first element is used 
- *   as the prototypical ancestor and any following Functions 
- *   become mixin ancestors. 
- * 
- *   All "superclass(es)" must be Functions (not mere Objects).
- *
- *   Using mixin ancestors provides a type of multiple
- *   inheritance. Mixin ancestors prototypical 
- *   properties are copied to the subclass, and any 
- *   inializater/constructor is invoked. 
- *
- * - "props" are copied to the constructor prototype
- *
- * - name of the class ("className" argument) is stored in 
- *   "declaredClass" property
- * 
- * - An initializer function can be specified in the "init" 
- *   argument, or by including a function called "initializer" 
- *   in "props".
- * 
- * - Superclass methods (inherited methods) can be invoked using "inherited" method:
- *
- * this.inherited(<method name>[, <argument array>]);
- * 
- * - inherited will continue up the prototype chain until it finds an implementation of method
- * - nested calls to inherited are supported (i.e. inherited method "A" can succesfully call inherited("A"), and so on)
- *
- * Aliased as "dojo.declare"
- *
- * Usage:
- *
- * dojo.declare("my.classes.bar", my.classes.foo, {
- *	initializer: function() {
- *		this.myComplicatedObject = new ReallyComplicatedObject(); 
- *	},
- *	someValue: 2,
- *	aMethod: function() { doStuff(); }
- * });
- *
- */
-dojo.lang.declare = function(className /*string*/, superclass /*function || array*/, init /*function*/, props /*object*/){
-	// FIXME: parameter juggling for backward compat ... deprecate and remove after 0.3.*
-	// new sig: (className (string)[, superclass (function || array)[, init (function)][, props (object)]])
-	// old sig: (className (string)[, superclass (function || array), props (object), init (function)])
-	if ((dojo.lang.isFunction(props))||((!props)&&(!dojo.lang.isFunction(init)))){ 
-		var temp = props;
-		props = init;
-		init = temp;
-	}	
-	var mixins = [ ];
-	if (dojo.lang.isArray(superclass)) {
-		mixins = superclass;
-		superclass = mixins.shift();
-	}
-	if(!init){
-		init = dojo.evalObjPath(className, false);
-		if ((init)&&(!dojo.lang.isFunction(init))){ init = null };
+		+-------------------------+
+		|  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);
 	}
-	var ctor = dojo.lang.declare._makeConstructor();
-	var scp = (superclass ? superclass.prototype : null);
-	if(scp){
-		scp.prototyping = true;
-		ctor.prototype = new superclass();
-		scp.prototyping = false; 
+
+	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() };
 	}
-	ctor.superclass = scp;
-	ctor.mixins = mixins;
-	for(var i=0,l=mixins.length; i<l; i++){
-		dojo.lang.extend(ctor, mixins[i].prototype);
+	// 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;
 	}
-	ctor.prototype.initializer = null;
-	ctor.prototype.declaredClass = className;
-	if(dojo.lang.isArray(props)){
-		dojo.lang.extend.apply(dojo.lang, [ctor].concat(props));
-	}else{
-		dojo.lang.extend(ctor, (props)||{});
+	
+	// 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); 
 	}
-	dojo.lang.extend(ctor, dojo.lang.declare.base);
-	ctor.prototype.constructor = ctor;
-	ctor.prototype.initializer=(ctor.prototype.initializer)||(init)||(function(){});
-	dojo.lang.setObjPathValue(className, ctor, null, true);
-}
 
-dojo.lang.declare._makeConstructor = function() {
-	return function(){ 
-		// get the generational context (which object [or prototype] should be constructed)
-		var self = this._getPropContext();
-		var s = self.constructor.superclass;
-		if((s)&&(s.constructor)){
-			if(s.constructor==arguments.callee){
-				// if this constructor is invoked directly (my.ancestor.call(this))
-				this.inherited("constructor", arguments);
-			}else{
-				this._inherited(s, "constructor", arguments);
-			}
-		}
-		var m = (self.constructor.mixins)||([]);
-		for(var i=0,l=m.length; i<l; i++) {
-			(((m[i].prototype)&&(m[i].prototype.initializer))||(m[i])).apply(this, arguments);
-		}
-		if((!this.prototyping)&&(self.initializer)){
-			self.initializer.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(var x=0; x<selectors.length; x++){
+			total += ds.getPixelValue(node, selectors[x], autoIsZero);
 		}
+		return total;
 	}
-}
 
-dojo.lang.declare.base = {
-	_getPropContext: function() { return (this.___proto||this); },
-	// caches ptype context and calls method on it
-	_inherited: function(ptype, method, args){
-		var stack = this.___proto;
-		this.___proto = ptype;
-		var result = ptype[method].apply(this,(args||[]));
-		this.___proto = stack;
-		return result;
-	},
-	// invokes ctor.prototype.method, with args, in our context 
-	inheritedFrom: function(ctor, prop, args){
-		var p = ((ctor)&&(ctor.prototype)&&(ctor.prototype[prop]));
-		return (dojo.lang.isFunction(p) ? p.apply(this, (args||[])) : p);
-	},
-	// searches backward thru prototype chain to find nearest ancestral instance of prop
-	inherited: function(prop, args){
-		var p = this._getPropContext();
-		do{
-			if((!p.constructor)||(!p.constructor.superclass)){return;}
-			p = p.constructor.superclass;
-		}while(!(prop in p));
-		return (dojo.lang.isFunction(p[prop]) ? this._inherited(p, prop, args) : p[prop]);
+	ds.isPositionAbsolute = function(node){
+		return (ds.getComputedStyle(node, 'position') == 'absolute');
 	}
-}
 
-dojo.declare = dojo.lang.declare;
-dojo.provide("dojo.event");
+	ds.getBorderExtent = function(node, side){
+		return (ds.getStyle(node, 'border-' + side + '-style') == 'none' ? 0 : ds.getPixelValue(node, 'border-' + side + '-width'));
+	}
 
-dojo.require("dojo.lang.array");
-dojo.require("dojo.lang.extras");
-dojo.require("dojo.lang.func");
+	ds.getMarginWidth = function(node){
+		return ds._sumPixelValues(node, ["margin-left", "margin-right"], ds.isPositionAbsolute(node));
+	}
 
-dojo.event = new function(){
-	this.canTimeout = dojo.lang.isFunction(dj_global["setTimeout"])||dojo.lang.isAlien(dj_global["setTimeout"]);
+	ds.getBorderWidth = function(node){
+		return ds.getBorderExtent(node, 'left') + ds.getBorderExtent(node, 'right');
+	}
 
-	// FIXME: where should we put this method (not here!)?
-	function interpolateArgs(args, searchForNames){
-		var dl = dojo.lang;
-		var ao = {
-			srcObj: dj_global,
-			srcFunc: null,
-			adviceObj: dj_global,
-			adviceFunc: null,
-			aroundObj: null,
-			aroundFunc: null,
-			adviceType: (args.length>2) ? args[0] : "after",
-			precedence: "last",
-			once: false,
-			delay: null,
-			rate: 0,
-			adviceMsg: false
-		};
-
-		switch(args.length){
-			case 0: return;
-			case 1: return;
-			case 2:
-				ao.srcFunc = args[0];
-				ao.adviceFunc = args[1];
-				break;
-			case 3:
-				if((dl.isObject(args[0]))&&(dl.isString(args[1]))&&(dl.isString(args[2]))){
-					ao.adviceType = "after";
-					ao.srcObj = args[0];
-					ao.srcFunc = args[1];
-					ao.adviceFunc = args[2];
-				}else if((dl.isString(args[1]))&&(dl.isString(args[2]))){
-					ao.srcFunc = args[1];
-					ao.adviceFunc = args[2];
-				}else if((dl.isObject(args[0]))&&(dl.isString(args[1]))&&(dl.isFunction(args[2]))){
-					ao.adviceType = "after";
-					ao.srcObj = args[0];
-					ao.srcFunc = args[1];
-					var tmpName  = dl.nameAnonFunc(args[2], ao.adviceObj, searchForNames);
-					ao.adviceFunc = tmpName;
-				}else if((dl.isFunction(args[0]))&&(dl.isObject(args[1]))&&(dl.isString(args[2]))){
-					ao.adviceType = "after";
-					ao.srcObj = dj_global;
-					var tmpName  = dl.nameAnonFunc(args[0], ao.srcObj, searchForNames);
-					ao.srcFunc = tmpName;
-					ao.adviceObj = args[1];
-					ao.adviceFunc = args[2];
-				}
-				break;
-			case 4:
-				if((dl.isObject(args[0]))&&(dl.isObject(args[2]))){
-					// we can assume that we've got an old-style "connect" from
-					// the sigslot school of event attachment. We therefore
-					// assume after-advice.
-					ao.adviceType = "after";
-					ao.srcObj = args[0];
-					ao.srcFunc = args[1];
-					ao.adviceObj = args[2];
-					ao.adviceFunc = args[3];
-				}else if((dl.isString(args[0]))&&(dl.isString(args[1]))&&(dl.isObject(args[2]))){
-					ao.adviceType = args[0];
-					ao.srcObj = dj_global;
-					ao.srcFunc = args[1];
-					ao.adviceObj = args[2];
-					ao.adviceFunc = args[3];
-				}else if((dl.isString(args[0]))&&(dl.isFunction(args[1]))&&(dl.isObject(args[2]))){
-					ao.adviceType = args[0];
-					ao.srcObj = dj_global;
-					var tmpName  = dl.nameAnonFunc(args[1], dj_global, searchForNames);
-					ao.srcFunc = tmpName;
-					ao.adviceObj = args[2];
-					ao.adviceFunc = args[3];
-				}else if((dl.isString(args[0]))&&(dl.isObject(args[1]))&&(dl.isString(args[2]))&&(dl.isFunction(args[3]))){
-					ao.srcObj = args[1];
-					ao.srcFunc = args[2];
-					var tmpName  = dl.nameAnonFunc(args[3], dj_global, searchForNames);
-					ao.adviceObj = dj_global;
-					ao.adviceFunc = tmpName;
-				}else if(dl.isObject(args[1])){
-					ao.srcObj = args[1];
-					ao.srcFunc = args[2];
-					ao.adviceObj = dj_global;
-					ao.adviceFunc = args[3];
-				}else if(dl.isObject(args[2])){
-					ao.srcObj = dj_global;
-					ao.srcFunc = args[1];
-					ao.adviceObj = args[2];
-					ao.adviceFunc = args[3];
-				}else{
-					ao.srcObj = ao.adviceObj = ao.aroundObj = dj_global;
-					ao.srcFunc = args[1];
-					ao.adviceFunc = args[2];
-					ao.aroundFunc = args[3];
-				}
-				break;
-			case 6:
-				ao.srcObj = args[1];
-				ao.srcFunc = args[2];
-				ao.adviceObj = args[3]
-				ao.adviceFunc = args[4];
-				ao.aroundFunc = args[5];
-				ao.aroundObj = dj_global;
-				break;
-			default:
-				ao.srcObj = args[1];
-				ao.srcFunc = args[2];
-				ao.adviceObj = args[3]
-				ao.adviceFunc = args[4];
-				ao.aroundObj = args[5];
-				ao.aroundFunc = args[6];
-				ao.once = args[7];
-				ao.delay = args[8];
-				ao.rate = args[9];
-				ao.adviceMsg = args[10];
-				break;
-		}
+	ds.getPaddingWidth = function(node){
+		return ds._sumPixelValues(node, ["padding-left", "padding-right"], true);
+	}
 
-		if(dl.isFunction(ao.aroundFunc)){
-			var tmpName  = dl.nameAnonFunc(ao.aroundFunc, ao.aroundObj, searchForNames);
-			ao.aroundFunc = tmpName;
-		}
+	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);
+	}
 
-		if(dl.isFunction(ao.srcFunc)){
-			ao.srcFunc = dl.getNameInObj(ao.srcObj, ao.srcFunc);
-		}
+	ds.getBorderBoxWidth = function(node){
+		node = dojo.byId(node);
+		return node.offsetWidth;
+	}
 
-		if(dl.isFunction(ao.adviceFunc)){
-			ao.adviceFunc = dl.getNameInObj(ao.adviceObj, ao.adviceFunc);
-		}
+	ds.getMarginBoxWidth = function(node){
+		return ds.getInnerWidth(node) + ds.getMarginWidth(node);
+	}
 
-		if((ao.aroundObj)&&(dl.isFunction(ao.aroundFunc))){
-			ao.aroundFunc = dl.getNameInObj(ao.aroundObj, ao.aroundFunc);
+	ds.setContentBoxWidth = function(node, pxWidth){
+		node = dojo.byId(node);
+		if (ds.isBorderBox(node)){
+			pxWidth += ds.getPadBorderWidth(node);
 		}
+		return ds.setPositivePixelValue(node, "width", pxWidth);
+	}
 
-		if(!ao.srcObj){
-			dojo.raise("bad srcObj for srcFunc: "+ao.srcFunc);
-		}
-		if(!ao.adviceObj){
-			dojo.raise("bad adviceObj for adviceFunc: "+ao.adviceFunc);
+	ds.setMarginBoxWidth = function(node, pxWidth){
+		node = dojo.byId(node);
+		if (!ds.isBorderBox(node)){
+			pxWidth -= ds.getPadBorderWidth(node);
 		}
-		return ao;
+		pxWidth -= ds.getMarginWidth(node);
+		return ds.setPositivePixelValue(node, "width", pxWidth);
 	}
 
-	this.connect = function(){
-		if(arguments.length == 1){
-			var ao = arguments[0];
-		}else{
-			var ao = interpolateArgs(arguments, true);
-		}
+	// FIXME: deprecate and remove
+	ds.getContentWidth = ds.getContentBoxWidth;
+	ds.getInnerWidth = ds.getBorderBoxWidth;
+	ds.getOuterWidth = ds.getMarginBoxWidth;
+	ds.setContentWidth = ds.setContentBoxWidth;
+	ds.setOuterWidth = ds.setMarginBoxWidth;
 
-		if(dojo.lang.isArray(ao.srcObj) && ao.srcObj!=""){
-			var tmpAO = {};
-			for(var x in ao){
-				tmpAO[x] = ao[x];
-			}
-			var mjps = [];
-			dojo.lang.forEach(ao.srcObj, function(src){
-				if((dojo.render.html.capable)&&(dojo.lang.isString(src))){
-					src = dojo.byId(src);
-					// dojo.debug(src);
-				}
-				tmpAO.srcObj = src;
-				// dojo.debug(tmpAO.srcObj, tmpAO.srcFunc);
-				// dojo.debug(tmpAO.adviceObj, tmpAO.adviceFunc);
-				mjps.push(dojo.event.connect.call(dojo.event, tmpAO));
-			});
-			return mjps;
-		}
+	ds.getMarginHeight = function(node){
+		return ds._sumPixelValues(node, ["margin-top", "margin-bottom"], ds.isPositionAbsolute(node));
+	}
 
-		// FIXME: just doing a "getForMethod()" seems to be enough to put this into infinite recursion!!
-		var mjp = dojo.event.MethodJoinPoint.getForMethod(ao.srcObj, ao.srcFunc);
-		if(ao.adviceFunc){
-			var mjp2 = dojo.event.MethodJoinPoint.getForMethod(ao.adviceObj, ao.adviceFunc);
-		}
+	ds.getBorderHeight = function(node){
+		return ds.getBorderExtent(node, 'top') + ds.getBorderExtent(node, 'bottom');
+	}
 
-		mjp.kwAddAdvice(ao);
+	ds.getPaddingHeight = function(node){
+		return ds._sumPixelValues(node, ["padding-top", "padding-bottom"], true);
+	}
 
-		return mjp;	// advanced users might want to fsck w/ the join point
-					// manually
+	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);
 	}
 
-	this.log = function(a1, a2){
-		var kwArgs;
-		if((arguments.length == 1)&&(typeof a1 == "object")){
-			kwArgs = a1;
-		}else{
-			kwArgs = {
-				srcObj: a1,
-				srcFunc: a2
-			};
-		}
-		kwArgs.adviceFunc = function(){
-			var argsStr = [];
-			for(var x=0; x<arguments.length; x++){
-				argsStr.push(arguments[x]);
-			}
-			dojo.debug("("+kwArgs.srcObj+")."+kwArgs.srcFunc, ":", argsStr.join(", "));
-		}
-		this.kwConnect(kwArgs);
+	ds.getBorderBoxHeight = function(node){
+		node = dojo.byId(node);
+		return node.offsetHeight; // FIXME: does this work?
 	}
 
-	this.connectBefore = function(){
-		var args = ["before"];
-		for(var i = 0; i < arguments.length; i++) { args.push(arguments[i]); }
-		return this.connect.apply(this, args);
+	ds.getMarginBoxHeight = function(node){
+		return ds.getInnerHeight(node) + ds.getMarginHeight(node);
 	}
 
-	this.connectAround = function(){
-		var args = ["around"];
-		for(var i = 0; i < arguments.length; i++) { args.push(arguments[i]); }
-		return this.connect.apply(this, args);
+	ds.setContentBoxHeight = function(node, pxHeight){
+		node = dojo.byId(node);
+		if (ds.isBorderBox(node)){
+			pxHeight += ds.getPadBorderHeight(node);
+		}
+		return ds.setPositivePixelValue(node, "height", pxHeight);
 	}
 
-	this.connectOnce = function(){
-		var ao = interpolateArgs(arguments, true);
-		ao.once = true;
-		return this.connect(ao);
+	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);
 	}
 
-	this._kwConnectImpl = function(kwArgs, disconnect){
-		var fn = (disconnect) ? "disconnect" : "connect";
-		if(typeof kwArgs["srcFunc"] == "function"){
-			kwArgs.srcObj = kwArgs["srcObj"]||dj_global;
-			var tmpName  = dojo.lang.nameAnonFunc(kwArgs.srcFunc, kwArgs.srcObj, true);
-			kwArgs.srcFunc = tmpName;
-		}
-		if(typeof kwArgs["adviceFunc"] == "function"){
-			kwArgs.adviceObj = kwArgs["adviceObj"]||dj_global;
-			var tmpName  = dojo.lang.nameAnonFunc(kwArgs.adviceFunc, kwArgs.adviceObj, true);
-			kwArgs.adviceFunc = tmpName;
+	// 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){
+		node = dojo.byId(node);
+		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 - ds.sumAncestorProperties(node, "scrollLeft");
+			ret.y = bo.y - ds.sumAncestorProperties(node, "scrollTop");
+		}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){
+					var nd = node;
+					if(window.opera){ nd = db; }
+					ret.x -= ds.sumAncestorProperties(nd, "scrollLeft");
+					ret.y -= ds.sumAncestorProperties(nd, "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;
+			}
 		}
-		return dojo.event[fn](	(kwArgs["type"]||kwArgs["adviceType"]||"after"),
-									kwArgs["srcObj"]||dj_global,
-									kwArgs["srcFunc"],
-									kwArgs["adviceObj"]||kwArgs["targetObj"]||dj_global,
-									kwArgs["adviceFunc"]||kwArgs["targetFunc"],
-									kwArgs["aroundObj"],
-									kwArgs["aroundFunc"],
-									kwArgs["once"],
-									kwArgs["delay"],
-									kwArgs["rate"],
-									kwArgs["adviceMsg"]||false );
-	}
 
-	this.kwConnect = function(kwArgs){
-		return this._kwConnectImpl(kwArgs, false);
+		// account for document scrolling!
+		if(includeScroll){
+			ret.y += st;
+			ret.x += sl;
+		}
 
+		ret[0] = ret.x;
+		ret[1] = ret.y;
+		return ret;
 	}
 
-	this.disconnect = function(){
-		var ao = interpolateArgs(arguments, true);
-		if(!ao.adviceFunc){ return; } // nothing to disconnect
-		var mjp = dojo.event.MethodJoinPoint.getForMethod(ao.srcObj, ao.srcFunc);
-		return mjp.removeAdvice(ao.adviceObj, ao.adviceFunc, ao.adviceType, ao.once);
+	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;
+				if(node==document.body){ break; }// opera and khtml #body & #html has the same values, we only need one value
+			}
+			node = node.parentNode;
+		}
+		return retVal;
 	}
 
-	this.kwDisconnect = function(kwArgs){
-		return this._kwConnectImpl(kwArgs, true);
+	ds.getTotalOffset = function(node, type, includeScroll){
+		return ds.abs(node, includeScroll)[(type == "top") ? "y" : "x"];
 	}
-}
 
-// exactly one of these is created whenever a method with a joint point is run,
-// if there is at least one 'around' advice.
-dojo.event.MethodInvocation = function(join_point, obj, args) {
-	this.jp_ = join_point;
-	this.object = obj;
-	this.args = [];
-	for(var x=0; x<args.length; x++){
-		this.args[x] = args[x];
+	ds.getAbsoluteX = ds.totalOffsetLeft = function(node, includeScroll){
+		return ds.getTotalOffset(node, "left", includeScroll);
 	}
-	// the index of the 'around' that is currently being executed.
-	this.around_index = -1;
-}
 
-dojo.event.MethodInvocation.prototype.proceed = function() {
-	this.around_index++;
-	if(this.around_index >= this.jp_.around.length){
-		return this.jp_.object[this.jp_.methodname].apply(this.jp_.object, this.args);
-		// return this.jp_.run_before_after(this.object, this.args);
-	}else{
-		var ti = this.jp_.around[this.around_index];
-		var mobj = ti[0]||dj_global;
-		var meth = ti[1];
-		return mobj[meth].call(mobj, this);
+	ds.getAbsoluteY = ds.totalOffsetTop = function(node, includeScroll){
+		return ds.getTotalOffset(node, "top", includeScroll);
 	}
-} 
 
+	ds.styleSheet = null;
 
-dojo.event.MethodJoinPoint = function(obj, methname){
-	this.object = obj||dj_global;
-	this.methodname = methname;
-	this.methodfunc = this.object[methname];
-	this.before = [];
-	this.after = [];
-	this.around = [];
-}
+	// 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
+		}
 
-dojo.event.MethodJoinPoint.getForMethod = function(obj, methname) {
-	// if(!(methname in obj)){
-	if(!obj){ obj = dj_global; }
-	if(!obj[methname]){
-		// supply a do-nothing method implementation
-		obj[methname] = function(){};
-		if(!obj[methname]){
-			// e.g. cannot add to inbuilt objects in IE6
-			dojo.raise("Cannot set do-nothing method on that object "+methname);
+		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
 		}
-	}else if((!dojo.lang.isFunction(obj[methname]))&&(!dojo.lang.isAlien(obj[methname]))){
-		return null; // FIXME: should we throw an exception here instead?
+
+		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
 	}
-	// we hide our joinpoint instance in obj[methname + '$joinpoint']
-	var jpname = methname + "$joinpoint";
-	var jpfuncname = methname + "$joinpoint$method";
-	var joinpoint = obj[jpname];
-	if(!joinpoint){
-		var isNode = false;
-		if(dojo.event["browser"]){
-			if( (obj["attachEvent"])||
-				(obj["nodeType"])||
-				(obj["addEventListener"]) ){
-				isNode = true;
-				dojo.event.browser.addClobberNodeAttrs(obj, [jpname, jpfuncname, methname]);
+
+	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);
 		}
-		var origArity = obj[methname].length;
-		obj[jpfuncname] = obj[methname];
-		// joinpoint = obj[jpname] = new dojo.event.MethodJoinPoint(obj, methname);
-		joinpoint = obj[jpname] = new dojo.event.MethodJoinPoint(obj, jpfuncname);
-		obj[methname] = function(){ 
-			var args = [];
+		return true;
+	}
 
-			if((isNode)&&(!arguments.length)){
-				var evt = null;
-				try{
-					if(obj.ownerDocument){
-						evt = obj.ownerDocument.parentWindow.event;
-					}else if(obj.documentElement){
-						evt = obj.documentElement.ownerDocument.parentWindow.event;
-					}else{
-						evt = window.event;
-					}
-				}catch(e){
-					evt = window.event;
-				}
+	// 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(evt){
-					args.push(dojo.event.browser.fixEvent(evt, this));
-				}
-			}else{
-				for(var x=0; x<arguments.length; x++){
-					if((x==0)&&(isNode)&&(dojo.event.browser.isEvent(arguments[x]))){
-						args.push(dojo.event.browser.fixEvent(arguments[x], this));
-					}else{
-						args.push(arguments[x]);
-					}
-				}
+		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; }
 			}
-			// return joinpoint.run.apply(joinpoint, arguments); 
-			return joinpoint.run.apply(joinpoint, args); 
 		}
-		obj[methname].__preJoinArity = origArity;
-	}
-	return joinpoint;
-}
-
-dojo.lang.extend(dojo.event.MethodJoinPoint, {
-	unintercept: function(){
-		this.object[this.methodname] = this.methodfunc;
-		this.before = [];
-		this.after = [];
-		this.around = [];
-	},
-
-	disconnect: dojo.lang.forward("unintercept"),
-
-	run: function() {
-		var obj = this.object||dj_global;
-		var args = arguments;
 
-		// optimization. We only compute once the array version of the arguments
-		// pseudo-arr in order to prevent building it each time advice is unrolled.
-		var aargs = [];
-		for(var x=0; x<args.length; x++){
-			aargs[x] = args[x];
+		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
+	}
 
-		var unrollAdvice  = function(marr){ 
-			if(!marr){
-				dojo.debug("Null argument to unrollAdvice()");
-				return;
-			}
-		  
-			var callObj = marr[0]||dj_global;
-			var callFunc = marr[1];
-			
-			if(!callObj[callFunc]){
-				dojo.raise("function \"" + callFunc + "\" does not exist on \"" + callObj + "\"");
-			}
-			
-			var aroundObj = marr[2]||dj_global;
-			var aroundFunc = marr[3];
-			var msg = marr[6];
-			var undef;
-
-			var to = {
-				args: [],
-				jp_: this,
-				object: obj,
-				proceed: function(){
-					return callObj[callFunc].apply(callObj, to.args);
-				}
-			};
-			to.args = aargs;
+	// 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");
+		// IE is b0rken enough to require that we add the element to the doc
+		// before changing it's properties
+		var head = doc.getElementsByTagName("head")[0];
+		if(!head){ // must have a head tag 
+			dojo.debug("No head tag in document, aborting styles");
+			return;
+		}else{
+			head.appendChild(style);
+		}
+		if(style.styleSheet){// IE
+			style.styleSheet.cssText = cssStr;
+		}else{ // w3c
+			var cssText = doc.createTextNode(cssStr);
+			style.appendChild(cssText);
+		}
+		return style;
+	}
 
-			var delay = parseInt(marr[4]);
-			var hasDelay = ((!isNaN(delay))&&(marr[4]!==null)&&(typeof marr[4] != "undefined"));
-			if(marr[5]){
-				var rate = parseInt(marr[5]);
-				var cur = new Date();
-				var timerSet = false;
-				if((marr["last"])&&((cur-marr.last)<=rate)){
-					if(dojo.event.canTimeout){
-						if(marr["delayTimer"]){
-							clearTimeout(marr.delayTimer);
-						}
-						var tod = parseInt(rate*2); // is rate*2 naive?
-						var mcpy = dojo.lang.shallowCopy(marr);
-						marr.delayTimer = setTimeout(function(){
-							// FIXME: on IE at least, event objects from the
-							// browser can go out of scope. How (or should?) we
-							// deal with it?
-							mcpy[5] = 0;
-							unrollAdvice(mcpy);
-						}, tod);
-					}
-					return;
-				}else{
-					marr.last = cur;
-				}
+	// 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;
+	}
 
-			// FIXME: need to enforce rates for a connection here!
+	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;
+	}
 
-			if(aroundFunc){
-				// NOTE: around advice can't delay since we might otherwise depend
-				// on execution order!
-				aroundObj[aroundFunc].call(aroundObj, to);
-			}else{
-				// var tmjp = dojo.event.MethodJoinPoint.getForMethod(obj, methname);
-				if((hasDelay)&&((dojo.render.html)||(dojo.render.svg))){  // FIXME: the render checks are grotty!
-					dj_global["setTimeout"](function(){
-						if(msg){
-							callObj[callFunc].call(callObj, to); 
-						}else{
-							callObj[callFunc].apply(callObj, args); 
-						}
-					}, delay);
-				}else{ // many environments can't support delay!
-					if(msg){
-						callObj[callFunc].call(callObj, to); 
-					}else{
-						callObj[callFunc].apply(callObj, args); 
-					}
-				}
+	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;
 		}
+	}
 
-		if(this.before.length>0){
-			dojo.lang.forEach(this.before, unrollAdvice);
-		}
+	/** 
+	 * 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);
+	}
 
-		var result;
-		if(this.around.length>0){
-			var mi = new dojo.event.MethodInvocation(this, obj, args);
-			result = mi.proceed();
-		}else if(this.methodfunc){
-			result = this.object[this.methodname].apply(this.object, args);
+	/** 
+	 * 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;
 		}
+	}
 
-		if(this.after.length>0){
-			dojo.lang.forEach(this.after, unrollAdvice);
+	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;		
+	}
 
-		return (this.methodfunc) ? result : null;
-	},
+	ds.toSelectorCase = function(selector) {
+		return selector.replace(/([A-Z])/g, "-$1" ).toLowerCase() ;
+	}
 
-	getArr: function(kind){
-		var arr = this.after;
-		// FIXME: we should be able to do this through props or Array.in()
-		if((typeof kind == "string")&&(kind.indexOf("before")!=-1)){
-			arr = this.before;
-		}else if(kind=="around"){
-			arr = this.around;
-		}
-		return arr;
-	},
-
-	kwAddAdvice: function(args){
-		this.addAdvice(	args["adviceObj"], args["adviceFunc"], 
-						args["aroundObj"], args["aroundFunc"], 
-						args["adviceType"], args["precedence"], 
-						args["once"], args["delay"], args["rate"], 
-						args["adviceMsg"]);
-	},
-
-	addAdvice: function(	thisAdviceObj, thisAdvice, 
-							thisAroundObj, thisAround, 
-							advice_kind, precedence, 
-							once, delay, rate, asMessage){
-		var arr = this.getArr(advice_kind);
-		if(!arr){
-			dojo.raise("bad this: " + this);
+	/* 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; }
 		}
-
-		var ao = [thisAdviceObj, thisAdvice, thisAroundObj, thisAround, delay, rate, asMessage];
-		
-		if(once){
-			if(this.hasAdvice(thisAdviceObj, thisAdvice, advice_kind, arr) >= 0){
-				return;
+		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;
 		}
-
-		if(precedence == "first"){
-			arr.unshift(ao);
+	}
+		
+	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{
-			arr.push(ao);
+			var opac = node.style.opacity || node.style.MozOpacity ||
+				node.style.KhtmlOpacity || 1;
 		}
-	},
+		return opac >= 0.999999 ? 1.0 : Number(opac);
+	}
 
-	hasAdvice: function(thisAdviceObj, thisAdvice, advice_kind, arr){
-		if(!arr){ arr = this.getArr(advice_kind); }
-		var ind = -1;
-		for(var x=0; x<arr.length; x++){
-			var aao = (typeof thisAdvice == "object") ? (new String(thisAdvice)).toString() : thisAdvice;
-			var a1o = (typeof arr[x][1] == "object") ? (new String(arr[x][1])).toString() : arr[x][1];
-			if((arr[x][0] == thisAdviceObj)&&(a1o == aao)){
-				ind = x;
+	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;
 		}
-		return ind;
-	},
-
-	removeAdvice: function(thisAdviceObj, thisAdvice, advice_kind, once){
-		var arr = this.getArr(advice_kind);
-		var ind = this.hasAdvice(thisAdviceObj, thisAdvice, advice_kind, arr);
-		if(ind == -1){
-			return false;
-		}
-		while(ind != -1){
-			arr.splice(ind, 1);
-			if(once){ break; }
-			ind = this.hasAdvice(thisAdviceObj, thisAdvice, advice_kind, arr);
-		}
-		return true;
 	}
-});
 
-dojo.require("dojo.event");
-dojo.provide("dojo.event.topic");
+	/** 
+	* Set the given style attributes for the node. 
+	* Patch submitted by Wolfram Kriesing, 22/03/2006.
+	*
+	* Ie. dojo.style.setStyleAttributes(myNode, "position:absolute; left:10px; top:10px;") 
+	* This just makes it easier to set a style directly without the need to  
+	* override it completely (as node.setAttribute() would). 
+	* If there is a dojo-method for an attribute, like for "opacity" there 
+	* is setOpacity, the dojo method is called instead. 
+	* For example: dojo.style.setStyleAttributes(myNode, "opacity: .4"); 
+	*  
+	* Additionally all the dojo.style.set* methods can also be used. 
+	* Ie. when attributes contains "outer-height: 10;" it will call dojo.style.setOuterHeight("10"); 
+	* 
+	* @param object The node to set the style attributes for. 
+	* @param string Ie. "position:absolute; left:10px; top:10px;" 
+	*/ 
+	ds.setStyleAttributes = function(node, attributes) { 
+		var methodMap={ 
+			"opacity":dojo.style.setOpacity,
+			"content-height":dojo.style.setContentHeight,
+			"content-width":dojo.style.setContentWidth,
+			"outer-height":dojo.style.setOuterHeight,
+			"outer-width":dojo.style.setOuterWidth 
+		} 
 
-dojo.event.topic = new function(){
-	this.topics = {};
+		var splittedAttribs=attributes.replace(/(;)?\s*$/, "").split(";"); 
+		for(var i=0; i<splittedAttribs.length; i++){ 
+			var nameValue=splittedAttribs[i].split(":"); 
+			var name=nameValue[0].replace(/\s*$/, "").replace(/^\s*/, "").toLowerCase();
+			var value=nameValue[1].replace(/\s*$/, "").replace(/^\s*/, "");
+			if(dojo.lang.has(methodMap,name)) { 
+				methodMap[name](node,value); 
+			} else { 
+				node.style[dojo.style.toCamelCase(name)]=value; 
+			} 
+		} 
+	} 
 
-	this.getTopic = function(topicName){
-		if(!this.topics[topicName]){
-			this.topics[topicName] = new this.TopicImpl(topicName);
-		}
-		return this.topics[topicName];
+	ds._toggle = function(node, tester, setter){
+		node = dojo.byId(node);
+		setter(node, !tester(node));
+		return tester(node);
 	}
 
-	this.registerPublisher = function(topic, obj, funcName){
-		var topic = this.getTopic(topic);
-		topic.registerPublisher(obj, funcName);
+	// 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
+		}
 	}
 
-	this.subscribe = function(topic, obj, funcName){
-		var topic = this.getTopic(topic);
-		topic.subscribe(obj, funcName);
+	// 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');
 	}
 
-	this.unsubscribe = function(topic, obj, funcName){
-		var topic = this.getTopic(topic);
-		topic.unsubscribe(obj, funcName);
+	// setShowing() calls show() if showing is true, hide() otherwise
+	ds.setShowing = function(node, showing){
+		ds[(showing ? 'show' : 'hide')](node);
 	}
 
-	this.destroy = function(topic){
-		this.getTopic(topic).destroy();
-		delete this.topics[topic];
+	// 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');
 	}
 
-	this.publishApply = function(topic, args){
-		var topic = this.getTopic(topic);
-		topic.sendMessage.apply(topic, args);
+	// 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);
 	}
 
-	this.publish = function(topic, message){
-		var topic = this.getTopic(topic);
-		// if message is an array, we treat it as a set of arguments,
-		// otherwise, we just pass on the arguments passed in as-is
-		var args = [];
-		// could we use concat instead here?
-		for(var x=1; x<arguments.length; x++){
-			args.push(arguments[x]);
+	// 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');
 		}
-		topic.sendMessage.apply(topic, args);
 	}
-}
-
-dojo.event.topic.TopicImpl = function(topicName){
-	this.topicName = topicName;
 
-	this.subscribe = function(listenerObject, listenerMethod){
-		var tf = listenerMethod||listenerObject;
-		var to = (!listenerMethod) ? dj_global : listenerObject;
-		dojo.event.kwConnect({
-			srcObj:		this, 
-			srcFunc:	"sendMessage", 
-			adviceObj:	to,
-			adviceFunc: tf
-		});
+	// 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')));
 	}
 
-	this.unsubscribe = function(listenerObject, listenerMethod){
-		var tf = (!listenerMethod) ? listenerObject : listenerMethod;
-		var to = (!listenerMethod) ? null : listenerObject;
-		dojo.event.kwDisconnect({
-			srcObj:		this, 
-			srcFunc:	"sendMessage", 
-			adviceObj:	to,
-			adviceFunc: tf
-		});
+	// 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');
 	}
 
-	this.destroy = function(){
-		dojo.event.MethodJoinPoint.getForMethod(this, "sendMessage").disconnect();
+	// 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);
 	}
 
-	this.registerPublisher = function(publisherObject, publisherMethod){
-		dojo.event.connect(publisherObject, publisherMethod, this, "sendMessage");
+	// 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')));
 	}
 
-	this.sendMessage = function(message){
-		// The message has been propagated
+	// 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);
+	}
 
-dojo.provide("dojo.event.browser");
-dojo.require("dojo.event");
+	// 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;
+	};
+})();
 
-// FIXME: any particular reason this is in the global scope?
-dojo._ie_clobber = new function(){
-	this.clobberNodes = [];
+dojo.provide("dojo.string.common");
 
-	function nukeProp(node, prop){
-		// try{ node.removeAttribute(prop); 	}catch(e){ /* squelch */ }
-		try{ node[prop] = null; 			}catch(e){ /* squelch */ }
-		try{ delete node[prop]; 			}catch(e){ /* squelch */ }
-		// FIXME: JotLive needs this, but I'm not sure if it's too slow or not
-		try{ node.removeAttribute(prop);	}catch(e){ /* squelch */ }
-	}
+dojo.require("dojo.string");
 
-	this.clobber = function(nodeRef){
-		var na;
-		var tna;
-		if(nodeRef){
-			tna = nodeRef.all || nodeRef.getElementsByTagName("*");
-			na = [nodeRef];
-			for(var x=0; x<tna.length; x++){
-				// if we're gonna be clobbering the thing, at least make sure
-				// we aren't trying to do it twice
-				if(tna[x]["__doClobber__"]){
-					na.push(tna[x]);
-				}
-			}
-		}else{
-			try{ window.onload = null; }catch(e){}
-			na = (this.clobberNodes.length) ? this.clobberNodes : document.all;
-		}
-		tna = null;
-		var basis = {};
-		for(var i = na.length-1; i>=0; i=i-1){
-			var el = na[i];
-			if(el["__clobberAttrs__"]){
-				for(var j=0; j<el.__clobberAttrs__.length; j++){
-					nukeProp(el, el.__clobberAttrs__[j]);
-				}
-				nukeProp(el, "__clobberAttrs__");
-				nukeProp(el, "__doClobber__");
-			}
-		}
-		na = null;
-	}
+/**
+ * Trim whitespace from 'str'. If 'wh' > 0,
+ * only trim from start, if 'wh' < 0, only trim
+ * from end, otherwise trim both ends
+ */
+dojo.string.trim = function(str, wh){
+	if(!str.replace){ return str; }
+	if(!str.length){ return str; }
+	var re = (wh > 0) ? (/^\s+/) : (wh < 0) ? (/\s+$/) : (/^\s+|\s+$/g);
+	return str.replace(re, "");
 }
 
-if(dojo.render.html.ie){
-	dojo.addOnUnload(function(){
-		dojo._ie_clobber.clobber();
-		try{
-			if((dojo["widget"])&&(dojo.widget["manager"])){
-				dojo.widget.manager.destroyAll();
-			}
-		}catch(e){}
-		try{ window.onload = null; }catch(e){}
-		try{ window.onunload = null; }catch(e){}
-		dojo._ie_clobber.clobberNodes = [];
-		// CollectGarbage();
-	});
+/**
+ * Trim whitespace at the beginning of 'str'
+ */
+dojo.string.trimStart = function(str) {
+	return dojo.string.trim(str, 1);
 }
 
-dojo.event.browser = new function(){
-
-	var clobberIdx = 0;
+/**
+ * Trim whitespace at the end of 'str'
+ */
+dojo.string.trimEnd = function(str) {
+	return dojo.string.trim(str, -1);
+}
 
-	this.clean = function(node){
-		if(dojo.render.html.ie){ 
-			dojo._ie_clobber.clobber(node);
+/**
+ * Return 'str' repeated 'count' times, optionally
+ * placing 'separator' between each rep
+ */
+dojo.string.repeat = function(str, count, separator) {
+	var out = "";
+	for(var i = 0; i < count; i++) {
+		out += str;
+		if(separator && i < count - 1) {
+			out += separator;
 		}
 	}
+	return out;
+}
 
-	this.addClobberNode = function(node){
-		if(!dojo.render.html.ie){ return; }
-		if(!node["__doClobber__"]){
-			node.__doClobber__ = true;
-			dojo._ie_clobber.clobberNodes.push(node);
-			// this might not be the most efficient thing to do, but it's
-			// much less error prone than other approaches which were
-			// previously tried and failed
-			node.__clobberAttrs__ = [];
-		}
+/**
+ * Pad 'str' to guarantee that it is at least 'len' length
+ * with the character 'c' at either the start (dir=1) or
+ * end (dir=-1) of the string
+ */
+dojo.string.pad = function(str, len/*=2*/, c/*='0'*/, dir/*=1*/) {
+	var out = String(str);
+	if(!c) {
+		c = '0';
 	}
-
-	this.addClobberNodeAttrs = function(node, props){
-		if(!dojo.render.html.ie){ return; }
-		this.addClobberNode(node);
-		for(var x=0; x<props.length; x++){
-			node.__clobberAttrs__.push(props[x]);
-		}
+	if(!dir) {
+		dir = 1;
 	}
-
-	this.removeListener = function(node, evtName, fp, capture){
-		if(!capture){ var capture = false; }
-		evtName = evtName.toLowerCase();
-		if(evtName.substr(0,2)=="on"){ evtName = evtName.substr(2); }
-		// FIXME: this is mostly a punt, we aren't actually doing anything on IE
-		if(node.removeEventListener){
-			node.removeEventListener(evtName, fp, capture);
+	while(out.length < len) {
+		if(dir > 0) {
+			out = c + out;
+		} else {
+			out += c;
 		}
 	}
+	return out;
+}
 
-	this.addListener = function(node, evtName, fp, capture, dontFix){
-		if(!node){ return; } // FIXME: log and/or bail?
-		if(!capture){ var capture = false; }
-		evtName = evtName.toLowerCase();
-		if(evtName.substr(0,2)!="on"){ evtName = "on"+evtName; }
+/** same as dojo.string.pad(str, len, c, 1) */
+dojo.string.padLeft = function(str, len, c) {
+	return dojo.string.pad(str, len, c, 1);
+}
 
-		if(!dontFix){
-			// build yet another closure around fp in order to inject fixEvent
-			// around the resulting event
-			var newfp = function(evt){
-				if(!evt){ evt = window.event; }
-				var ret = fp(dojo.event.browser.fixEvent(evt, this));
-				if(capture){
-					dojo.event.browser.stopEvent(evt);
-				}
-				return ret;
-			}
-		}else{
-			newfp = fp;
-		}
+/** same as dojo.string.pad(str, len, c, -1) */
+dojo.string.padRight = function(str, len, c) {
+	return dojo.string.pad(str, len, c, -1);
+}
 
-		if(node.addEventListener){ 
-			node.addEventListener(evtName.substr(2), newfp, capture);
-			return newfp;
-		}else{
-			if(typeof node[evtName] == "function" ){
-				var oldEvt = node[evtName];
-				node[evtName] = function(e){
-					oldEvt(e);
-					return newfp(e);
-				}
-			}else{
-				node[evtName]=newfp;
-			}
-			if(dojo.render.html.ie){
-				this.addClobberNodeAttrs(node, [evtName]);
-			}
-			return newfp;
-		}
-	}
+dojo.provide("dojo.string");
+dojo.require("dojo.string.common");
 
-	this.isEvent = function(obj){
-		// FIXME: event detection hack ... could test for additional attributes
-		// if necessary
-		return (typeof obj != "undefined")&&(typeof Event != "undefined")&&(obj.eventPhase);
-		// Event does not support instanceof in Opera, otherwise:
-		//return (typeof Event != "undefined")&&(obj instanceof Event);
-	}
+dojo.provide("dojo.html");
 
-	this.currentEvent = null;
-	
-	this.callListener = function(listener, curTarget){
-		if(typeof listener != 'function'){
-			dojo.raise("listener not a function: " + listener);
+dojo.require("dojo.lang.func");
+dojo.require("dojo.dom");
+dojo.require("dojo.style");
+dojo.require("dojo.string");
+
+dojo.lang.mixin(dojo.html, dojo.dom);
+dojo.lang.mixin(dojo.html, dojo.style);
+
+// FIXME: we are going to assume that we can throw any and every rendering
+// engine into the IE 5.x box model. In Mozilla, we do this w/ CSS.
+// Need to investigate for KHTML and Opera
+
+dojo.html.clearSelection = function(){
+	try{
+		if(window["getSelection"]){ 
+			if(dojo.render.html.safari){
+				// pulled from WebCore/ecma/kjs_window.cpp, line 2536
+				window.getSelection().collapse();
+			}else{
+				window.getSelection().removeAllRanges();
+			}
+		}else if(document.selection){
+			if(document.selection.empty){
+				document.selection.empty();
+			}else if(document.selection.clear){
+				document.selection.clear();
+			}
 		}
-		dojo.event.browser.currentEvent.currentTarget = curTarget;
-		return listener.call(curTarget, dojo.event.browser.currentEvent);
+		return true;
+	}catch(e){
+		dojo.debug(e);
+		return false;
 	}
+}
 
-	this.stopPropagation = function(){
-		dojo.event.browser.currentEvent.cancelBubble = true;
+dojo.html.disableSelection = function(element){
+	element = dojo.byId(element)||document.body;
+	var h = dojo.render.html;
+	
+	if(h.mozilla){
+		element.style.MozUserSelect = "none";
+	}else if(h.safari){
+		element.style.KhtmlUserSelect = "none"; 
+	}else if(h.ie){
+		element.unselectable = "on";
+	}else{
+		return false;
 	}
+	return true;
+}
 
-	this.preventDefault = function(){
-	  dojo.event.browser.currentEvent.returnValue = false;
+dojo.html.enableSelection = function(element){
+	element = dojo.byId(element)||document.body;
+	
+	var h = dojo.render.html;
+	if(h.mozilla){ 
+		element.style.MozUserSelect = ""; 
+	}else if(h.safari){
+		element.style.KhtmlUserSelect = "";
+	}else if(h.ie){
+		element.unselectable = "off";
+	}else{
+		return false;
 	}
+	return true;
+}
 
-	this.keys = {
-		KEY_BACKSPACE: 8,
-		KEY_TAB: 9,
-		KEY_ENTER: 13,
-		KEY_SHIFT: 16,
-		KEY_CTRL: 17,
-		KEY_ALT: 18,
-		KEY_PAUSE: 19,
-		KEY_CAPS_LOCK: 20,
-		KEY_ESCAPE: 27,
-		KEY_SPACE: 32,
-		KEY_PAGE_UP: 33,
-		KEY_PAGE_DOWN: 34,
-		KEY_END: 35,
-		KEY_HOME: 36,
-		KEY_LEFT_ARROW: 37,
-		KEY_UP_ARROW: 38,
-		KEY_RIGHT_ARROW: 39,
-		KEY_DOWN_ARROW: 40,
-		KEY_INSERT: 45,
-		KEY_DELETE: 46,
-		KEY_LEFT_WINDOW: 91,
-		KEY_RIGHT_WINDOW: 92,
-		KEY_SELECT: 93,
-		KEY_F1: 112,
-		KEY_F2: 113,
-		KEY_F3: 114,
-		KEY_F4: 115,
-		KEY_F5: 116,
-		KEY_F6: 117,
-		KEY_F7: 118,
-		KEY_F8: 119,
-		KEY_F9: 120,
-		KEY_F10: 121,
-		KEY_F11: 122,
-		KEY_F12: 123,
-		KEY_NUM_LOCK: 144,
-		KEY_SCROLL_LOCK: 145
-	};
-
-	// reverse lookup
-	this.revKeys = [];
-	for(var key in this.keys){
-		this.revKeys[this.keys[key]] = key;
+dojo.html.selectElement = function(element){
+	element = dojo.byId(element);
+	if(document.selection && document.body.createTextRange){ // IE
+		var range = document.body.createTextRange();
+		range.moveToElementText(element);
+		range.select();
+	}else if(window["getSelection"]){
+		var selection = window.getSelection();
+		// FIXME: does this work on Safari?
+		if(selection["selectAllChildren"]){ // Mozilla
+			selection.selectAllChildren(element);
+		}
 	}
+}
 
-	this.fixEvent = function(evt, sender){
-		if((!evt)&&(window["event"])){
-			var evt = window.event;
-		}
-		
-		if((evt["type"])&&(evt["type"].indexOf("key") == 0)){ // key events
-			evt.keys = this.revKeys;
-			// FIXME: how can we eliminate this iteration?
-			for(var key in this.keys) {
-				evt[key] = this.keys[key];
-			}
-			if((dojo.render.html.ie)&&(evt["type"] == "keypress")){
-				evt.charCode = evt.keyCode;
-			}
-		}
-	
-		if(dojo.render.html.ie){
-			if(!evt.target){ evt.target = evt.srcElement; }
-			if(!evt.currentTarget){ evt.currentTarget = (sender ? sender : evt.srcElement); }
-			if(!evt.layerX){ evt.layerX = evt.offsetX; }
-			if(!evt.layerY){ evt.layerY = evt.offsetY; }
-			// FIXME: scroll position query is duped from dojo.html to avoid dependency on that entire module
-			var docBody = ((dojo.render.html.ie55)||(document["compatMode"] == "BackCompat")) ? document.body : document.documentElement;
-			if(!evt.pageX){ evt.pageX = evt.clientX + (docBody.scrollLeft || 0) }
-			if(!evt.pageY){ evt.pageY = evt.clientY + (docBody.scrollTop || 0) }
-			// mouseover
-			if(evt.type == "mouseover"){ evt.relatedTarget = evt.fromElement; }
-			// mouseout
-			if(evt.type == "mouseout"){ evt.relatedTarget = evt.toElement; }
-			this.currentEvent = evt;
-			evt.callListener = this.callListener;
-			evt.stopPropagation = this.stopPropagation;
-			evt.preventDefault = this.preventDefault;
-		}
-		return evt;
+dojo.html.selectInputText = function(element){
+	element = dojo.byId(element);
+	if(document.selection && document.body.createTextRange){ // IE
+		var range = element.createTextRange();
+		range.moveStart("character", 0);
+		range.moveEnd("character", element.value.length);
+		range.select();
+	}else if(window["getSelection"]){
+		var selection = window.getSelection();
+		// FIXME: does this work on Safari?
+		element.setSelectionRange(0, element.value.length);
 	}
+	element.focus();
+}
 
-	this.stopEvent = function(ev) {
-		if(window.event){
-			ev.returnValue = false;
-			ev.cancelBubble = true;
-		}else{
-			ev.preventDefault();
-			ev.stopPropagation();
+
+dojo.html.isSelectionCollapsed = function(){
+	if(document["selection"]){ // IE
+		return document.selection.createRange().text == "";
+	}else if(window["getSelection"]){
+		var selection = window.getSelection();
+		if(dojo.lang.isString(selection)){ // Safari
+			return selection == "";
+		}else{ // Mozilla/W3
+			return selection.isCollapsed;
 		}
 	}
 }
 
-dojo.kwCompoundRequire({
-	common: ["dojo.event", "dojo.event.topic"],
-	browser: ["dojo.event.browser"],
-	dashboard: ["dojo.event.browser"]
-});
-dojo.provide("dojo.event.*");
+dojo.html.getEventTarget = function(evt){
+	if(!evt) { evt = window.event || {} };
+	var t = (evt.srcElement ? evt.srcElement : (evt.target ? evt.target : null));
+	while((t)&&(t.nodeType!=1)){ t = t.parentNode; }
+	return t;
+}
 
-dojo.provide("dojo.widget.Manager");
-dojo.require("dojo.lang.array");
-dojo.require("dojo.lang.func");
-dojo.require("dojo.event.*");
+dojo.html.getDocumentWidth = function(){
+	dojo.deprecated("dojo.html.getDocument*", "replaced by dojo.html.getViewport*", "0.4");
+	return dojo.html.getViewportWidth();
+}
 
-// Manager class
-dojo.widget.manager = new function(){
-	this.widgets = [];
-	this.widgetIds = [];
-	
-	// map of widgetId-->widget for widgets without parents (top level widgets)
-	this.topWidgets = {};
+dojo.html.getDocumentHeight = function(){
+	dojo.deprecated("dojo.html.getDocument*", "replaced by dojo.html.getViewport*", "0.4");
+	return dojo.html.getViewportHeight();
+}
 
-	var widgetTypeCtr = {};
-	var renderPrefixCache = [];
+dojo.html.getDocumentSize = function(){
+	dojo.deprecated("dojo.html.getDocument*", "replaced of dojo.html.getViewport*", "0.4");
+	return dojo.html.getViewportSize();
+}
 
-	this.getUniqueId = function (widgetType) {
-		return widgetType + "_" + (widgetTypeCtr[widgetType] != undefined ?
-			++widgetTypeCtr[widgetType] : widgetTypeCtr[widgetType] = 0);
+dojo.html.getViewportWidth = function(){
+	var w = 0;
+
+	if(window.innerWidth){
+		w = window.innerWidth;
 	}
 
-	this.add = function(widget){
-		dojo.profile.start("dojo.widget.manager.add");
-		this.widgets.push(widget);
-		// Opera9 uses ID (caps)
-		if(!widget.extraArgs["id"]){
-			widget.extraArgs["id"] = widget.extraArgs["ID"];
+	if(dojo.exists(document, "documentElement.clientWidth")){
+		// IE6 Strict
+		var w2 = document.documentElement.clientWidth;
+		// this lets us account for scrollbars
+		if(!w || w2 && w2 < w) {
+			w = w2;
 		}
-		// FIXME: the rest of this method is very slow!
-		if(widget.widgetId == ""){
-			if(widget["id"]){
-				widget.widgetId = widget["id"];
-			}else if(widget.extraArgs["id"]){
-				widget.widgetId = widget.extraArgs["id"];
-			}else{
-				widget.widgetId = this.getUniqueId(widget.widgetType);
-			}
-		}
-		if(this.widgetIds[widget.widgetId]){

[... 18536 lines stripped ...]