You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@struts.apache.org by he...@apache.org on 2006/11/13 23:55:14 UTC

svn commit: r474551 [44/49] - in /struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo: ./ src/ src/alg/ src/animation/ src/cal/ src/charting/ src/charting/svg/ src/charting/vml/ src/collections/ src/crypto/ src/data/ src/data/cs...

Added: struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/TreeWithNode.js
URL: http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/TreeWithNode.js?view=auto&rev=474551
==============================================================================
--- struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/TreeWithNode.js (added)
+++ struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/TreeWithNode.js Mon Nov 13 14:54:45 2006
@@ -0,0 +1,277 @@
+/*
+	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.lang.declare");
+dojo.provide("dojo.widget.TreeWithNode");
+
+dojo.declare(
+	"dojo.widget.TreeWithNode",
+	null,
+	function(){ },
+{
+	/*
+	 * dynamic loading-related stuff. 
+	 * When an empty folder node appears, it is "UNCHECKED" first,
+	 * then after Rpc call it becomes LOADING and, finally LOADED
+	 *
+	 * tree may be dynamically loaded also
+	 */
+	loadStates: {
+		UNCHECKED: "UNCHECKED",
+    	LOADING: "LOADING",
+    	LOADED: "LOADED"
+	},
+	
+	state: "UNCHECKED",  // after creation will change to loadStates: "loaded/loading/unchecked"
+
+    //RpcUrl: "", // user can override rpc url for specific nodes
+
+	objectId: "", // the widget represents an object
+
+
+	// I need this to parse children
+	isContainer: true,
+	
+	lockLevel: 0, // lock ++ unlock --, so nested locking works fine
+	
+	lock: function() {
+		this.lockLevel++;
+	},
+	unlock: function() {
+		if (!this.lockLevel) {
+			//dojo.debug((new Error()).stack);
+			dojo.raise(this.widgetType+" unlock: not locked");
+		}
+		this.lockLevel--;
+	},
+	
+	
+	expandLevel: 0, // expand to level automatically
+	loadLevel: 0, // load to level automatically
+		
+	hasLock: function() {
+		return this.lockLevel>0;
+	},
+
+	isLocked: function() {
+		var node = this;
+		while (true) {
+			if (node.lockLevel) {
+				return true;
+			}
+			if (!node.parent || node.isTree) {
+				break;
+			}
+			
+			node = node.parent;
+			
+		}
+
+		return false;
+	},
+
+	
+	flushLock: function() {
+		this.lockLevel = 0;
+		//this.unMarkLoading();
+	},
+	
+	
+	actionIsDisabled: function(action) {
+		var disabled = false;
+
+		if (dojo.lang.inArray(this.actionsDisabled, action)) {
+			disabled = true;
+		}
+
+
+		//dojo.debug("Check "+this+" "+disabled)
+		
+		
+		if (this.isTreeNode) {
+			if (!this.tree.allowAddChildToLeaf && action == this.actions.ADDCHILD && !this.isFolder) {
+				disabled = true;
+			}
+		}
+		return disabled;
+	},
+		
+	actionIsDisabledNow: function(action) {
+		return this.actionIsDisabled(action) || this.isLocked();
+	},
+	
+	
+	/**
+	 * childrenArray is array of Widgets or array of Objects
+	 * widgets may be both attached and detached
+	 *
+	 * Use Cases
+	 * 1) lots of widgets are packed and passed in.
+	 *  - widgets are created
+	 *  - widgets have no parent (detached or not attached yet)
+	 *
+	 * 2) array of widgets and data objects passed in with flag makeWidgetsFromChildren
+	 *  - some widgets are not created
+	 *  - all objects have no parent
+	 *
+	 * 3) expand is called with makeWidgetsFromChildren=true
+	 *  - some objects need to be turned into widgets
+	 *  - some widgets have parent (e.g markup), some widgets and objects do not
+	 *
+	 *  Will folderize a node as side-effect.
+	 */
+	setChildren: function(childrenArray) {
+		//dojo.profile.start("setChildren "+this);
+		//dojo.debug("setChildren in "+this);
+		
+		
+		if (this.isTreeNode && !this.isFolder) {
+			//dojo.debug("folder parent "+parent+ " isfolder "+parent.isFolder);
+			this.setFolder();
+		} else if (this.isTreeNode) {
+			this.state = this.loadStates.LOADED;
+		}
+		
+		var hadChildren = this.children.length > 0;
+		
+        if (hadChildren && childrenArray){
+            // perf: most of time setChildren used for empty nodes, so save function call
+            this.destroyChildren()
+        }
+        
+		if (childrenArray) {
+			this.children = childrenArray;
+		}
+		
+
+
+		var hasChildren = this.children.length > 0;
+		if (this.isTreeNode && hasChildren != hadChildren) {
+			// call only when hasChildren state changes
+			this.viewSetHasChildren();
+		}
+		
+
+
+		for(var i=0; i<this.children.length; i++) {
+			var child = this.children[i];
+			
+			//dojo.profile.start("setChildren - create "+this);
+			
+			if (!(child instanceof dojo.widget.Widget)) {
+				
+				child = this.children[i] = this.tree.createNode(child);
+				var childWidgetCreated = true;	
+				//dojo.debugShallow(child)
+				
+				//dojo.debug("setChildren creates node "+child);
+			} else {
+				var childWidgetCreated = false;
+			}
+			
+			//dojo.profile.end("setChildren - create "+this);
+
+			//dojo.profile.start("setChildren - attach "+this);
+
+			if (!child.parent) { // detached child
+				
+				//dojo.debug("detached child "+child);
+				
+				child.parent = this;
+
+				//dojo.profile.start("setChildren - updateTree "+this);
+				
+				if (this.tree !== child.tree) {				
+					child.updateTree(this.tree);
+				}
+				//dojo.profile.end("setChildren - updateTree "+this);
+
+			
+				//dojo.debug("Add layout for "+child);
+				child.viewAddLayout();
+				this.containerNode.appendChild(child.domNode);
+					
+				var message = {
+					child: child,
+					index: i,
+					parent: this,
+					childWidgetCreated: childWidgetCreated
+				}
+			
+				delete dojo.widget.manager.topWidgets[child.widgetId];
+		
+
+				//dojo.profile.start("setChildren - event "+this);
+				//dojo.debug("publish "+this.tree.eventNames.afterAddChild)
+				dojo.event.topic.publish(this.tree.eventNames.afterAddChild, message);
+
+				//dojo.profile.end("setChildren - event "+this);
+
+			}
+			
+			if (this.tree.eagerWidgetInstantiation) {
+				dojo.lang.forEach(this.children, function(child) {
+					child.setChildren();
+				});
+			}
+
+			//dojo.profile.end("setChildren - attach "+this);
+
+		
+		}
+		
+
+
+		//dojo.profile.end("setChildren "+this);
+		
+	},	
+	
+	
+	doAddChild: function(child, index) {
+		return this.addChild(child, index, true);
+	},
+		
+	addChild: function(child, index, dontPublishEvent) {
+		if (dojo.lang.isUndefined(index)) {
+			index = this.children.length;
+		}
+		
+		//dojo.debug("doAddChild "+index+" called for "+this+" child "+child+" existing children "+(this.children.length ? this.children : "<no children>"));
+				
+		if (!child.isTreeNode){
+			dojo.raise("You can only add TreeNode widgets to a "+this.widgetType+" widget!");
+			return;
+		}
+			
+		this.children.splice(index, 0, child);
+		child.parent = this;
+				
+		child.addedTo(this, index, dontPublishEvent);
+		
+		// taken from DomWidget.registerChild
+		// delete from widget list that are notified on resize etc (no parent)
+		delete dojo.widget.manager.topWidgets[child.widgetId];
+				
+	},
+	
+	 /**
+     * does not inform children about resize (skips onShow),
+     * because on large trees that's slow
+     */
+    onShow: function() {        
+        this.animationInProgress=false;
+    },
+    
+    onHide: function() {        
+        this.animationInProgress=false;
+    }
+	
+});

Propchange: struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/TreeWithNode.js
------------------------------------------------------------------------------
    svn:eol-style = native

Added: struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/UsTextbox.js
URL: http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/UsTextbox.js?view=auto&rev=474551
==============================================================================
--- struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/UsTextbox.js (added)
+++ struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/UsTextbox.js Mon Nov 13 14:54:45 2006
@@ -0,0 +1,88 @@
+/*
+	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.widget.UsTextbox");
+
+dojo.require("dojo.widget.ValidationTextbox");
+dojo.require("dojo.validate.us");
+
+dojo.widget.defineWidget(
+	"dojo.widget.UsStateTextbox",
+	dojo.widget.ValidationTextbox,
+	{
+		// summary: a Textbox which tests for a United States state abbreviation
+		// allowTerritories  Allow Guam, Puerto Rico, etc.  Default is true.
+		// allowMilitary     Allow military 'states', e.g. Armed Forces Europe (AE). Default is true.
+
+		mixInProperties: function(/*Object*/localProperties){
+			// summary: see dojo.widget.Widget
+
+			// Initialize properties in super-class.
+			dojo.widget.UsStateTextbox.superclass.mixInProperties.apply(this, arguments);
+
+			// Get properties from markup attributes, and assign to flags object.
+			if(localProperties.allowterritories){
+				this.flags.allowTerritories = (localProperties.allowterritories == "true");
+			}
+			if(localProperties.allowmilitary){
+				this.flags.allowMilitary = (localProperties.allowmilitary == "true");
+			}
+		},
+
+		isValid: function(){
+			// summary: see dojo.widget.ValidationTextbox
+			return dojo.validate.us.isState(this.textbox.value, this.flags);
+		}
+	}
+);
+
+/*
+  ****** UsZipTextbox ******
+
+  A subclass of ValidationTextbox.
+  Over-rides isValid to test if input is a US zip code.
+  Validates zip-5 and zip-5 plus 4.
+*/
+dojo.widget.defineWidget(
+	"dojo.widget.UsZipTextbox",
+	dojo.widget.ValidationTextbox,
+	{
+		// summary: a Textbox which tests for a United States postal code
+		isValid: function(){
+			// summary: see dojo.widget.ValidationTextbox
+			return dojo.validate.us.isZipCode(this.textbox.value);
+		}
+	}
+);
+
+dojo.widget.defineWidget(
+	"dojo.widget.UsSocialSecurityNumberTextbox",
+	dojo.widget.ValidationTextbox,
+	{
+		// summary: a Textbox which tests for a United States Social Security number
+		isValid: function(){
+			// summary: see dojo.widget.ValidationTextbox
+			return dojo.validate.us.isSocialSecurityNumber(this.textbox.value);
+		}
+	}
+);
+
+dojo.widget.defineWidget(
+	"dojo.widget.UsPhoneNumberTextbox",
+	dojo.widget.ValidationTextbox,
+	{
+		// summary: a Textbox which tests for a United States 10-digit telephone number, extension is optional.
+
+		isValid: function(){
+			// summary: see dojo.widget.ValidationTextbox
+			return dojo.validate.us.isPhoneNumber(this.textbox.value);
+		}
+	}
+);

Propchange: struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/UsTextbox.js
------------------------------------------------------------------------------
    svn:eol-style = native

Added: struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/ValidationTextbox.js
URL: http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/ValidationTextbox.js?view=auto&rev=474551
==============================================================================
--- struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/ValidationTextbox.js (added)
+++ struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/ValidationTextbox.js Mon Nov 13 14:54:45 2006
@@ -0,0 +1,195 @@
+/*
+	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.widget.ValidationTextbox");
+
+dojo.require("dojo.widget.Textbox");
+dojo.require("dojo.i18n.common");
+
+/*
+  ****** ValidationTextbox ******
+
+  A subclass of Textbox.
+  Over-ride isValid in subclasses to perform specific kinds of validation.
+  Has several new properties that can be specified as attributes in the markup.
+
+  @attr type          		Basic input tag type declaration.
+  @attr size          		Basic input tag size declaration.
+  @attr type          		Basic input tag maxlength declaration.	
+  @attr required          	Can be true or false, default is false.
+  @attr validColor        	The color textbox is highlighted for valid input. Default is #cfc.
+  @attr invalidColor      	The color textbox is highlighted for invalid input. Default is #fcc.
+  @attr invalidClass		Class used to format displayed text in page if necessary to override default class
+  @attr invalidMessage    	The message to display if value is invalid.
+  @attr missingMessage    	The message to display if value is missing.
+  @attr missingClass		Override default class used for missing input data
+  @attr listenOnKeyPress	Updates messages on each key press.  Default is true.
+  @attr promptMessage		Will not issue invalid message if field is populated with default user-prompt text
+*/
+dojo.widget.defineWidget(
+	"dojo.widget.ValidationTextbox",
+	dojo.widget.Textbox,
+	function() {
+		// this property isn't a primitive and needs to be created on a per-item basis.
+		this.flags = {};
+	},
+	{
+		// default values for new subclass properties
+		required: false,
+		rangeClass: "range",
+		invalidClass: "invalid",
+		missingClass: "missing",
+		classPrefix: "dojoValidate",
+		size: "",
+		maxlength: "",
+		promptMessage: "",
+		invalidMessage: "",
+		missingMessage: "",
+		rangeMessage: "",
+		listenOnKeyPress: true,
+		htmlfloat: "none",
+		lastCheckedValue: null,
+	
+		templatePath: dojo.uri.dojoUri("src/widget/templates/ValidationTextbox.html"),
+		templateCssPath: dojo.uri.dojoUri("src/widget/templates/Validate.css"),
+		
+		// new DOM nodes
+		invalidSpan: null,
+		missingSpan: null,
+		rangeSpan: null,
+	
+		getValue: function() {
+			return this.textbox.value;
+		},
+	
+		setValue: function(value) {
+			this.textbox.value = value;
+			this.update();
+		},
+	
+		// Need to over-ride with your own validation code in subclasses
+		isValid: function() { return true; },
+	
+		// Need to over-ride with your own validation code in subclasses
+		isInRange: function() { return true; },
+	
+		// Returns true if value is all whitespace
+		isEmpty: function() { 
+			return ( /^\s*$/.test(this.textbox.value) );
+		},
+	
+		// Returns true if value is required and it is all whitespace.
+		isMissing: function() { 
+			return ( this.required && this.isEmpty() );
+		},
+	
+		// Called oninit, onblur, and onkeypress.
+		// Show missing or invalid messages if appropriate, and highlight textbox field.
+		update: function() {
+			this.lastCheckedValue = this.textbox.value;
+			this.missingSpan.style.display = "none";
+			this.invalidSpan.style.display = "none";
+			this.rangeSpan.style.display = "none";
+	
+			var empty = this.isEmpty();
+			var valid = true;
+			if(this.promptMessage != this.textbox.value){ 
+				valid = this.isValid(); 
+			}
+			var missing = this.isMissing();
+	
+			// Display at most one error message
+			if(missing){
+				this.missingSpan.style.display = "";
+			}else if( !empty && !valid ){
+				this.invalidSpan.style.display = "";
+			}else if( !empty && !this.isInRange() ){
+				this.rangeSpan.style.display = "";
+			}
+			this.highlight();
+		},
+		
+		updateClass: function(className){
+		//summary: used to ensure that only 1 validation class is set at a time
+			var pre = this.classPrefix;
+			dojo.html.removeClass(this.textbox,pre+"Empty");
+			dojo.html.removeClass(this.textbox,pre+"Valid");
+			dojo.html.removeClass(this.textbox,pre+"Invalid");
+			dojo.html.addClass(this.textbox,pre+className);
+		},
+		
+		// Called oninit, and onblur.
+		highlight: function() {
+			// highlight textbox background 
+			if (this.isEmpty()) {
+				this.updateClass("Empty");
+			}else if (this.isValid() && this.isInRange() ){
+				this.updateClass("Valid");
+			}else if(this.textbox.value != this.promptMessage){ 
+				this.updateClass("Invalid");
+			}else{
+				this.updateClass("Empty");
+			}
+		},
+	
+		onfocus: function(evt) {
+			if ( !this.listenOnKeyPress) {
+				this.updateClass("Empty");
+//			    this.textbox.style.backgroundColor = "";
+			}
+		},
+	
+		onblur: function(evt) { 
+			this.filter();
+			this.update(); 
+		},
+	
+		onkeyup: function(evt){ 
+			if(this.listenOnKeyPress){ 
+				//this.filter();  trim is problem if you have to type two words
+				this.update(); 
+			}else if (this.textbox.value != this.lastCheckedValue){
+				this.updateClass("Empty");
+//			    this.textbox.style.backgroundColor = "";
+			}
+		},
+
+		postMixInProperties: function(localProperties, frag) {
+			dojo.widget.ValidationTextbox.superclass.postMixInProperties.apply(this, arguments);
+			this.messages = dojo.i18n.getLocalization("dojo.widget", "validate", this.lang);
+			dojo.lang.forEach(["invalidMessage", "missingMessage", "rangeMessage"], function(prop) {
+				if(this[prop]){ this.messages[prop] = this[prop]; }
+			}, this);
+		},
+	
+		// FIXME: why are there to fillInTemplate methods defined here?
+		fillInTemplate: function() {
+			dojo.widget.ValidationTextbox.superclass.fillInTemplate.apply(this, arguments);
+
+			// Attach isMissing and isValid methods to the textbox.
+			// We may use them later in connection with a submit button widget.
+			// TODO: this is unorthodox; it seems better to do it another way -- Bill
+			this.textbox.isValid = function() { this.isValid.call(this); };
+			this.textbox.isMissing = function() { this.isMissing.call(this); };
+			this.textbox.isInRange = function() { this.isInRange.call(this); };
+			dojo.html.setClass(this.invalidSpan,this.invalidClass);
+			this.update(); 
+			
+			// apply any filters to initial value
+			this.filter();
+
+			// set table to be inlined (technique varies by browser)
+			if(dojo.render.html.ie){ dojo.html.addClass(this.domNode, "ie"); }
+			if(dojo.render.html.moz){ dojo.html.addClass(this.domNode, "moz"); }
+			if(dojo.render.html.opera){ dojo.html.addClass(this.domNode, "opera"); }
+			if(dojo.render.html.safari){ dojo.html.addClass(this.domNode, "safari"); }
+		}
+	}
+);

Propchange: struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/ValidationTextbox.js
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/Widget.js
URL: http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/Widget.js?view=diff&rev=474551&r1=474550&r2=474551
==============================================================================
--- struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/Widget.js (original)
+++ struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/Widget.js Mon Nov 13 14:54:45 2006
@@ -1,5 +1,5 @@
 /*
-	Copyright (c) 2004-2005, The Dojo Foundation
+	Copyright (c) 2004-2006, The Dojo Foundation
 	All Rights Reserved.
 
 	Licensed under the Academic Free License version 2.1 or above OR the
@@ -9,145 +9,328 @@
 */
 
 dojo.provide("dojo.widget.Widget");
-dojo.provide("dojo.widget.tags");
 
-dojo.require("dojo.lang");
+dojo.require("dojo.lang.func");
+dojo.require("dojo.lang.array");
+dojo.require("dojo.lang.extras");
+dojo.require("dojo.lang.declare");
+dojo.require("dojo.ns");
 dojo.require("dojo.widget.Manager");
 dojo.require("dojo.event.*");
-dojo.require("dojo.string");
+dojo.require("dojo.a11y");
 
-dojo.widget.Widget = function(){
-	// these properties aren't primitives and need to be created on a per-item
-	// basis.
-	this.children = [];
-	// this.selection = new dojo.widget.Selection();
-	// FIXME: need to replace this with context menu stuff
-	this.extraArgs = {};
-}
-// FIXME: need to be able to disambiguate what our rendering context is
-//        here!
-
-// needs to be a string with the end classname. Every subclass MUST
-// over-ride.
-dojo.lang.extend(dojo.widget.Widget, {
+dojo.declare("dojo.widget.Widget", null,
+	function(){
+		//dojo.debug("NEW "+this.widgetType);
+		// these properties aren't primitives and need to be created on a per-item
+		// basis.
+		this.children = [];
+		// this.selection = new dojo.widget.Selection();
+		// FIXME: need to replace this with context menu stuff
+		this.extraArgs = {};
+	},
+{
+	// FIXME: need to be able to disambiguate what our rendering context is
+	//        here!
+	//
+	// needs to be a string with the end classname. Every subclass MUST
+	// over-ride.
+	//
 	// base widget properties
-	parent: null,
+
+	// Widget: the parent of this widget
+	parent: null, 
+
+	// NOTE: "children" and "extraArgs" re-defined in the constructor as they need to be local to the widget
+
+	// Array:
+	//		a list of all of the widgets that have been added as children of
+	//		this component. Should only have values if isContainer is true.
+	children: [],
+
+	// Object:
+	//		a map of properties which the widget system tried to assign from
+	//		user input but did not correspond to any of the properties set on
+	//		the class prototype. These names will also be available in all
+	//		lower-case form in this map
+	extraArgs: {},
+
 	// obviously, top-level and modal widgets should set these appropriately
-	isTopLevel:  false,
-	isModal: false,
 
+	// Boolean: should this widget eat all events that bubble up to it?
+	isTopLevel:  false, 
+
+	// Boolean: should this widget block other widgets?
+	isModal: false, 
+
+	// Boolean: should this widget respond to user input?
 	isEnabled: true,
+
+	// Boolean: have we hidden the widget via hide()?
 	isHidden: false,
-	isContainer: false, // can we contain other widgets?
+
+	// Boolean: can this widget contain other widgets?
+	isContainer: false, 
+
+	// String:
+	//		a unique, opaque ID string that can be assigned by users or by the
+	//		system. If the developer passes an ID which is known not to be
+	//		unique, the specified ID is ignored and the system-generated ID is
+	//		used instead.
 	widgetId: "",
-	widgetType: "Widget", // used for building generic widgets
 
-	toString: function() {
-		return '[Widget ' + this.widgetType + ', ' + (this.widgetId || 'NO ID') + ']';
+	// String: used for building generic widgets
+	widgetType: "Widget",
+
+	// String: defaults to 'dojo'.  "namespace" is a reserved word in JavaScript, so we abbreviate
+	ns: "dojo",
+
+	getNamespacedType: function(){ 
+		// summary:
+		//		get the "full" name of the widget. If the widget comes from the
+		//		"dojo" namespace and is a Button, calling this method will
+		//		return "dojo:button", all lower-case
+		return (this.ns ? this.ns + ":" + this.widgetType : this.widgetType).toLowerCase(); // String
+	},
+	
+	toString: function(){
+		// summary:
+		//		returns a string that represents the widget. When a widget is
+		//		cast to a string, this method will be used to generate the
+		//		output. Currently, it does not implement any sort of reversable
+		//		serialization.
+		return '[Widget ' + this.getNamespacedType() + ', ' + (this.widgetId || 'NO ID') + ']'; // String
 	},
 
 	repr: function(){
-		return this.toString();
+		// summary: returns the string representation of the widget.
+		return this.toString(); // String
 	},
 
 	enable: function(){
-		// should be over-ridden
+		// summary:
+		//		enables the widget, usually involving unmasking inputs and
+		//		turning on event handlers. Not implemented here.
 		this.isEnabled = true;
 	},
 
 	disable: function(){
-		// should be over-ridden
+		// summary:
+		//		disables the widget, usually involves masking inputs and
+		//		unsetting event handlers. Not implemented here.
 		this.isEnabled = false;
 	},
 
 	hide: function(){
-		// should be over-ridden
+		// summary: hides the widget from view. Not implemented here.
 		this.isHidden = true;
 	},
 
 	show: function(){
-		// should be over-ridden
+		// summary: re-adds the widget to the view. Not implemented here.
 		this.isHidden = false;
 	},
 
-	create: function(args, fragment, parentComp){
+	onResized: function(){
+		// summary:
+		//		A signal that widgets will call when they have been resized.
+		//		Can be connected to for determining if a layout needs to be
+		//		reflowed. Clients should override this function to do special
+		//		processing, then call this.notifyChildrenOfResize() to notify
+		//		children of resize.
+		this.notifyChildrenOfResize();
+	},
+	
+	notifyChildrenOfResize: function(){
+		// summary: dispatches resized events to all children of this widget
+		for(var i=0; i<this.children.length; i++){
+			var child = this.children[i];
+			//dojo.debug(this.widgetId + " resizing child " + child.widgetId);
+			if( child.onResized ){
+				child.onResized();
+			}
+		}
+	},
+
+	create: function(/*Object*/ args, /*Object*/fragment, /*Widget, optional*/parent, /*String, optional*/ns){
+		// summary:
+		//		'create' manages the initialization part of the widget
+		//		lifecycle. It's called implicitly when any widget is created.
+		//		All other initialization functions for widgets, except for the
+		//		constructor, are called as a result of 'create' being fired.
+		// args:
+		//		a normalized view of the parameters that the widget should take
+		// fragment:
+		//		if the widget is being instantiated from markup, this object 
+		// parent:
+		//		the widget, if any, that this widget will be the child of.  If
+		//		none is passed, the global default widget is used.
+		// ns: what namespace the widget belongs to
+		// description:
+		//		to understand the process by which widgets are instantiated, it
+		//		is critical to understand what other methods 'create' calls and
+		//		which of them you'll want to over-ride. Of course, adventurous
+		//		developers could over-ride 'create' entirely, but this should
+		//		only be done as a last resort.
+		//
+		//		Below is a list of the methods that are called, in the order
+		//		they are fired, along with notes about what they do and if/when
+		//		you should over-ride them in your widget:
+		//			
+		//			mixInProperties:
+		//				takes the args and does lightweight type introspection
+		//				on pre-existing object properties to initialize widget
+		//				values by casting the values that are passed in args
+		//			postMixInProperties:
+		//				a stub function that you can over-ride to modify
+		//				variables that may have been naively assigned by
+		//				mixInProperties
+		//			# widget is added to manager object here
+		//			buildRendering
+		//				subclasses use this method to handle all UI initialization
+		//			initialize:
+		//				a stub function that you can over-ride.
+		//			postInitialize:
+		//				a stub function that you can over-ride.
+		//			postCreate
+		//				a stub function that you can over-ride to modify take
+		//				actions once the widget has been placed in the UI
+		//
+		//		all of these functions are passed the same arguments as are
+		//		passed to 'create'
+
+		//dojo.profile.start(this.widgetType + " create");
+		if(ns){
+			this.ns = ns;
+		}
 		// dojo.debug(this.widgetType, "create");
-		this.satisfyPropertySets(args, fragment, parentComp);
+		//dojo.profile.start(this.widgetType + " satisfyPropertySets");
+		this.satisfyPropertySets(args, fragment, parent);
+		//dojo.profile.end(this.widgetType + " satisfyPropertySets");
 		// dojo.debug(this.widgetType, "-> mixInProperties");
-		this.mixInProperties(args, fragment, parentComp);
+		//dojo.profile.start(this.widgetType + " mixInProperties");
+		this.mixInProperties(args, fragment, parent);
+		//dojo.profile.end(this.widgetType + " mixInProperties");
 		// dojo.debug(this.widgetType, "-> postMixInProperties");
-		this.postMixInProperties(args, fragment, parentComp);
+		//dojo.profile.start(this.widgetType + " postMixInProperties");
+		this.postMixInProperties(args, fragment, parent);
+		//dojo.profile.end(this.widgetType + " postMixInProperties");
 		// dojo.debug(this.widgetType, "-> dojo.widget.manager.add");
 		dojo.widget.manager.add(this);
 		// dojo.debug(this.widgetType, "-> buildRendering");
-		this.buildRendering(args, fragment, parentComp);
+		//dojo.profile.start(this.widgetType + " buildRendering");
+		this.buildRendering(args, fragment, parent);
+		//dojo.profile.end(this.widgetType + " buildRendering");
 		// dojo.debug(this.widgetType, "-> initialize");
-		this.initialize(args, fragment, parentComp);
+		//dojo.profile.start(this.widgetType + " initialize");
+		this.initialize(args, fragment, parent);
+		//dojo.profile.end(this.widgetType + " initialize");
 		// dojo.debug(this.widgetType, "-> postInitialize");
-		this.postInitialize(args, fragment, parentComp);
+		// postinitialize includes subcomponent creation
+		// profile is put directly to function
+		this.postInitialize(args, fragment, parent);
 		// dojo.debug(this.widgetType, "-> postCreate");
-		this.postCreate(args, fragment, parentComp);
+		//dojo.profile.start(this.widgetType + " postCreate");
+		this.postCreate(args, fragment, parent);
+		//dojo.profile.end(this.widgetType + " postCreate");
 		// dojo.debug(this.widgetType, "done!");
+		
+		//dojo.profile.end(this.widgetType + " create");
+		
 		return this;
 	},
 
-	destroy: function(finalize){
+	destroy: function(/*Boolean*/finalize){
+		// summary:
+		// 		Destroy this widget and it's descendants. This is the generic
+		// 		"destructor" function that all widget users should call to
+		// 		clealy discard with a widget. Once a widget is destroyed, it's
+		// 		removed from the manager object.
+		// finalize:
+		//		is this function being called part of global environment
+		//		tear-down?
+
 		// FIXME: this is woefully incomplete
+		this.destroyChildren();
 		this.uninitialize();
 		this.destroyRendering(finalize);
 		dojo.widget.manager.removeById(this.widgetId);
 	},
 
-	destroyChildren: function(testFunc){
-		testFunc = (!testFunc) ? function(){ return true; } : testFunc;
-		for(var x=0; x<this.children.length; x++){
-			var tc = this.children[x];
-			if((tc)&&(testFunc(tc))){
-				tc.destroy();
+	destroyChildren: function(){
+		// summary:
+		//		Recursively destroy the children of this widget and their
+		//		descendents.
+		var widget;
+		var i=0;
+		while(this.children.length > i){
+			widget = this.children[i];
+			if (widget instanceof dojo.widget.Widget) { // find first widget
+				this.removeChild(widget);
+				widget.destroy();
+				continue;
 			}
+			
+			i++; // skip data object
 		}
-		// this.children = [];
+				
 	},
 
-	destroyChildrenOfType: function(type){
-		type = type.toLowerCase();
-		this.destroyChildren(function(item){
-			if(item.widgetType.toLowerCase() == type){
-				return true;
-			}else{
-				return false;
-			}
-		});
-	},
-
-	getChildrenOfType: function(type, recurse){
+	getChildrenOfType: function(/*String*/type, /*Boolean*/recurse){
+		// summary: 
+		//		return an array of descendant widgets who match the passed type
+		// recurse:
+		//		should we try to get all descendants that match? Defaults to
+		//		false.
 		var ret = [];
-		type = type.toLowerCase();
+		var isFunc = dojo.lang.isFunction(type);
+		if(!isFunc){
+			type = type.toLowerCase();
+		}
 		for(var x=0; x<this.children.length; x++){
-			if(this.children[x].widgetType.toLowerCase() == type){
-				ret.push(this.children[x]);
+			if(isFunc){
+				if(this.children[x] instanceof type){
+					ret.push(this.children[x]);
+				}
+			}else{
+				if(this.children[x].widgetType.toLowerCase() == type){
+					ret.push(this.children[x]);
+				}
 			}
 			if(recurse){
 				ret = ret.concat(this.children[x].getChildrenOfType(type, recurse));
 			}
 		}
-		return ret;
+		return ret; // Array
 	},
 
 	getDescendants: function(){
-		// FIXME: this does not appear to be recursive. Shouldn't a function 
-		// with this signature get *all* descendants?
+		// summary: returns a flattened array of all direct descendants including self
 		var result = [];
 		var stack = [this];
 		var elem;
-		while (elem = stack.pop()){
+		while ((elem = stack.pop())){
 			result.push(elem);
-			dojo.lang.forEach(elem.children, function(elem) { stack.push(elem); });
+			// a child may be data object without children field set (not widget)
+			if (elem.children) {
+				dojo.lang.forEach(elem.children, function(elem) { stack.push(elem); });
+			}
 		}
-		return result;
+		return result; // Array
+	},
+
+
+	isFirstChild: function(){
+		return this === this.parent.children[0]; // Boolean
+	},
+
+	isLastChild: function() {
+		return this === this.parent.children[this.parent.children.length-1]; // Boolean
 	},
 
 	satisfyPropertySets: function(args){
+		// summary: not implemented!
+
 		// dojo.profile.start("satisfyPropertySets");
 		// get the default propsets for our component type
 		/*
@@ -168,7 +351,48 @@
 		return args;
 	},
 
-	mixInProperties: function(args, frag){
+	mixInProperties: function(/*Object*/args, /*Object*/frag){
+		// summary:
+		// 		takes the list of properties listed in args and sets values of
+		// 		the current object based on existence of properties with the
+		// 		same name (case insensitive) and the type of the pre-existing
+		// 		property. This is a lightweight conversion and is not intended
+		// 		to capture custom type semantics.
+		// args:
+		//		A map of properties and values to set on the current object. By
+		//		default it is assumed that properties in args are in string
+		//		form and need to be converted. However, if there is a
+		//		'fastMixIn' property with the value 'true' in the args param,
+		//		this assumption is ignored and all values in args are copied
+		//		directly to the current object without any form of type
+		//		casting.
+		// description:
+		//		The mix-in code attempts to do some type-assignment based on
+		//		PRE-EXISTING properties of the "this" object. When a named
+		//		property of args is located, it is first tested to make
+		//		sure that the current object already "has one". Properties
+		//		which are undefined in the base widget are NOT settable here.
+		//		The next step is to try to determine type of the pre-existing
+		//		property. If it's a string, the property value is simply
+		//		assigned. If a function, it is first cast using "new
+		//		Function()" and the execution scope modified such that it
+		//		always evaluates in the context of the current object. This
+		//		listener is then added to the original function via
+		//		dojo.event.connect(). If an Array, the system attempts to split
+		//		the string value on ";" chars, and no further processing is
+		//		attempted (conversion of array elements to a integers, for
+		//		instance). If the property value is an Object
+		//		(testObj.constructor === Object), the property is split first
+		//		on ";" chars, secondly on ":" chars, and the resulting
+		//		key/value pairs are assigned to an object in a map style. The
+		//		onus is on the property user to ensure that all property values
+		//		are converted to the expected type before usage. Properties
+		//		which do not occur in the "this" object are assigned to the
+		//		this.extraArgs map using both the original name and the
+		//		lower-case name of the property. This allows for consistent
+		//		access semantics regardless of the case preservation of the
+		//		source of the property names.
+		
 		if((args["fastMixIn"])||(frag["fastMixIn"])){
 			// dojo.profile.start("mixInProperties_fastMixIn");
 			// fast mix in assumes case sensitivity, no type casting, etc...
@@ -180,24 +404,6 @@
 			return;
 		}
 		// dojo.profile.start("mixInProperties");
-		/*
-		 * the actual mix-in code attempts to do some type-assignment based on
-		 * PRE-EXISTING properties of the "this" object. When a named property
-		 * of a propset is located, it is first tested to make sure that the
-		 * current object already "has one". Properties which are undefined in
-		 * the base widget are NOT settable here. The next step is to try to
-		 * determine type of the pre-existing property. If it's a string, the
-		 * property value is simply assigned. If a function, the property is
-		 * replaced with a "new Function()" declaration. If an Array, the
-		 * system attempts to split the string value on ";" chars, and no
-		 * further processing is attempted (conversion of array elements to a
-		 * integers, for instance). If the property value is an Object
-		 * (testObj.constructor === Object), the property is split first on ";"
-		 * chars, secondly on ":" chars, and the resulting key/value pairs are
-		 * assigned to an object in a map style. The onus is on the property
-		 * user to ensure that all property values are converted to the
-		 * expected type before usage.
-		 */
 
 		var undef;
 
@@ -262,8 +468,20 @@
 						// that these event handlers should execute in the
 						// context of the widget, so that the "this" pointer
 						// takes correctly.
-						var tn = dojo.lang.nameAnonFunc(new Function(args[x]), this);
-						dojo.event.connect(this, x, this, tn);
+						
+						// argument that contains no punctuation other than . is 
+						// considered a function spec, not code
+						if(args[x].search(/[^\w\.]+/i) == -1){
+							this[x] = dojo.evalObjPath(args[x], false);
+						}else{
+							var tn = dojo.lang.nameAnonFunc(new Function(args[x]), this);
+							dojo.event.kwConnect({
+								srcObj: this, 
+								srcFunc: x, 
+								adviceObj: this, 
+								adviceFunc: tn
+							});
+						}
 					}else if(dojo.lang.isArray(this[x])){ // typeof [] == "object"
 						this[x] = args[x].split(";");
 					} else if (this[x] instanceof Date) {
@@ -272,13 +490,21 @@
 						// FIXME: should we be allowing extension here to handle
 						// other object types intelligently?
 
-						// FIXME: unlike all other types, we do not replace the
-						// object with a new one here. Should we change that?
-						var pairs = args[x].split(";");
-						for(var y=0; y<pairs.length; y++){
-							var si = pairs[y].indexOf(":");
-							if((si != -1)&&(pairs[y].length>si)){
-								this[x][dojo.string.trim(pairs[y].substr(0, si))] = pairs[y].substr(si+1);
+						// if we defined a URI, we probably want to allow plain strings
+						// to override it
+						if (this[x] instanceof dojo.uri.Uri){
+
+							this[x] = args[x];
+						}else{
+
+							// FIXME: unlike all other types, we do not replace the
+							// object with a new one here. Should we change that?
+							var pairs = args[x].split(";");
+							for(var y=0; y<pairs.length; y++){
+								var si = pairs[y].indexOf(":");
+								if((si != -1)&&(pairs[y].length>si)){
+									this[x][pairs[y].substr(0, si).replace(/^\s+|\s+$/g, "")] = pairs[y].substr(si+1);
+								}
 							}
 						}
 					}else{
@@ -289,89 +515,109 @@
 				}
 			}else{
 				// collect any extra 'non mixed in' args
-				this.extraArgs[x] = args[x];
+				this.extraArgs[x.toLowerCase()] = args[x];
 			}
 		}
 		// dojo.profile.end("mixInProperties");
 	},
 	
-	postMixInProperties: function(){
+	postMixInProperties: function(/*Object*/args, /*Object*/frag, /*Widget*/parent){
+		// summary:
+		//		stub function. Can be over-ridden to handle advanced property
+		//		casting and object configuration.
 	},
 
-	initialize: function(args, frag){
-		// dj_unimplemented("dojo.widget.Widget.initialize");
+	initialize: function(/*Object*/args, /*Object*/frag, /*Widget*/parent){
+		// summary: stub function.
 		return false;
+		// dojo.unimplemented("dojo.widget.Widget.initialize");
 	},
 
-	postInitialize: function(args, frag){
+	postInitialize: function(/*Object*/args, /*Object*/frag, /*Widget*/parent){
+		// summary: stub function.
 		return false;
 	},
 
-	postCreate: function(args, frag){
+	postCreate: function(/*Object*/args, /*Object*/frag, /*Widget*/parent){
+		// summary: stub function.
 		return false;
 	},
 
 	uninitialize: function(){
-		// dj_unimplemented("dojo.widget.Widget.uninitialize");
+		// summary: 
+		//		stub function. Over-ride to implement custom widget tear-down
+		//		behavior.
 		return false;
 	},
 
-	buildRendering: function(){
-		// SUBCLASSES MUST IMPLEMENT
-		dj_unimplemented("dojo.widget.Widget.buildRendering, on "+this.toString()+", ");
+	buildRendering: function(/*Object*/args, /*Object*/frag, /*Widget*/parent){
+		// summary: stub function. SUBCLASSES MUST IMPLEMENT
+		dojo.unimplemented("dojo.widget.Widget.buildRendering, on "+this.toString()+", ");
 		return false;
 	},
 
 	destroyRendering: function(){
-		// SUBCLASSES MUST IMPLEMENT
-		dj_unimplemented("dojo.widget.Widget.destroyRendering");
+		// summary: stub function. SUBCLASSES MUST IMPLEMENT
+		dojo.unimplemented("dojo.widget.Widget.destroyRendering");
 		return false;
 	},
 
 	cleanUp: function(){
-		// SUBCLASSES MUST IMPLEMENT
-		dj_unimplemented("dojo.widget.Widget.cleanUp");
+		// summary: 
+		//		stub function for destruction finalization. SUBCLASSES MUST
+		//		IMPLEMENT
+		dojo.unimplemented("dojo.widget.Widget.cleanUp");
 		return false;
 	},
 
-	addedTo: function(parent){
-		// this is just a signal that can be caught
+	addedTo: function(/*Widget*/parent){
+		// summary:
+		//		stub function this is just a signal that can be caught
+		// parent: instance of dojo.widget.Widget that we were added to
 	},
 
 	addChild: function(child){
-		// SUBCLASSES MUST IMPLEMENT
-		dj_unimplemented("dojo.widget.Widget.addChild");
-		return false;
-	},
-
-	addChildAtIndex: function(child, index){
-		// SUBCLASSES MUST IMPLEMENT
-		dj_unimplemented("dojo.widget.Widget.addChildAtIndex");
+		// summary: stub function. SUBCLASSES MUST IMPLEMENT
+		dojo.unimplemented("dojo.widget.Widget.addChild");
 		return false;
 	},
 
-	removeChild: function(childRef){
-		// SUBCLASSES MUST IMPLEMENT
-		dj_unimplemented("dojo.widget.Widget.removeChild");
-		return false;
-	},
-
-	removeChildAtIndex: function(index){
-		// SUBCLASSES MUST IMPLEMENT
-		dj_unimplemented("dojo.widget.Widget.removeChildAtIndex");
-		return false;
+	// Detach the given child widget from me, but don't destroy it
+	removeChild: function(/*Widget*/widget){
+		// summary: 
+		//		removes the passed widget instance from this widget but does
+		//		not destroy it
+		for(var x=0; x<this.children.length; x++){
+			if(this.children[x] === widget){
+				this.children.splice(x, 1);
+				break;
+			}
+		}
+		return widget; // Widget
 	},
 
-	resize: function(width, height){
-		// both width and height may be set as percentages. The setWidth and
-		// setHeight  functions attempt to determine if the passed param is
-		// specified in percentage or native units. Integers without a
-		// measurement are assumed to be in the native unit of measure.
+	resize: function(/*String or int*/width, /*String or int*/height){
+		// summary:
+		// 		both width and height may be set as percentages. The setWidth
+		// 		and setHeight  functions attempt to determine if the passed
+		// 		param is specified in percentage or native units. Integers
+		// 		without a measurement are assumed to be in the native unit of
+		// 		measure.
+		// width:
+		//		the width, either in native measures, or as a percentage. If as
+		//		percentage, pass it as a string in the form "30%".
+		// height:
+		//		the height, either in native measures, or as a percentage. If as
+		//		percentage, pass it as a string in the form "30%".
 		this.setWidth(width);
 		this.setHeight(height);
 	},
 
-	setWidth: function(width){
+	setWidth: function(/*String or int*/width){
+		// summary: like it says on the tin...
+		// width:
+		//		the width, either in native measures, or as a percentage. If as
+		//		percentage, pass it as a string in the form "30%".
 		if((typeof width == "string")&&(width.substr(-1) == "%")){
 			this.setPercentageWidth(width);
 		}else{
@@ -379,7 +625,11 @@
 		}
 	},
 
-	setHeight: function(height){
+	setHeight: function(/*String or int*/height){
+		// summary: like it says on the tin...
+		// height:
+		//		the height, either in native measures, or as a percentage. If
+		//		as percentage, pass it as a string in the form "30%".
 		if((typeof height == "string")&&(height.substr(-1) == "%")){
 			this.setPercentageHeight(height);
 		}else{
@@ -387,36 +637,59 @@
 		}
 	},
 
-	setPercentageHeight: function(height){
-		// SUBCLASSES MUST IMPLEMENT
+	setPercentageHeight: function(/*int*/height){
+		// summary: stub function. SUBCLASSES MUST IMPLEMENT
 		return false;
 	},
 
-	setNativeHeight: function(height){
-		// SUBCLASSES MUST IMPLEMENT
+	setNativeHeight: function(/*int*/height){
+		// summary: stub function. SUBCLASSES MUST IMPLEMENT
 		return false;
 	},
 
-	setPercentageWidth: function(width){
-		// SUBCLASSES MUST IMPLEMENT
+	setPercentageWidth: function(/*int*/width){
+		// summary: stub function. SUBCLASSES MUST IMPLEMENT
 		return false;
 	},
 
-	setNativeWidth: function(width){
-		// SUBCLASSES MUST IMPLEMENT
+	setNativeWidth: function(/*int*/width){
+		// summary: stub function. SUBCLASSES MUST IMPLEMENT
 		return false;
 	},
 
-	getDescendants: function() {
-		var result = [];
-		var stack = [this];
-		var elem;
-		while (elem = stack.pop()) {
-			result.push(elem);
-			dojo.lang.forEach(elem.children, function(elem) { stack.push(elem); });
-		}
+	getPreviousSibling: function(){
+		// summary:
+		//		returns null if this is the first child of the parent,
+		//		otherwise returns the next sibling to the "left".
+		var idx = this.getParentIndex();
+ 
+		 // first node is idx=0 not found is idx<0
+		if (idx<=0) return null;
+ 
+		return this.parent.children[idx-1]; // Widget
+	},
+ 
+	getSiblings: function(){
+		// summary: gets an array of all children of our parent, including "this"
+		return this.parent.children; // Array
+	},
+ 
+	getParentIndex: function(){
+		// summary: what index are we at in the parent's children array?
+		return dojo.lang.indexOf(this.parent.children, this, true); // int
+	},
+ 
+	getNextSibling: function(){
+		// summary:
+		//		returns null if this is the last child of the parent,
+		//		otherwise returns the next sibling to the "right".
+ 
+		var idx = this.getParentIndex();
  
-		return result;
+		if (idx == this.parent.children.length-1){return null;} // last node
+		if (idx < 0){return null;} // not found
+ 
+		return this.parent.children[idx+1]; // Widget
 	}
 });
 
@@ -432,13 +705,22 @@
 // TODO: parse subcomponents
 // TODO: copy/clone raw markup fragments/nodes as appropriate
 dojo.widget.tags = {};
-dojo.widget.tags.addParseTreeHandler = function(type){
+dojo.widget.tags.addParseTreeHandler = function(/*String*/type){
+	// summary: deprecated!
+	dojo.deprecated("addParseTreeHandler", ". ParseTreeHandlers are now reserved for components. Any unfiltered DojoML tag without a ParseTreeHandler is assumed to be a widget", "0.5");
+	/*
 	var ltype = type.toLowerCase();
-	this[ltype] = function(fragment, widgetParser, parentComp, insertionIndex, localProps){ 
-		return dojo.widget.buildWidgetFromParseTree(ltype, fragment, widgetParser, parentComp, insertionIndex, localProps);
+	this[ltype] = function(fragment, widgetParser, parentComp, insertionIndex, localProps){
+		var _ltype = ltype;
+		dojo.profile.start(_ltype);
+		var n = dojo.widget.buildWidgetFromParseTree(ltype, fragment, widgetParser, parentComp, insertionIndex, localProps);
+		dojo.profile.end(_ltype);
+		return n;
 	}
+	*/
 }
-dojo.widget.tags.addParseTreeHandler("dojo:widget");
+
+//dojo.widget.tags.addParseTreeHandler("dojo:widget");
 
 dojo.widget.tags["dojo:propertyset"] = function(fragment, widgetParser, parentComp){
 	// FIXME: Is this needed?
@@ -452,24 +734,115 @@
 	var properties = widgetParser.parseProperties(fragment["dojo:connect"]);
 }
 
-dojo.widget.buildWidgetFromParseTree = function(type, frag, 
-												parser, parentComp, 
-												insertionIndex, localProps){
+// FIXME: if we know the insertion point (to a reasonable location), why then do we:
+//	- create a template node
+//	- clone the template node
+//	- render the clone and set properties
+//	- remove the clone from the render tree
+//	- place the clone
+// this is quite dumb
+dojo.widget.buildWidgetFromParseTree = function(/*String*/				type,
+												/*Object*/				frag, 
+												/*dojo.widget.Parse*/	parser,
+												/*Widget, optional*/	parentComp, 
+												/*int, optional*/		insertionIndex,
+												/*Object*/				localProps){
+
+	// summary: creates a tree of widgets from the data structure produced by the first-pass parser (frag)
+	
+	// test for accessibility mode 
+	dojo.a11y.setAccessibleMode();
+	//dojo.profile.start("buildWidgetFromParseTree");
+	// FIXME: for codepath from createComponentFromScript, we are now splitting a path 
+	// that we already split and then joined
 	var stype = type.split(":");
 	stype = (stype.length == 2) ? stype[1] : type;
+	
 	// FIXME: we don't seem to be doing anything with this!
 	// var propertySets = parser.getPropertySets(frag);
-	var localProperties = localProps || parser.parseProperties(frag["dojo:"+stype]);
-	// var tic = new Date();
-	var twidget = dojo.widget.manager.getImplementation(stype);
+	var localProperties = localProps || parser.parseProperties(frag[frag["ns"]+":"+stype]);
+	var twidget = dojo.widget.manager.getImplementation(stype,null,null,frag["ns"]);
 	if(!twidget){
-		throw new Error("cannot find \"" + stype + "\" widget");
+		throw new Error('cannot find "' + type + '" widget');
 	}else if (!twidget.create){
-		throw new Error("\"" + stype + "\" widget object does not appear to implement *Widget");
+		throw new Error('"' + type + '" widget object has no "create" method and does not appear to implement *Widget');
 	}
 	localProperties["dojoinsertionindex"] = insertionIndex;
-	// FIXME: we loose no less than 5ms in construction!
-	var ret = twidget.create(localProperties, frag, parentComp);
-	// dojo.debug(new Date() - tic);
+	// FIXME: we lose no less than 5ms in construction!
+	var ret = twidget.create(localProperties, frag, parentComp, frag["ns"]);
+	// dojo.profile.end("buildWidgetFromParseTree");
 	return ret;
+}
+
+dojo.widget.defineWidget = function(/*String*/			widgetClass, 
+									/*String*/			renderer,
+									/*function||array*/	superclasses, 
+									/*function*/		init,
+									/*Object*/			props){
+
+	// summary: Create a widget constructor function (aka widgetClass)
+	// widgetClass: the location in the object hierarchy to place the new widget class constructor
+	// renderer: usually "html", determines when this delcaration will be used
+	// superclasses:
+	//		can be either a single function or an array of functions to be
+	//		mixed in as superclasses. If an array, only the first will be used
+	//		to set prototype inheritance.
+	// init: an optional constructor function. Will be called after superclasses are mixed in.
+	// props: a map of properties and functions to extend the class prototype with
+
+	// This meta-function does parameter juggling for backward compat and overloading
+	// if 4th argument is a string, we are using the old syntax
+	// old sig: widgetClass, superclasses, props (object), renderer (string), init (function)
+	if(dojo.lang.isString(arguments[3])){
+		dojo.widget._defineWidget(arguments[0], arguments[3], arguments[1], arguments[4], arguments[2]);
+	}else{
+		// widgetClass
+		var args = [ arguments[0] ], p = 3;
+		if(dojo.lang.isString(arguments[1])){
+			// renderer, superclass
+			args.push(arguments[1], arguments[2]);
+		}else{
+			// superclass
+			args.push('', arguments[1]);
+			p = 2;
+		}
+		if(dojo.lang.isFunction(arguments[p])){
+			// init (function), props (object) 
+			args.push(arguments[p], arguments[p+1]);
+		}else{
+			// props (object) 
+			args.push(null, arguments[p]);
+		}
+		dojo.widget._defineWidget.apply(this, args);
+	}
+}
+
+dojo.widget.defineWidget.renderers = "html|svg|vml";
+
+dojo.widget._defineWidget = function(widgetClass /*string*/, renderer /*string*/, superclasses /*function||array*/, init /*function*/, props /*object*/){
+	// FIXME: uncomment next line to test parameter juggling ... remove when confidence improves
+	// dojo.debug('(c:)' + widgetClass + '\n\n(r:)' + renderer + '\n\n(i:)' + init + '\n\n(p:)' + props);
+	// widgetClass takes the form foo.bar.baz<.renderer>.WidgetName (e.g. foo.bar.baz.WidgetName or foo.bar.baz.html.WidgetName)
+	var module = widgetClass.split(".");
+	var type = module.pop(); // type <= WidgetName, module <= foo.bar.baz<.renderer>
+	var regx = "\\.(" + (renderer ? renderer + '|' : '') + dojo.widget.defineWidget.renderers + ")\\.";
+	var r = widgetClass.search(new RegExp(regx));
+	module = (r < 0 ? module.join(".") : widgetClass.substr(0, r));
+
+	// deprecated in favor of namespace system, remove for 0.5
+	dojo.widget.manager.registerWidgetPackage(module);
+	
+	var pos = module.indexOf(".");
+	var nsName = (pos > -1) ? module.substring(0,pos) : module;
+
+	// FIXME: hrm, this might make things simpler
+	//dojo.widget.tags.addParseTreeHandler(nsName+":"+type.toLowerCase());
+	
+	props=(props)||{};
+	props.widgetType = type;
+	if((!init)&&(props["classConstructor"])){
+		init = props.classConstructor;
+		delete props.classConstructor;
+	}
+	dojo.declare(widgetClass, superclasses, init, props);
 }

Modified: struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/Wizard.js
URL: http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/Wizard.js?view=diff&rev=474551&r1=474550&r2=474551
==============================================================================
--- struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/Wizard.js (original)
+++ struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/Wizard.js Mon Nov 13 14:54:45 2006
@@ -1,5 +1,5 @@
 /*
-	Copyright (c) 2004-2005, The Dojo Foundation
+	Copyright (c) 2004-2006, The Dojo Foundation
 	All Rights Reserved.
 
 	Licensed under the Academic Free License version 2.1 or above OR the
@@ -11,23 +11,18 @@
 dojo.provide("dojo.widget.Wizard");
 
 dojo.require("dojo.widget.*");
-dojo.require("dojo.widget.LayoutPane");
+dojo.require("dojo.widget.LayoutContainer");
+dojo.require("dojo.widget.ContentPane");
 dojo.require("dojo.event.*");
-dojo.require("dojo.html");
-dojo.require("dojo.style");
+dojo.require("dojo.html.style");
 
 //////////////////////////////////////////
-// Wizard -- a set of panels
+// WizardContainer -- a set of panels
 //////////////////////////////////////////
-dojo.widget.Wizard = function() {
-	dojo.widget.html.LayoutPane.call(this);
-}
-dojo.inherits(dojo.widget.Wizard, dojo.widget.html.LayoutPane);
-
-dojo.lang.extend(dojo.widget.Wizard, {
-
-	widgetType: "Wizard",
-
+dojo.widget.defineWidget(
+	"dojo.widget.WizardContainer",
+	dojo.widget.LayoutContainer,
+{
 	labelPosition: "top",
 
 	templatePath: dojo.uri.dojoUri("src/widget/templates/Wizard.html"),
@@ -91,7 +86,7 @@
 	},
 
 	registerChild: function(panel, insertionIndex){
-		dojo.widget.Wizard.superclass.registerChild.call(this, panel, insertionIndex);
+		dojo.widget.WizardContainer.superclass.registerChild.call(this, panel, insertionIndex);
 		this.wizardPanelContainerNode.appendChild(panel.domNode);
 		panel.hide();
 
@@ -161,19 +156,14 @@
 		this.selected.done();
 	}
 });
-dojo.widget.tags.addParseTreeHandler("dojo:Wizard");
 
 //////////////////////////////////////////
 // WizardPane -- a panel in a wizard
 //////////////////////////////////////////
-dojo.widget.WizardPane = function() {
-	dojo.widget.html.LayoutPane.call(this);
-}
-dojo.inherits(dojo.widget.WizardPane, dojo.widget.html.LayoutPane);
-
-dojo.lang.extend(dojo.widget.WizardPane, {
-	widgetType: "WizardPane",
-
+dojo.widget.defineWidget(
+	"dojo.widget.WizardPane",
+	dojo.widget.ContentPane,
+{
 	canGoBack: true,
 
 	passFunction: "",
@@ -205,5 +195,3 @@
 		}
 	}
 });
-
-dojo.widget.tags.addParseTreeHandler("dojo:WizardPane");

Added: struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/YahooMap.js
URL: http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/YahooMap.js?view=auto&rev=474551
==============================================================================
--- struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/YahooMap.js (added)
+++ struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/YahooMap.js Mon Nov 13 14:54:45 2006
@@ -0,0 +1,181 @@
+/*
+	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.widget.YahooMap");
+dojo.require("dojo.event.*");
+dojo.require("dojo.math");
+dojo.require("dojo.widget.*");
+dojo.require("dojo.widget.HtmlWidget");
+
+(function(){
+	var yappid = djConfig["yAppId"]||djConfig["yahooAppId"]||"dojotoolkit";
+	if(!dojo.hostenv.post_load_){
+		if(yappid == "dojotoolkit"){
+			dojo.debug("please provide a unique Yahoo App ID in djConfig.yahooAppId when using the map widget");
+		}
+		var tag = "<scr"+"ipt src='http://api.maps.yahoo.com/ajaxymap?v=3.0&appid="+yappid+"'></scri"+"pt>";
+		if(!dj_global["YMap"]){
+			document.write(tag);
+		}
+	}else{
+		dojo.debug("cannot initialize map system after the page has been loaded! Please either manually include the script block provided by Yahoo in your page or require() the YahooMap widget before onload has fired");
+	}
+})();
+
+dojo.widget.defineWidget(
+	"dojo.widget.YahooMap",
+	dojo.widget.HtmlWidget,
+	function(){
+		//	summary
+		//	Initialize properties of the widget.
+		this.map=null;
+		this.datasrc="";
+		this.data=[];
+		this.width=0;
+		this.height=0;
+		this.controls=["zoomlong","maptype","pan"];
+	},
+{
+	isContainer: false,
+	templatePath:null,
+	templateCssPath:null,
+
+	findCenter:function(/* array */aPts){
+		//	summary
+		//	Find the center lat/lng coordinate based on the passed points.
+		var start=new YGeoPoint(37,-90);
+		if(aPts.length==0) return start;
+		var minLat,maxLat, minLon, maxLon, cLat, cLon;
+		minLat=maxLat=aPts[0].Lat;
+		minLon=maxLon=aPts[0].Lon;
+		for(var i=0; i<aPts.length; i++){
+			minLat=Math.min(minLat,aPts[i].Lat);
+			maxLat=Math.max(maxLat,aPts[i].Lat);
+			minLon=Math.min(minLon,aPts[i].Lon);
+			maxLon=Math.max(maxLon,aPts[i].Lon);
+		}
+		cLat=dojo.math.round((minLat+maxLat)/2,6);
+		cLon=dojo.math.round((minLon+maxLon)/2,6);
+		return new YGeoPoint(cLat,cLon);	//	YGeoPoint
+	},
+	setControls:function(){
+		//	summary
+		//	Set the controls on the map
+		var methodmap={
+			maptype:"addTypeControl",
+			pan:"addPanControl",
+			zoomlong:"addZoomLong",
+			zoomshort:"addZoomShort"
+		}
+		var c=this.controls;
+		for(var i=0; i<c.length; i++){
+			var controlMethod=methodmap[c[i].toLowerCase()];
+			if(this.map[controlMethod]){
+				this.map[controlMethod]();
+			}
+		}
+	},
+	
+	parse:function(/* HTMLTable */table){
+		//	summary
+		//	Parses an HTML table for data to plot on the map.
+		this.data=[];
+
+		//	get the column indices
+		var h=table.getElementsByTagName("thead")[0];
+		if(!h){
+			return;
+		}
+
+		var a=[];
+		var cols=h.getElementsByTagName("td");
+		if(cols.length==0){
+			cols=h.getElementsByTagName("th");
+		}
+		for(var i=0; i<cols.length; i++){
+			var c=cols[i].innerHTML.toLowerCase();
+			if(c=="long") c="lng";
+			a.push(c);
+		}
+		
+		//	parse the data
+		var b=table.getElementsByTagName("tbody")[0];
+		if(!b){
+			return;
+		}
+		for(var i=0; i<b.childNodes.length; i++){
+			if(!(b.childNodes[i].nodeName&&b.childNodes[i].nodeName.toLowerCase()=="tr")){
+				continue;
+			}
+			var cells=b.childNodes[i].getElementsByTagName("td");
+			var o={};
+			for(var j=0; j<a.length; j++){
+				var col=a[j];
+				if(col=="lat"||col=="lng"){
+					o[col]=parseFloat(cells[j].innerHTML);					
+				}else{
+					o[col]=cells[j].innerHTML;
+				}
+			}
+			this.data.push(o);
+		}
+	},
+	render:function(){
+		//	summary
+		//	Plots all points in internal data array on the map.
+		var pts=[];
+		var d=this.data;
+		for(var i=0; i<d.length; i++){
+			var pt=new YGeoPoint(d[i].lat, d[i].lng);
+			pts.push(pt);
+			var icon=d[i].icon||null;
+			if(icon){
+				icon=new YImage(icon);
+			}
+			var m=new YMarker(pt,icon);
+			if(d[i].description){
+				m.addAutoExpand("<div>"+d[i].description+"</div>");
+			}
+			this.map.addOverlay(m);
+		}
+		var c=this.findCenter(pts);
+		var z=this.map.getZoomLevel(pts);
+		this.map.drawZoomAndCenter(c,z);
+	},
+	
+	initialize:function(/* object */args, /* object */frag){
+		//	summary
+		//	Initialize the widget.
+		if(!YMap || !YGeoPoint){
+			dojo.raise("dojo.widget.YahooMap: The Yahoo Map script must be included in order to use this widget.");
+		}
+		if(this.datasrc){
+			this.parse(dojo.byId(this.datasrc));
+		}
+		else if(this.domNode.getElementsByTagName("table")[0]){
+			this.parse(this.domNode.getElementsByTagName("table")[0]);
+		}
+	},
+	postCreate:function(){
+		//	summary
+		//	Finalize and plot all points on the widget.
+		while(this.domNode.childNodes.length>0){
+			this.domNode.removeChild(this.domNode.childNodes[0]);
+		}
+
+		if(this.width>0&&this.height>0){
+			this.map=new YMap(this.domNode, YAHOO_MAP_REG, new YSize(this.width, this.height));
+		}else{
+			this.map=new YMap(this.domNode);
+		}
+		this.setControls();
+		this.render();
+	}
+});

Propchange: struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/YahooMap.js
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/__package__.js
URL: http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/__package__.js?view=diff&rev=474551&r1=474550&r2=474551
==============================================================================
--- struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/__package__.js (original)
+++ struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/__package__.js Mon Nov 13 14:54:45 2006
@@ -1,5 +1,5 @@
 /*
-	Copyright (c) 2004-2005, The Dojo Foundation
+	Copyright (c) 2004-2006, The Dojo Foundation
 	All Rights Reserved.
 
 	Licensed under the Academic Free License version 2.1 or above OR the
@@ -8,13 +8,16 @@
 		http://dojotoolkit.org/community/licensing.shtml
 */
 
-dojo.hostenv.conditionalLoadModule({
+dojo.kwCompoundRequire({
 	common: ["dojo.xml.Parse", 
 			 "dojo.widget.Widget", 
 			 "dojo.widget.Parse", 
 			 "dojo.widget.Manager"],
 	browser: ["dojo.widget.DomWidget",
 			  "dojo.widget.HtmlWidget"],
-	svg: 	 ["dojo.widget.SvgWidget"]
+	dashboard: ["dojo.widget.DomWidget",
+			  "dojo.widget.HtmlWidget"],
+	svg: 	 ["dojo.widget.SvgWidget"],
+	rhino: 	 ["dojo.widget.SwtWidget"]
 });
-dojo.hostenv.moduleLoaded("dojo.widget.*");
+dojo.provide("dojo.widget.*");

Added: struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/demoEngine/DemoContainer.js
URL: http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/demoEngine/DemoContainer.js?view=auto&rev=474551
==============================================================================
--- struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/demoEngine/DemoContainer.js (added)
+++ struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/demoEngine/DemoContainer.js Mon Nov 13 14:54:45 2006
@@ -0,0 +1,107 @@
+/*
+	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.widget.demoEngine.DemoContainer");
+dojo.require("dojo.widget.*");
+dojo.require("dojo.widget.HtmlWidget");
+dojo.require("dojo.widget.demoEngine.DemoPane");
+dojo.require("dojo.widget.demoEngine.SourcePane");
+dojo.require("dojo.widget.TabContainer");
+
+dojo.widget.defineWidget("my.widget.demoEngine.DemoContainer", 
+	dojo.widget.HtmlWidget, 
+	{
+		templatePath: dojo.uri.dojoUri("src/widget/demoEngine/templates/DemoContainer.html"),
+		templateCssPath: dojo.uri.dojoUri("src/widget/demoEngine/templates/DemoContainer.css"),
+		postCreate: function() {
+			dojo.html.addClass(this.domNode,this.domNodeClass);
+			dojo.html.addClass(this.tabNode, this.tabClass);
+			dojo.html.addClass(this.returnImageNode, this.returnClass);
+			this.returnImageNode.src=this.returnImage;
+
+			this.tabContainer = dojo.widget.createWidget("TabContainer",{},this.tabNode);
+
+			this.demoTab = dojo.widget.createWidget("DemoPane",{});
+			this.tabContainer.addChild(this.demoTab);
+
+			this.sourceTab= dojo.widget.createWidget("SourcePane",{});
+			this.tabContainer.addChild(this.sourceTab);
+
+			dojo.html.setOpacity(this.domNode,0);
+			dojo.html.hide(this.domNode);
+		},
+
+		loadDemo: function(url) {
+			this.demoTab.setHref(url);
+			this.sourceTab.setHref(url);
+			this.showDemo();
+		},
+
+		setName: function(name) {
+			dojo.html.removeChildren(this.demoNameNode);
+			this.demoNameNode.appendChild(document.createTextNode(name));
+		},
+
+		setSummary: function(summary) {
+			dojo.html.removeChildren(this.summaryNode);
+			this.summaryNode.appendChild(document.createTextNode(summary));
+		},
+
+		showSource: function() {
+			dojo.html.removeClass(this.demoButtonNode,this.selectedButtonClass);
+			dojo.html.addClass(this.sourceButtonNode,this.selectedButtonClass);
+			this.tabContainer.selectTab(this.sourceTab);	
+		},
+
+		showDemo: function() {
+			dojo.html.removeClass(this.sourceButtonNode,this.selectedButtonClass);
+			dojo.html.addClass(this.demoButtonNode,this.selectedButtonClass);
+			this.tabContainer.selectTab(this.demoTab);
+		},
+
+		returnToDemos: function() {
+			dojo.debug("Return To Demos");
+		},
+
+		show: function() {
+			dojo.html.setOpacity(this.domNode,1);
+			dojo.html.show(this.domNode);
+			this.tabContainer.checkSize();
+		}
+	},
+	"",
+	function() {
+		dojo.debug("DemoPane Init");
+		this.domNodeClass="demoContainer";
+
+		this.tabContainer="";
+		this.sourceTab="";
+		this.demoTab="";
+
+		this.headerNode="";
+		this.returnNode="";
+	
+		this.returnImageNode="";
+		this.returnImage="images/dojoDemos.gif";
+		this.returnClass="return";
+		
+		this.summaryNode="";
+		this.demoNameNode="";
+		this.tabControlNode="";
+
+		this.tabNode="";
+		this.tabClass = "demoContainerTabs";
+
+		this.sourceButtonNode="";
+		this.demoButtonNode="";
+
+		this.selectedButtonClass="selected";
+	}
+);

Propchange: struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/demoEngine/DemoContainer.js
------------------------------------------------------------------------------
    svn:eol-style = native

Added: struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/demoEngine/DemoItem.js
URL: http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/demoEngine/DemoItem.js?view=auto&rev=474551
==============================================================================
--- struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/demoEngine/DemoItem.js (added)
+++ struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/demoEngine/DemoItem.js Mon Nov 13 14:54:45 2006
@@ -0,0 +1,71 @@
+/*
+	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.widget.demoEngine.DemoItem");
+dojo.require("dojo.widget.*");
+dojo.require("dojo.widget.HtmlWidget");
+
+dojo.widget.defineWidget("my.widget.demoEngine.DemoItem", 
+	dojo.widget.HtmlWidget, 
+	{
+		templatePath: dojo.uri.dojoUri("src/widget/demoEngine/templates/DemoItem.html"),
+		templateCssPath: dojo.uri.dojoUri("src/widget/demoEngine/templates/DemoItem.css"),
+		postCreate: function() {
+			dojo.html.addClass(this.domNode,this.domNodeClass);
+			dojo.html.addClass(this.summaryBoxNode, this.summaryBoxClass);
+			dojo.html.addClass(this.screenshotTdNode, this.screenshotTdClass);
+			dojo.html.addClass(this.summaryContainerNode, this.summaryContainerClass);
+			dojo.html.addClass(this.summaryNode, this.summaryClass);
+			dojo.html.addClass(this.viewDemoLinkNode, this.viewDemoLinkClass);
+
+			this.nameNode.appendChild(document.createTextNode(this.name));
+			this.descriptionNode.appendChild(document.createTextNode(this.description));
+			this.thumbnailImageNode.src = this.thumbnail;
+			this.thumbnailImageNode.name=this.name;
+			this.viewDemoImageNode.src = this.viewDemoImage;
+			this.viewDemoImageNode.name=this.name;
+		},
+		onSelectDemo: function() {
+			//Attach to this to do something when a demo is selected
+		}
+	},
+	"",
+	function() {
+		this.demo = "";
+
+		this.domNodeClass="demoItemWrapper";
+
+		this.summaryBoxNode="";
+		this.summaryBoxClass="demoItemSummaryBox";
+
+		this.nameNode="";
+		this.thumbnailImageNode="";
+		this.viewDemoImageNode="";
+
+		this.screenshotTdNode="";
+		this.screenshotTdClass="demoItemScreenshot";
+
+		this.summaryContainerNode="";
+		this.summaryContainerClass="demoItemSummaryContainer";
+
+		this.summaryNode="";
+		this.summaryClass="demoItemSummary";
+
+		this.viewDemoLinkNode="";
+		this.viewDemoLinkClass="demoItemView";
+
+		this.descriptionNode="";
+
+		this.name="Some Demo";
+		this.description="This is the description of this demo.";
+		this.thumbnail="images/test_thumb.gif";
+		this.viewDemoImage="images/viewDemo.png";
+	}
+);

Propchange: struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/demoEngine/DemoItem.js
------------------------------------------------------------------------------
    svn:eol-style = native

Added: struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/demoEngine/DemoNavigator.js
URL: http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/demoEngine/DemoNavigator.js?view=auto&rev=474551
==============================================================================
--- struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/demoEngine/DemoNavigator.js (added)
+++ struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/demoEngine/DemoNavigator.js Mon Nov 13 14:54:45 2006
@@ -0,0 +1,188 @@
+/*
+	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.widget.demoEngine.DemoNavigator");
+dojo.require("dojo.widget.*");
+dojo.require("dojo.widget.HtmlWidget");
+dojo.require("dojo.widget.Button");
+dojo.require("dojo.widget.demoEngine.DemoItem");
+dojo.require("dojo.io.*");
+dojo.require("dojo.lfx.*");
+dojo.require("dojo.lang.common");
+
+dojo.widget.defineWidget("my.widget.demoEngine.DemoNavigator", 
+	dojo.widget.HtmlWidget, 
+	{
+		templatePath: dojo.uri.dojoUri("src/widget/demoEngine/templates/DemoNavigator.html"),
+		templateCssPath: dojo.uri.dojoUri("src/widget/demoEngine/templates/DemoNavigator.css"),
+		postCreate: function() {
+			dojo.html.addClass(this.domNode,this.domNodeClass);
+			dojo.html.addClass(this.demoListWrapperNode,this.demoListWrapperClass);
+			dojo.html.addClass(this.demoListContainerNode,this.demoListContainerClass);
+
+			if (dojo.render.html.ie) {
+				dojo.debug("render ie");
+				dojo.html.hide(this.demoListWrapperNode); 
+			} else {
+				dojo.debug("render non-ie");
+				dojo.lfx.html.fadeHide(this.demoListWrapperNode, 0).play();	
+			}
+
+			this.getRegistry(this.demoRegistryUrl);
+
+			this.demoContainer = dojo.widget.createWidget("DemoContainer",{returnImage: this.returnImage},this.demoNode);
+			dojo.event.connect(this.demoContainer,"returnToDemos", this, "returnToDemos");
+			this.demoContainer.hide();
+		},
+
+		returnToDemos: function() {
+			this.demoContainer.hide();
+			if (dojo.render.html.ie) {
+				dojo.debug("render ie");
+				dojo.html.show(this.navigationContainer) ;
+			} else {	
+				dojo.debug("render non-ie");
+				dojo.lfx.html.fadeShow(this.navigationContainer,250).play();
+			}
+
+			//if (dojo.render.html.ie) {
+			//	dojo.html.setOpacity(this.navigationContainer);
+			//}
+
+			dojo.lang.forEach(this.categoriesChildren, dojo.lang.hitch(this, function(child){
+				child.checkSize();
+			}));
+
+			dojo.lang.forEach(this.demoListChildren, dojo.lang.hitch(this, function(child){
+				child.checkSize();
+			}));
+		},
+
+		show: function() {
+			//dojo.widget.demoEngine.DemoNavigator.superclass.show.call(this);
+			dojo.html.show(this.domNode);
+			dojo.html.setOpacity(this.domNode,1);
+			//dojo.html.setOpacity(this.navigationContainer);	
+			//dojo.html.show(this.navigationContainer);
+			dojo.html.setOpacity(this.navigationContainer,1);
+
+			dojo.lang.forEach(this.categoriesChildren, dojo.lang.hitch(this, function(child){
+				child.checkSize();
+			}));
+
+			dojo.lang.forEach(this.demoListChildren, dojo.lang.hitch(this, function(child){
+				child.checkSize();
+			}));
+		},
+		getRegistry: function(url) {
+			dojo.io.bind({
+				url: url,
+				load: dojo.lang.hitch(this,this.processRegistry),
+				mimetype: "text/json"
+			});
+		},
+
+		processRegistry: function(type,registry,e) {
+			dojo.debug("Processing Registry");
+			this.registry = registry;
+			dojo.lang.forEach(this.registry.navigation, dojo.lang.hitch(this,this.addCategory)); 
+		},
+
+		addCategory: function(category) {
+				var newCat = dojo.widget.createWidget("Button",{caption: category.name});
+
+				if(!dojo.lang.isObject(this.registry.categories)) {
+					this.registry.categories=function(){};
+				}
+
+				this.registry.categories[category.name] = category;
+				this.categoriesChildren.push(newCat);
+				this.categoriesButtonsNode.appendChild(newCat.domNode);	
+				newCat.domNode.categoryName = category.name;
+				dojo.event.connect(newCat,"onClick", this, "onSelectCategory");
+		},
+
+		addDemo: function(demoName) {
+			var demo = this.registry.definitions[demoName];
+
+			if (dojo.render.html.ie) {
+				dojo.html.show(this.demoListWrapperNode) 
+			} else {
+				dojo.lfx.html.fadeShow(this.demoListWrapperNode, 250).play();
+			}
+
+			var newDemo = dojo.widget.createWidget("DemoItem",{viewDemoImage: this.viewDemoImage, name: demoName, description: demo.description, thumbnail: demo.thumbnail});
+			this.demoListChildren.push(newDemo);
+			this.demoListContainerNode.appendChild(newDemo.domNode);	
+			dojo.event.connect(newDemo,"onSelectDemo",this,"onSelectDemo");
+		},
+
+		onSelectCategory: function(e) {
+			catName = e.currentTarget.categoryName;	
+			dojo.debug("Selected Category: " + catName);
+			//Remove current list of demos
+			dojo.lang.forEach(this.demoListChildren, function(child) {
+					child.destroy();
+			});
+			this.demoListChildren=[];
+
+			//add demos from this cat
+			dojo.lang.forEach(this.registry.categories[catName].demos, dojo.lang.hitch(this,function(demoName){
+				this.addDemo(demoName);
+			}));
+		},
+
+		onSelectDemo: function(e) {
+			//Attach to this to do something when a demo is selected
+			dojo.debug("Demo Selected: " + e.target.name);
+
+			if (dojo.render.html.ie) {
+				dojo.debug("render ie");
+				dojo.html.hide(this.navigationContainer) ;
+				this.demoContainer.show();
+				this.demoContainer.showDemo();
+			} else {
+				dojo.debug("render non-ie");
+				dojo.lfx.html.fadeHide(this.navigationContainer,250,null,dojo.lang.hitch(this, function() {
+					this.demoContainer.show();	
+					this.demoContainer.showDemo();
+				})).play();
+			}
+
+			this.demoContainer.loadDemo(this.registry.definitions[e.target.name].url);
+			this.demoContainer.setName(e.target.name);
+			this.demoContainer.setSummary(this.registry.definitions[e.target.name].description);
+		}
+		
+	},
+	"",
+	function() {
+		this.demoRegistryUrl="demoRegistry.json";
+		this.registry=function(){};
+
+		this.categoriesNode="";
+		this.categoriesButtonsNode="";
+		this.navigationContainer="";
+
+		this.domNodeClass="demoNavigator";
+
+		this.demoNode="";
+		this.demoContainer="";
+
+		this.demoListWrapperNode="";
+		this.demoListWrapperClass="demoNavigatorListWrapper";
+		this.demoListContainerClass="demoNavigatorListContainer";
+
+		this.returnImage="images/dojoDemos.gif";
+		this.viewDemoImage="images/viewDemo.png";
+		this.demoListChildren = [];
+		this.categoriesChildren = [];
+	}
+);

Propchange: struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/demoEngine/DemoNavigator.js
------------------------------------------------------------------------------
    svn:eol-style = native

Added: struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/demoEngine/DemoPane.js
URL: http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/demoEngine/DemoPane.js?view=auto&rev=474551
==============================================================================
--- struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/demoEngine/DemoPane.js (added)
+++ struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/demoEngine/DemoPane.js Mon Nov 13 14:54:45 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.widget.demoEngine.DemoPane");
+dojo.require("dojo.widget.*");
+dojo.require("dojo.widget.HtmlWidget");
+
+dojo.widget.defineWidget("my.widget.demoEngine.DemoPane", 
+	dojo.widget.HtmlWidget, 
+	{
+		templatePath: dojo.uri.dojoUri("src/widget/demoEngine/templates/DemoPane.html"),
+		templateCssPath: dojo.uri.dojoUri("src/widget/demoEngine/templates/DemoPane.css"),
+		postCreate: function() {
+			dojo.html.addClass(this.domNode,this.domNodeClass);
+			dojo.debug("PostCreate");
+			this._launchDemo();
+		},
+		
+		_launchDemo: function() {
+			dojo.debug("Launching Demo");
+			dojo.debug(this.demoNode);
+			this.demoNode.src=this.href;
+		},
+
+		setHref: function(url) {
+			this.href = url;
+			this._launchDemo();
+		}
+	},
+	"",
+	function() {
+		dojo.debug("DemoPane Init");
+		this.domNodeClass="demoPane";
+		this.demoNode = "";
+		this.href = "";
+	}
+);

Propchange: struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/demoEngine/DemoPane.js
------------------------------------------------------------------------------
    svn:eol-style = native

Added: struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/demoEngine/SourcePane.js
URL: http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/demoEngine/SourcePane.js?view=auto&rev=474551
==============================================================================
--- struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/demoEngine/SourcePane.js (added)
+++ struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/demoEngine/SourcePane.js Mon Nov 13 14:54:45 2006
@@ -0,0 +1,52 @@
+/*
+	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.widget.demoEngine.SourcePane");
+dojo.require("dojo.widget.*");
+dojo.require("dojo.widget.HtmlWidget");
+dojo.require("dojo.io.*");
+
+dojo.widget.defineWidget("my.widget.demoEngine.SourcePane", 
+	dojo.widget.HtmlWidget, 
+	{
+		templatePath: dojo.uri.dojoUri("src/widget/demoEngine/templates/SourcePane.html"),
+		templateCssPath: dojo.uri.dojoUri("src/widget/demoEngine/templates/SourcePane.css"),
+		postCreate: function() {
+			dojo.html.addClass(this.domNode,this.domNodeClass);
+			dojo.debug("PostCreate");
+		},
+	
+		getSource: function() {
+			if (this.href) {
+				dojo.io.bind({
+					url: this.href,
+					load: dojo.lang.hitch(this, "fillInSource"),
+					mimetype: "text/plain"
+				});
+			}
+		},	
+
+		fillInSource: function(type, source, e) {
+			this.sourceNode.value=source;
+		},
+
+		setHref: function(url) {
+			this.href = url;
+			this.getSource();
+		}
+	},
+	"",
+	function() {
+		dojo.debug("SourcePane Init");
+		this.domNodeClass="sourcePane";
+		this.sourceNode = "";
+		this.href = "";
+	}
+);

Propchange: struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/demoEngine/SourcePane.js
------------------------------------------------------------------------------
    svn:eol-style = native

Added: struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/demoEngine/__package__.js
URL: http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/demoEngine/__package__.js?view=auto&rev=474551
==============================================================================
--- struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/demoEngine/__package__.js (added)
+++ struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/demoEngine/__package__.js Mon Nov 13 14:54:45 2006
@@ -0,0 +1,20 @@
+/*
+	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({
+	browser: [
+		"dojo.widget.demoEngine.DemoItem",
+		"dojo.widget.demoEngine.DemoNavigator",
+		"dojo.widget.demoEngine.DemoPane",
+		"dojo.widget.demoEngine.SourcePane",
+		"dojo.widget.demoEngine.DemoContainer"
+	]
+});
+dojo.provide("dojo.widget.demoEngine.*");

Propchange: struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/demoEngine/__package__.js
------------------------------------------------------------------------------
    svn:eol-style = native

Added: struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/demoEngine/templates/DemoContainer.css
URL: http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/demoEngine/templates/DemoContainer.css?view=auto&rev=474551
==============================================================================
--- struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/demoEngine/templates/DemoContainer.css (added)
+++ struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/demoEngine/templates/DemoContainer.css Mon Nov 13 14:54:45 2006
@@ -0,0 +1,39 @@
+.demoContainer{
+	width: 100%;
+	height: 100%;
+	padding: 0px;
+	margin: 0px;
+}
+
+.demoContainer .return {
+	cursor: pointer;
+}
+
+.demoContainer span {
+	margin-right: 10px;
+	cursor: pointer;
+}
+
+.demoContainer .selected {
+	border-bottom: 5px solid #95bfff;
+}
+
+.demoContainer table {
+	background: #f5f5f5;
+	width: 100%;
+	height: 100%;
+}
+
+.demoContainerTabs {
+	width: 100%;
+	height: 400px;
+}
+
+.demoContainerTabs .dojoTabLabels-top {
+	display: none;
+}
+
+.demoContainerTabs .dojoTabPaneWrapper {
+	border: 0px;
+}
+

Propchange: struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/demoEngine/templates/DemoContainer.css
------------------------------------------------------------------------------
    svn:eol-style = native

Added: struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/demoEngine/templates/DemoContainer.html
URL: http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/demoEngine/templates/DemoContainer.html?view=auto&rev=474551
==============================================================================
--- struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/demoEngine/templates/DemoContainer.html (added)
+++ struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/demoEngine/templates/DemoContainer.html Mon Nov 13 14:54:45 2006
@@ -0,0 +1,25 @@
+<div dojoAttachPoint="domNode">
+	<table width="100%" cellspacing="0" cellpadding="5">
+		<tbody>
+			<tr dojoAttachPoint="headerNode">
+				<td dojoAttachPoint="returnNode" valign="middle" width="1%">
+					<img dojoAttachPoint="returnImageNode" dojoAttachEvent="onclick: returnToDemos"/>
+				</td>
+				<td>
+					<h1 dojoAttachPoint="demoNameNode"></h1>
+					<p dojoAttachPoint="summaryNode"></p>
+				</td>
+				<td dojoAttachPoint="tabControlNode" valign="middle" align="right" nowrap>
+					<span dojoAttachPoint="sourceButtonNode" dojoAttachEvent="onclick: showSource">source</span>
+					<span dojoAttachPoint="demoButtonNode" dojoAttachEvent="onclick: showDemo">demo</span>
+				</td>
+			</tr>
+			<tr>
+				<td colspan="3">
+					<div dojoAttachPoint="tabNode">
+					</div>
+				</td>
+			</tr>
+		</tbody>
+	</table>
+</div>

Propchange: struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/demoEngine/templates/DemoContainer.html
------------------------------------------------------------------------------
    svn:eol-style = native

Added: struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/demoEngine/templates/DemoItem.css
URL: http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/demoEngine/templates/DemoItem.css?view=auto&rev=474551
==============================================================================
--- struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/demoEngine/templates/DemoItem.css (added)
+++ struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/demoEngine/templates/DemoItem.css Mon Nov 13 14:54:45 2006
@@ -0,0 +1,58 @@
+.demoItemSummaryBox {
+	background: #efefef;
+	border:1px solid #dae3ee;
+}
+
+.demoItemScreenshot {
+	padding:0.65em;
+	width:175px;
+	border-right:1px solid #fafafa;
+	text-align:center;
+	cursor: pointer;
+}
+
+.demoItemWrapper{
+	margin-bottom:1em;
+}
+
+.demoItemWrapper a:link, .demoItemWrapper a:visited {
+	color:#a6238f;
+	text-decoration:none;
+}
+
+.demoItemSummaryContainer {
+	border-left:1px solid #ddd;
+}
+
+.demoItemSummaryContainer h1 {
+	background-color:#e8e8e8;
+	border-bottom: 1px solid #e6e6e6;
+	color:#738fb9;
+	margin:1px;
+	padding:0.5em;
+	font-family:"Lucida Grande", "Tahoma", serif;
+	font-size:1.25em;
+	font-weight:normal;
+}
+
+.demoItemSummaryContainer h1 .packageSummary {
+	display:block;
+	color:#000;
+	font-size:10px;
+	margin-top:2px;
+}
+
+.demoItemSummaryContainer .demoItemSummary{
+	padding:1em;
+}
+
+.demoItemSummaryContainer .demoItemSummary p {
+	font-size:0.85em;
+	padding:0;
+	margin:0;
+}
+
+.demoItemView {
+	text-align:right;
+	cursor: pointer;
+}

Propchange: struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/demoEngine/templates/DemoItem.css
------------------------------------------------------------------------------
    svn:eol-style = native