You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tapestry.apache.org by jk...@apache.org on 2006/09/23 01:22:51 UTC

svn commit: r449122 [34/40] - in /tapestry/tapestry4/trunk/tapestry-framework/src: java/org/apache/tapestry/ java/org/apache/tapestry/dojo/ java/org/apache/tapestry/dojo/form/ java/org/apache/tapestry/dojo/html/ java/org/apache/tapestry/form/ java/org/...

Added: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/Widget.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/Widget.js?view=auto&rev=449122
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/Widget.js (added)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/Widget.js Fri Sep 22 16:22:30 2006
@@ -0,0 +1,845 @@
+/*
+	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.Widget");
+dojo.provide("dojo.widget.tags");
+
+dojo.require("dojo.lang.func");
+dojo.require("dojo.lang.array");
+dojo.require("dojo.lang.extras");
+dojo.require("dojo.lang.declare");
+dojo.require("dojo.namespace");
+dojo.require("dojo.widget.Manager");
+dojo.require("dojo.event.*");
+dojo.require("dojo.a11y");
+
+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
+
+	// 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
+
+	// 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,
+
+	// 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: "",
+
+	// String: used for building generic widgets
+	widgetType: "Widget",
+
+	// String: defaults to 'dojo'.  "namespace" is a reserved word in JavaScript
+	"namespace": "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.namespace ? this.namespace + ":" + this.widgetType : this.widgetType).toLowerCase(); // String
+		return (this["namespace"] ? this["namespace"] + ":" + 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(){
+		// summary: returns the string representation of the widget.
+		return this.toString(); // String
+	},
+
+	enable: function(){
+		// summary:
+		//		enables the widget, usually involving unmasking inputs and
+		//		turning on event handlers. Not implemented here.
+		this.isEnabled = true;
+	},
+
+	disable: function(){
+		// summary:
+		//		disables the widget, usually involves masking inputs and
+		//		unsetting event handlers. Not implemented here.
+		this.isEnabled = false;
+	},
+
+	hide: function(){
+		// summary: hides the widget from view. Not implemented here.
+		this.isHidden = true;
+	},
+
+	show: function(){
+		// summary: re-adds the widget to the view. Not implemented here.
+		this.isHidden = false;
+	},
+
+	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["namespace"] = ns;
+		}
+		// dojo.debug(this.widgetType, "create");
+		//dojo.profile.start(this.widgetType + " satisfyPropertySets");
+		this.satisfyPropertySets(args, fragment, parent);
+		//dojo.profile.end(this.widgetType + " satisfyPropertySets");
+		// dojo.debug(this.widgetType, "-> mixInProperties");
+		//dojo.profile.start(this.widgetType + " mixInProperties");
+		this.mixInProperties(args, fragment, parent);
+		//dojo.profile.end(this.widgetType + " mixInProperties");
+		// dojo.debug(this.widgetType, "-> postMixInProperties");
+		//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");
+		//dojo.profile.start(this.widgetType + " buildRendering");
+		this.buildRendering(args, fragment, parent);
+		//dojo.profile.end(this.widgetType + " buildRendering");
+		// dojo.debug(this.widgetType, "-> initialize");
+		//dojo.profile.start(this.widgetType + " initialize");
+		this.initialize(args, fragment, parent);
+		//dojo.profile.end(this.widgetType + " initialize");
+		// dojo.debug(this.widgetType, "-> postInitialize");
+		// postinitialize includes subcomponent creation
+		// profile is put directly to function
+		this.postInitialize(args, fragment, parent);
+		// dojo.debug(this.widgetType, "-> postCreate");
+		//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(/*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(){
+		// 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
+		}
+				
+	},
+
+	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 = [];
+		var isFunc = dojo.lang.isFunction(type);
+		if(!isFunc){
+			type = type.toLowerCase();
+		}
+		for(var x=0; x<this.children.length; 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; // Array
+	},
+
+	getDescendants: function(){
+		// summary: returns a flattened array of all direct descendants including self
+		var result = [];
+		var stack = [this];
+		var elem;
+		while ((elem = stack.pop())){
+			result.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; // 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
+		/*
+		var typePropSets = []; // FIXME: need to pull these from somewhere!
+		var localPropSets = []; // pull out propsets from the parser's return structure
+
+		// for(var x=0; x<args.length; x++){
+		// }
+
+		for(var x=0; x<typePropSets.length; x++){
+		}
+
+		for(var x=0; x<localPropSets.length; x++){
+		}
+		*/
+		// dojo.profile.end("satisfyPropertySets");
+		
+		return args;
+	},
+
+	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...
+			// dojo.lang.mixin(this, args);
+			for(var x in args){
+				this[x] = args[x];
+			}
+			// dojo.profile.end("mixInProperties_fastMixIn");
+			return;
+		}
+		// dojo.profile.start("mixInProperties");
+
+		var undef;
+
+		// NOTE: we cannot assume that the passed properties are case-correct
+		// (esp due to some browser bugs). Therefore, we attempt to locate
+		// properties for assignment regardless of case. This may cause
+		// problematic assignments and bugs in the future and will need to be
+		// documented with big bright neon lights.
+
+		// FIXME: fails miserably if a mixin property has a default value of null in 
+		// a widget
+
+		// NOTE: caching lower-cased args in the prototype is only 
+		// acceptable if the properties are invariant.
+		// if we have a name-cache, get it
+		var lcArgs = dojo.widget.lcArgsCache[this.widgetType];
+		if ( lcArgs == null ){
+			// build a lower-case property name cache if we don't have one
+			lcArgs = {};
+			for(var y in this){
+				lcArgs[((new String(y)).toLowerCase())] = y;
+			}
+			dojo.widget.lcArgsCache[this.widgetType] = lcArgs;
+		}
+		var visited = {};
+		for(var x in args){
+			if(!this[x]){ // check the cache for properties
+				var y = lcArgs[(new String(x)).toLowerCase()];
+				if(y){
+					args[y] = args[x];
+					x = y; 
+				}
+			}
+			if(visited[x]){ continue; }
+			visited[x] = true;
+			if((typeof this[x]) != (typeof undef)){
+				if(typeof args[x] != "string"){
+					this[x] = args[x];
+				}else{
+					if(dojo.lang.isString(this[x])){
+						this[x] = args[x];
+					}else if(dojo.lang.isNumber(this[x])){
+						this[x] = new Number(args[x]); // FIXME: what if NaN is the result?
+					}else if(dojo.lang.isBoolean(this[x])){
+						this[x] = (args[x].toLowerCase()=="false") ? false : true;
+					}else if(dojo.lang.isFunction(this[x])){
+
+						// FIXME: need to determine if always over-writing instead
+						// of attaching here is appropriate. I suspect that we
+						// might want to only allow attaching w/ action items.
+						
+						// RAR, 1/19/05: I'm going to attach instead of
+						// over-write here. Perhaps function objects could have
+						// some sort of flag set on them? Or mixed-into objects
+						// could have some list of non-mutable properties
+						// (although I'm not sure how that would alleviate this
+						// particular problem)? 
+
+						// this[x] = new Function(args[x]);
+
+						// after an IRC discussion last week, it was decided
+						// that these event handlers should execute in the
+						// context of the widget, so that the "this" pointer
+						// takes correctly.
+						
+						// 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.connect(this, x, this, tn);
+						}
+					}else if(dojo.lang.isArray(this[x])){ // typeof [] == "object"
+						this[x] = args[x].split(";");
+					} else if (this[x] instanceof Date) {
+						this[x] = new Date(Number(args[x])); // assume timestamp
+					}else if(typeof this[x] == "object"){ 
+						// FIXME: should we be allowing extension here to handle
+						// other object types intelligently?
+
+						// 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{
+						// the default is straight-up string assignment. When would
+						// we ever hit this?
+						this[x] = args[x];
+					}
+				}
+			}else{
+				// collect any extra 'non mixed in' args
+				this.extraArgs[x.toLowerCase()] = args[x];
+			}
+		}
+		// dojo.profile.end("mixInProperties");
+	},
+	
+	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(/*Object*/args, /*Object*/frag, /*Widget*/parent){
+		// summary: stub function.
+		return false;
+		// dojo.unimplemented("dojo.widget.Widget.initialize");
+	},
+
+	postInitialize: function(/*Object*/args, /*Object*/frag, /*Widget*/parent){
+		// summary: stub function.
+		return false;
+	},
+
+	postCreate: function(/*Object*/args, /*Object*/frag, /*Widget*/parent){
+		// summary: stub function.
+		return false;
+	},
+
+	uninitialize: function(){
+		// summary: 
+		//		stub function. Over-ride to implement custom widget tear-down
+		//		behavior.
+		return false;
+	},
+
+	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(){
+		// summary: stub function. SUBCLASSES MUST IMPLEMENT
+		dojo.unimplemented("dojo.widget.Widget.destroyRendering");
+		return false;
+	},
+
+	cleanUp: function(){
+		// summary: 
+		//		stub function for destruction finalization. SUBCLASSES MUST
+		//		IMPLEMENT
+		dojo.unimplemented("dojo.widget.Widget.cleanUp");
+		return false;
+	},
+
+	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){
+		// summary: stub function. SUBCLASSES MUST IMPLEMENT
+		dojo.unimplemented("dojo.widget.Widget.addChild");
+		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(/*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(/*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{
+			this.setNativeWidth(width);
+		}
+	},
+
+	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{
+			this.setNativeHeight(height);
+		}
+	},
+
+	setPercentageHeight: function(/*int*/height){
+		// summary: stub function. SUBCLASSES MUST IMPLEMENT
+		return false;
+	},
+
+	setNativeHeight: function(/*int*/height){
+		// summary: stub function. SUBCLASSES MUST IMPLEMENT
+		return false;
+	},
+
+	setPercentageWidth: function(/*int*/width){
+		// summary: stub function. SUBCLASSES MUST IMPLEMENT
+		return false;
+	},
+
+	setNativeWidth: function(/*int*/width){
+		// summary: stub function. SUBCLASSES MUST IMPLEMENT
+		return false;
+	},
+
+	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();
+ 
+		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
+	}
+});
+
+// Lower case name cache: listing of the lower case elements in each widget.
+// We can't store the lcArgs in the widget itself because if B subclasses A,
+// then B.prototype.lcArgs might return A.prototype.lcArgs, which is not what we
+// want
+dojo.widget.lcArgsCache = {};
+
+// TODO: should have a more general way to add tags or tag libraries?
+// TODO: need a default tags class to inherit from for things like getting propertySets
+// TODO: parse properties/propertySets into component attributes
+// TODO: parse subcomponents
+// TODO: copy/clone raw markup fragments/nodes as appropriate
+dojo.widget.tags = {};
+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){
+		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["dojo:propertyset"] = function(fragment, widgetParser, parentComp){
+	// FIXME: Is this needed?
+	// FIXME: Not sure that this parses into the structure that I want it to parse into...
+	// FIXME: add support for nested propertySets
+	var properties = widgetParser.parseProperties(fragment["dojo:propertyset"]);
+}
+
+// FIXME: need to add the <dojo:connect />
+dojo.widget.tags["dojo:connect"] = function(fragment, widgetParser, parentComp){
+	var properties = widgetParser.parseProperties(fragment["dojo:connect"]);
+}
+
+// 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[frag["namespace"]+":"+stype]);
+	var twidget = dojo.widget.manager.getImplementation(stype,null,null,frag["namespace"]);
+	if(!twidget){
+		throw new Error('cannot find "' + type + '" widget');
+	}else if (!twidget.create){
+		throw new Error('"' + type + '" widget object has no "create" method and does not appear to implement *Widget');
+	}
+	localProperties["dojoinsertionindex"] = insertionIndex;
+	// FIXME: we lose no less than 5ms in construction!
+	var ret = twidget.create(localProperties, frag, parentComp, frag["namespace"]);
+	// 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);
+}

Propchange: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/Widget.js
------------------------------------------------------------------------------
    svn:eol-style = native

Added: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/Wizard.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/Wizard.js?view=auto&rev=449122
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/Wizard.js (added)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/Wizard.js Fri Sep 22 16:22:30 2006
@@ -0,0 +1,197 @@
+/*
+	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.Wizard");
+
+dojo.require("dojo.widget.*");
+dojo.require("dojo.widget.LayoutContainer");
+dojo.require("dojo.widget.ContentPane");
+dojo.require("dojo.event.*");
+dojo.require("dojo.html.style");
+
+//////////////////////////////////////////
+// WizardContainer -- a set of panels
+//////////////////////////////////////////
+dojo.widget.defineWidget(
+	"dojo.widget.WizardContainer",
+	dojo.widget.LayoutContainer,
+{
+	labelPosition: "top",
+
+	templatePath: dojo.uri.dojoUri("src/widget/templates/Wizard.html"),
+	templateCssPath: dojo.uri.dojoUri("src/widget/templates/Wizard.css"),
+
+	selected: null,		// currently selected panel
+	wizardNode: null, // the outer wizard node
+	wizardPanelContainerNode: null, // the container for the panels
+	wizardControlContainerNode: null, // the container for the wizard controls
+	previousButton: null, // the previous button
+	nextButton: null, // the next button
+	cancelButton: null, // the cancel button
+	doneButton: null, // the done button
+	nextButtonLabel: "next",
+	previousButtonLabel: "previous",
+	cancelButtonLabel: "cancel",
+	doneButtonLabel: "done",
+	cancelFunction : "",
+
+	hideDisabledButtons: false,
+
+	fillInTemplate: function(args, frag){
+		dojo.event.connect(this.nextButton, "onclick", this, "nextPanel");
+		dojo.event.connect(this.previousButton, "onclick", this, "previousPanel");
+		if (this.cancelFunction){
+			dojo.event.connect(this.cancelButton, "onclick", this.cancelFunction);
+		}else{
+			this.cancelButton.style.display = "none";
+		}
+		dojo.event.connect(this.doneButton, "onclick", this, "done");
+		this.nextButton.value = this.nextButtonLabel;
+		this.previousButton.value = this.previousButtonLabel;
+		this.cancelButton.value = this.cancelButtonLabel;
+		this.doneButton.value = this.doneButtonLabel;
+	},
+
+	checkButtons: function(){
+		var lastStep = !this.hasNextPanel();
+		this.nextButton.disabled = lastStep;
+		this.setButtonClass(this.nextButton);
+		if(this.selected.doneFunction){
+			this.doneButton.style.display = "";
+			// hide the next button if this is the last one and we have a done function
+			if(lastStep){
+				this.nextButton.style.display = "none";
+			}
+		}else{
+			this.doneButton.style.display = "none";
+		}
+		this.previousButton.disabled = ((!this.hasPreviousPanel()) || (!this.selected.canGoBack));
+		this.setButtonClass(this.previousButton);
+	},
+
+	setButtonClass: function(button){
+		if(!this.hideDisabledButtons){
+			button.style.display = "";
+			dojo.html.setClass(button, button.disabled ? "WizardButtonDisabled" : "WizardButton");
+		}else{
+			button.style.display = button.disabled ? "none" : "";
+		}
+	},
+
+	registerChild: function(panel, insertionIndex){
+		dojo.widget.WizardContainer.superclass.registerChild.call(this, panel, insertionIndex);
+		this.wizardPanelContainerNode.appendChild(panel.domNode);
+		panel.hide();
+
+		if(!this.selected){
+			this.onSelected(panel);
+		}
+		this.checkButtons();
+	},
+
+	onSelected: function(panel){
+		// Deselect old panel and select new one
+		if(this.selected ){
+			if (this.selected.checkPass()) {
+				this.selected.hide();
+			} else {
+				return;
+			}
+		}
+		panel.show();
+		this.selected = panel;
+	},
+
+	getPanels: function() {
+		return this.getChildrenOfType("WizardPane", false);
+	},
+
+	selectedIndex: function() {
+		if (this.selected) {
+			return dojo.lang.indexOf(this.getPanels(), this.selected);
+		}
+		return -1;
+	},
+
+	nextPanel: function() {
+		var selectedIndex = this.selectedIndex();
+		if ( selectedIndex > -1 ) {
+			var childPanels = this.getPanels();
+			if (childPanels[selectedIndex + 1]) {
+				this.onSelected(childPanels[selectedIndex + 1]);
+			}
+		}
+		this.checkButtons();
+	},
+
+	previousPanel: function() {
+		var selectedIndex = this.selectedIndex();
+		if ( selectedIndex > -1 ) {
+			var childPanels = this.getPanels();
+			if (childPanels[selectedIndex - 1]) {
+				this.onSelected(childPanels[selectedIndex - 1]);
+			}
+		}
+		this.checkButtons();
+	},
+
+	hasNextPanel: function() {
+		var selectedIndex = this.selectedIndex();
+		return (selectedIndex < (this.getPanels().length - 1));
+	},
+
+	hasPreviousPanel: function() {
+		var selectedIndex = this.selectedIndex();
+		return (selectedIndex > 0);
+	},
+
+	done: function() {
+		this.selected.done();
+	}
+});
+
+//////////////////////////////////////////
+// WizardPane -- a panel in a wizard
+//////////////////////////////////////////
+dojo.widget.defineWidget(
+	"dojo.widget.WizardPane",
+	dojo.widget.ContentPane,
+{
+	canGoBack: true,
+
+	passFunction: "",
+	doneFunction: "",
+
+	fillInTemplate: function(args, frag) {
+		if (this.passFunction) {
+			this.passFunction = dj_global[this.passFunction];
+		}
+		if (this.doneFunction) {
+			this.doneFunction = dj_global[this.doneFunction];
+		}
+	},
+
+	checkPass: function() {
+		if (this.passFunction && dojo.lang.isFunction(this.passFunction)) {
+			var failMessage = this.passFunction();
+			if (failMessage) {
+				alert(failMessage);
+				return false;
+			}
+		}
+		return true;
+	},
+
+	done: function() {
+		if (this.doneFunction && dojo.lang.isFunction(this.doneFunction)) {
+			this.doneFunction();
+		}
+	}
+});

Propchange: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/Wizard.js
------------------------------------------------------------------------------
    svn:eol-style = native

Added: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/YahooMap.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/YahooMap.js?view=auto&rev=449122
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/YahooMap.js (added)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/YahooMap.js Fri Sep 22 16:22:30 2006
@@ -0,0 +1,169 @@
+/*
+	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(){
+		// parameters
+		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(aPts){
+		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);
+	},
+	setControls:function(){
+		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(table){
+		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(){
+		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(args, frag){
+		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(){
+		//	clean the domNode before creating the map.
+		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: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/YahooMap.js
------------------------------------------------------------------------------
    svn:eol-style = native

Added: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/__package__.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/__package__.js?view=auto&rev=449122
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/__package__.js (added)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/__package__.js Fri Sep 22 16:22:30 2006
@@ -0,0 +1,23 @@
+/*
+	Copyright (c) 2004-2006, The Dojo Foundation
+	All Rights Reserved.
+
+	Licensed under the Academic Free License version 2.1 or above OR the
+	modified BSD license. For more information on Dojo licensing, see:
+
+		http://dojotoolkit.org/community/licensing.shtml
+*/
+
+dojo.kwCompoundRequire({
+	common: ["dojo.xml.Parse", 
+			 "dojo.widget.Widget", 
+			 "dojo.widget.Parse", 
+			 "dojo.widget.Manager"],
+	browser: ["dojo.widget.DomWidget",
+			  "dojo.widget.HtmlWidget"],
+	dashboard: ["dojo.widget.DomWidget",
+			  "dojo.widget.HtmlWidget"],
+	svg: 	 ["dojo.widget.SvgWidget"],
+	rhino: 	 ["dojo.widget.SwtWidget"]
+});
+dojo.provide("dojo.widget.*");

Propchange: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/__package__.js
------------------------------------------------------------------------------
    svn:eol-style = native

Added: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/demoEngine/DemoContainer.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/demoEngine/DemoContainer.js?view=auto&rev=449122
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/demoEngine/DemoContainer.js (added)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/demoEngine/DemoContainer.js Fri Sep 22 16:22:30 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: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/demoEngine/DemoContainer.js
------------------------------------------------------------------------------
    svn:eol-style = native

Added: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/demoEngine/DemoItem.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/demoEngine/DemoItem.js?view=auto&rev=449122
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/demoEngine/DemoItem.js (added)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/demoEngine/DemoItem.js Fri Sep 22 16:22:30 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: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/demoEngine/DemoItem.js
------------------------------------------------------------------------------
    svn:eol-style = native

Added: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/demoEngine/DemoNavigator.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/demoEngine/DemoNavigator.js?view=auto&rev=449122
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/demoEngine/DemoNavigator.js (added)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/demoEngine/DemoNavigator.js Fri Sep 22 16:22:30 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: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/demoEngine/DemoNavigator.js
------------------------------------------------------------------------------
    svn:eol-style = native

Added: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/demoEngine/DemoPane.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/demoEngine/DemoPane.js?view=auto&rev=449122
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/demoEngine/DemoPane.js (added)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/demoEngine/DemoPane.js Fri Sep 22 16:22:30 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: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/demoEngine/DemoPane.js
------------------------------------------------------------------------------
    svn:eol-style = native

Added: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/demoEngine/SourcePane.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/demoEngine/SourcePane.js?view=auto&rev=449122
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/demoEngine/SourcePane.js (added)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/demoEngine/SourcePane.js Fri Sep 22 16:22:30 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: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/demoEngine/SourcePane.js
------------------------------------------------------------------------------
    svn:eol-style = native

Added: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/demoEngine/__package__.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/demoEngine/__package__.js?view=auto&rev=449122
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/demoEngine/__package__.js (added)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/demoEngine/__package__.js Fri Sep 22 16:22:30 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: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/demoEngine/__package__.js
------------------------------------------------------------------------------
    svn:eol-style = native

Added: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/demoEngine/templates/DemoContainer.css
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/demoEngine/templates/DemoContainer.css?view=auto&rev=449122
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/demoEngine/templates/DemoContainer.css (added)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/demoEngine/templates/DemoContainer.css Fri Sep 22 16:22:30 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: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/demoEngine/templates/DemoContainer.css
------------------------------------------------------------------------------
    svn:eol-style = native

Added: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/demoEngine/templates/DemoContainer.html
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/demoEngine/templates/DemoContainer.html?view=auto&rev=449122
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/demoEngine/templates/DemoContainer.html (added)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/demoEngine/templates/DemoContainer.html Fri Sep 22 16:22:30 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: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/demoEngine/templates/DemoContainer.html
------------------------------------------------------------------------------
    svn:eol-style = native

Added: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/demoEngine/templates/DemoItem.css
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/demoEngine/templates/DemoItem.css?view=auto&rev=449122
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/demoEngine/templates/DemoItem.css (added)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/demoEngine/templates/DemoItem.css Fri Sep 22 16:22:30 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: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/demoEngine/templates/DemoItem.css
------------------------------------------------------------------------------
    svn:eol-style = native

Added: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/demoEngine/templates/DemoItem.html
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/demoEngine/templates/DemoItem.html?view=auto&rev=449122
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/demoEngine/templates/DemoItem.html (added)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/demoEngine/templates/DemoItem.html Fri Sep 22 16:22:30 2006
@@ -0,0 +1,21 @@
+<div dojoAttachPoint="domNode">
+	<div dojoAttachPoint="summaryBoxNode">
+		<table width="100%" cellspacing="0" cellpadding="0">
+			<tbody>
+				<tr>
+					<td dojoAttachPoint="screenshotTdNode" valign="top" width="1%">
+						<img dojoAttachPoint="thumbnailImageNode" dojoAttachEvent="onclick: onSelectDemo" />
+					</td>
+					<td dojoAttachPoint="summaryContainerNode" valign="top">
+						<h1 dojoAttachPoint="nameNode">
+						</h1>
+						<div dojoAttachPoint="summaryNode">
+							<p dojoAttachPoint="descriptionNode"></p>
+							<div dojoAttachPoint="viewDemoLinkNode"><img dojoAttachPoint="viewDemoImageNode"/ dojoAttachEvent="onclick: onSelectDemo"></div>
+						</div>
+					</td>
+				</tr>
+			</tbody>
+		</table>
+	</div>
+</div>

Propchange: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/demoEngine/templates/DemoItem.html
------------------------------------------------------------------------------
    svn:eol-style = native

Added: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/demoEngine/templates/DemoNavigator.css
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/demoEngine/templates/DemoNavigator.css?view=auto&rev=449122
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/demoEngine/templates/DemoNavigator.css (added)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/demoEngine/templates/DemoNavigator.css Fri Sep 22 16:22:30 2006
@@ -0,0 +1,28 @@
+.demoNavigatorListWrapper {
+	border:1px solid #dcdbdb;
+	background-color:#f8f8f8;
+	padding:2px;
+}
+
+.demoNavigatorListContainer {
+	border:1px solid #f0f0f0;
+	background-color:#fff;
+	padding:1em;
+}
+
+.demoNavigator h1 {
+	margin-top: 0px;
+	margin-bottom: 10px;
+	font-size: 1.2em;
+	border-bottom:1px dotted #a9ccf5;
+}
+
+.demoNavigator .dojoButton {
+	margin-bottom: 5px;
+}
+
+.demoNavigator .dojoButton .dojoButtonContents {
+	font-size: 1.1em;
+	width: 100px;
+	color: black;
+}

Propchange: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/demoEngine/templates/DemoNavigator.css
------------------------------------------------------------------------------
    svn:eol-style = native

Added: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/demoEngine/templates/DemoNavigator.html
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/demoEngine/templates/DemoNavigator.html?view=auto&rev=449122
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/demoEngine/templates/DemoNavigator.html (added)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/demoEngine/templates/DemoNavigator.html Fri Sep 22 16:22:30 2006
@@ -0,0 +1,24 @@
+<div dojoAttachPoint="domNode">
+	<table width="100%" cellspacing="0" cellpadding="5">
+		<tbody>
+			<tr dojoAttachPoint="navigationContainer">
+				<td dojoAttachPoint="categoriesNode" valign="top" width="1%">
+					<h1>Categories</h1>
+					<div dojoAttachPoint="categoriesButtonsNode"></div>
+				</td>
+
+				<td dojoAttachPoint="demoListNode" valign="top">
+					<div dojoAttachPoint="demoListWrapperNode">
+						<div dojoAttachPoint="demoListContainerNode">
+						</div>
+					</div>
+				</td>
+			</tr>
+			<tr>
+				<td colspan="2">
+					<div dojoAttachPoint="demoNode"></div>
+				</td>
+			</tr>
+		</tbody>
+	</table>
+</div>

Propchange: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/demoEngine/templates/DemoNavigator.html
------------------------------------------------------------------------------
    svn:eol-style = native

Added: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/demoEngine/templates/DemoPane.css
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/demoEngine/templates/DemoPane.css?view=auto&rev=449122
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/demoEngine/templates/DemoPane.css (added)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/demoEngine/templates/DemoPane.css Fri Sep 22 16:22:30 2006
@@ -0,0 +1,18 @@
+.demoPane {
+	width: 100%;
+	height: 100%;
+	padding: 0px;
+	margin: 0px;
+	overflow: hidden;
+}
+
+.demoPane iframe {
+	width: 100%;
+	height: 100%;
+	border: 0px;
+	border: none;
+	overflow: auto;
+	padding: 0px;
+	margin:0px;
+	background: #ffffff;
+}

Propchange: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/demoEngine/templates/DemoPane.css
------------------------------------------------------------------------------
    svn:eol-style = native

Added: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/demoEngine/templates/DemoPane.html
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/demoEngine/templates/DemoPane.html?view=auto&rev=449122
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/demoEngine/templates/DemoPane.html (added)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/demoEngine/templates/DemoPane.html Fri Sep 22 16:22:30 2006
@@ -0,0 +1,3 @@
+<div dojoAttachPoint="domNode">
+	<iframe dojoAttachPoint="demoNode"></iframe>
+</div>

Propchange: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/demoEngine/templates/DemoPane.html
------------------------------------------------------------------------------
    svn:eol-style = native

Added: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/demoEngine/templates/SourcePane.css
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/demoEngine/templates/SourcePane.css?view=auto&rev=449122
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/demoEngine/templates/SourcePane.css (added)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/demoEngine/templates/SourcePane.css Fri Sep 22 16:22:30 2006
@@ -0,0 +1,20 @@
+.sourcePane {
+	width: 100%;
+	height: 100%;
+	padding: 0px;
+	margin: 0px;
+	overflow: hidden;
+}
+
+.sourcePane textarea{
+	width: 100%;
+	height: 100%;
+	border: 0px;
+	overflow: auto;
+	padding: 0px;
+	margin:0px;
+}
+
+* html .sourcePane {
+	overflow: auto;
+}

Propchange: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/demoEngine/templates/SourcePane.css
------------------------------------------------------------------------------
    svn:eol-style = native

Added: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/demoEngine/templates/SourcePane.html
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/demoEngine/templates/SourcePane.html?view=auto&rev=449122
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/demoEngine/templates/SourcePane.html (added)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/demoEngine/templates/SourcePane.html Fri Sep 22 16:22:30 2006
@@ -0,0 +1,3 @@
+<div dojoAttachPoint="domNode">
+	<textarea dojoAttachPoint="sourceNode" rows="100%"></textarea>
+</div>

Propchange: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/demoEngine/templates/SourcePane.html
------------------------------------------------------------------------------
    svn:eol-style = native

Added: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/demoEngine/templates/general.css
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/demoEngine/templates/general.css?view=auto&rev=449122
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/demoEngine/templates/general.css (added)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/demoEngine/templates/general.css Fri Sep 22 16:22:30 2006
@@ -0,0 +1,73 @@
+.demoListWrapper {
+	border:1px solid #dcdbdb;
+	background-color:#f8f8f8;
+	padding:2px;
+}
+
+.demoListContainer {
+	border:1px solid #f0f0f0;
+	background-color:#fff;
+	padding:1em;
+}
+
+.demoSummaryBox {
+	background: #efefef;
+	border:1px solid #dae3ee;
+}
+
+.screenshot {
+	padding:0.65em;
+	width:175px;
+	border-right:1px solid #fafafa;
+	text-align:center;
+}
+
+.demoSummary {
+	margin-bottom:1em;
+}
+
+.demoSummary a:link, .demoSummary a:visited {
+	color:#a6238f;
+	text-decoration:none;
+}
+
+.summaryContainer {
+	border-left:1px solid #ddd;
+}
+
+.summaryContainer 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;
+}
+
+.summaryContainer h1 .packageSummary {
+	display:block;
+	color:#000;
+	font-size:10px;
+	margin-top:2px;
+}
+
+.summaryContainer .summary {
+	padding:1em;
+}
+
+.summaryContainer .summary p {
+	font-size:0.85em;
+	padding:0;
+	margin:0;
+}
+
+.reflection {
+	background: url("images/demoBoxReflection.gif") repeat-x top left;
+	height:25px;
+}
+
+.view {
+	text-align:right;
+}

Propchange: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/demoEngine/templates/general.css
------------------------------------------------------------------------------
    svn:eol-style = native

Added: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/demoEngine/templates/images/test_thumb.gif
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/demoEngine/templates/images/test_thumb.gif?view=auto&rev=449122
==============================================================================
Binary file - no diff available.

Propchange: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/demoEngine/templates/images/test_thumb.gif
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/demoEngine/templates/images/viewDemo.png
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/demoEngine/templates/images/viewDemo.png?view=auto&rev=449122
==============================================================================
Binary file - no diff available.

Propchange: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/demoEngine/templates/images/viewDemo.png
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/html/layout.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/html/layout.js?view=auto&rev=449122
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/html/layout.js (added)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/html/layout.js Fri Sep 22 16:22:30 2006
@@ -0,0 +1,121 @@
+/*
+	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.html.layout");
+
+dojo.require("dojo.lang.common");
+dojo.require("dojo.string.extras");
+dojo.require("dojo.html.style");
+dojo.require("dojo.html.layout");
+
+/**
+ * Layout a bunch of child dom nodes within a parent dom node
+ * Input is an array of objects like:
+ * @ container - parent node
+ * @ layoutPriority - "top-bottom" or "left-right"
+ * @ children an array like [ {domNode: foo, layoutAlign: "bottom" }, {domNode: bar, layoutAlign: "client"} ]
+ */
+dojo.widget.html.layout = function(container, children, layoutPriority) {
+	dojo.html.addClass(container, "dojoLayoutContainer");
+
+	// Copy children array and remove elements w/out layout.
+	// Also record each child's position in the input array, for sorting purposes.
+	children = dojo.lang.filter(children, function(child, idx){
+		child.idx = idx;
+		return dojo.lang.inArray(["top","bottom","left","right","client","flood"], child.layoutAlign)
+	});
+
+	// Order the children according to layoutPriority.
+	// Multiple children w/the same layoutPriority will be sorted by their position in the input array.
+	if(layoutPriority && layoutPriority!="none"){
+		var rank = function(child){
+			switch(child.layoutAlign){
+				case "flood":
+					return 1;
+				case "left":
+				case "right":
+					return (layoutPriority=="left-right") ? 2 : 3;
+				case "top":
+				case "bottom":
+					return (layoutPriority=="left-right") ? 3 : 2;
+				default:
+					return 4;
+			}
+		};
+		children.sort(function(a,b){
+			return (rank(a)-rank(b)) || (a.idx - b.idx);
+		});
+	}
+
+	// remaining space (blank area where nothing has been written)
+	var f={
+		top: dojo.html.getPixelValue(container, "padding-top", true),
+		left: dojo.html.getPixelValue(container, "padding-left", true)
+	};
+	dojo.lang.mixin(f, dojo.html.getContentBox(container));
+
+	// set positions/sizes
+	dojo.lang.forEach(children, function(child){
+		var elm=child.domNode;
+		var pos=child.layoutAlign;
+		// set elem to upper left corner of unused space; may move it later
+		with(elm.style){
+			left = f.left+"px";
+			top = f.top+"px";
+			bottom = "auto";
+			right = "auto";
+		}
+		dojo.html.addClass(elm, "dojoAlign" + dojo.string.capitalize(pos));
+
+		// set size && adjust record of remaining space.
+		// note that setting the width of a <div> may affect it's height.
+		// TODO: same is true for widgets but need to implement API to support that
+		if ( (pos=="top")||(pos=="bottom") ) {
+			dojo.html.setMarginBox(elm, { width: f.width });
+			var h = dojo.html.getMarginBox(elm).height;
+			f.height -= h;
+			if(pos=="top"){
+				f.top += h;
+			}else{
+				elm.style.top = f.top + f.height + "px";
+			}
+		}else if(pos=="left" || pos=="right"){
+			var w = dojo.html.getMarginBox(elm).width;
+			// width needs to be set for Firefox (#941)
+			dojo.html.setMarginBox(elm, { width: w, height: f.height });
+
+			f.width -= w;
+			if(pos=="left"){
+				f.left += w;
+			}else{
+				elm.style.left = f.left + f.width + "px";
+			}
+		} else if(pos=="flood" || pos=="client"){
+			dojo.html.setMarginBox(elm, { width: f.width, height: f.height });
+		}
+		
+		// TODO: for widgets I want to call resizeTo(), but for top/bottom
+		// alignment I only want to set the width, and have the size determined
+		// dynamically.  (The thinner you make a div, the more height it consumes.)
+		if(child.onResized){
+			child.onResized();
+		}
+	});
+};
+
+// This is essential CSS to make layout work (it isn't "styling" CSS)
+// make sure that the position:absolute in dojoAlign* overrides other classes
+dojo.html.insertCssText(
+	".dojoLayoutContainer{ position: relative; display: block; }\n" +
+	"body .dojoAlignTop, body .dojoAlignBottom, body .dojoAlignLeft, body .dojoAlignRight { position: absolute; overflow: hidden; }\n" +
+	"body .dojoAlignClient { position: absolute }\n" +
+	".dojoAlignClient { overflow: auto; }\n"
+);
+

Propchange: tapestry/tapestry4/trunk/tapestry-framework/src/js/dojo/src/widget/html/layout.js
------------------------------------------------------------------------------
    svn:eol-style = native