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/06/10 15:59:38 UTC

svn commit: r413300 [13/16] - in /tapestry/tapestry4/trunk/framework/src/js: dojo/ dojo/src/ dojo/src/animation/ dojo/src/collections/ dojo/src/compat/ dojo/src/crypto/ dojo/src/data/ dojo/src/data/format/ dojo/src/data/provider/ dojo/src/debug/ dojo/s...

Added: tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/TreeBasicController.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/TreeBasicController.js?rev=413300&view=auto
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/TreeBasicController.js (added)
+++ tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/TreeBasicController.js Sat Jun 10 06:59:28 2006
@@ -0,0 +1,294 @@
+/*
+	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.TreeBasicController");
+
+dojo.require("dojo.event.*");
+dojo.require("dojo.json")
+dojo.require("dojo.io.*");
+
+
+dojo.widget.tags.addParseTreeHandler("dojo:TreeBasicController");
+
+
+dojo.widget.TreeBasicController = function() {
+	dojo.widget.HtmlWidget.call(this);
+}
+
+dojo.inherits(dojo.widget.TreeBasicController, dojo.widget.HtmlWidget);
+
+
+dojo.lang.extend(dojo.widget.TreeBasicController, {
+	widgetType: "TreeBasicController",
+
+	DNDController: "",
+
+	dieWithTree: false,
+
+	initialize: function(args, frag){
+
+		/* no DND by default for compatibility */
+		if (this.DNDController == "create") {
+			dojo.require("dojo.dnd.TreeDragAndDrop");
+			this.DNDController = new dojo.dnd.TreeDNDController(this);
+		}
+
+
+
+	},
+
+
+	/**
+	 * Binds controller to all tree events
+	*/
+	listenTree: function(tree) {
+		//dojo.debug("Event "+tree.eventNames.treeClick);
+		dojo.event.topic.subscribe(tree.eventNames.createDOMNode, this, "onCreateDOMNode");
+		dojo.event.topic.subscribe(tree.eventNames.treeClick, this, "onTreeClick");
+		dojo.event.topic.subscribe(tree.eventNames.treeCreate, this, "onTreeCreate");
+		dojo.event.topic.subscribe(tree.eventNames.treeDestroy, this, "onTreeDestroy");
+
+		if (this.DNDController) {
+			this.DNDController.listenTree(tree);
+		}
+	},
+
+	unlistenTree: function(tree) {
+		dojo.event.topic.unsubscribe(tree.eventNames.createDOMNode, this, "onCreateDOMNode");
+		dojo.event.topic.unsubscribe(tree.eventNames.treeClick, this, "onTreeClick");
+		dojo.event.topic.unsubscribe(tree.eventNames.treeCreate, this, "onTreeCreate");
+		dojo.event.topic.unsubscribe(tree.eventNames.treeDestroy, this, "onTreeDestroy");
+	},
+
+	onTreeDestroy: function(message) {
+		var tree = message.source;
+
+		this.unlistenTree(tree);
+
+		if (this.dieWithTree) {
+			//alert("Killing myself "+this.widgetId);
+			this.destroy();
+			//dojo.debug("done");
+		}
+	},
+
+	onCreateDOMNode: function(message) {
+
+		var node = message.source;
+
+
+		if (node.expandLevel > 0) {
+			this.expandToLevel(node, node.expandLevel);
+		}
+	},
+
+	// perform actions-initializers for tree
+	onTreeCreate: function(message) {
+		var tree = message.source;
+		var _this = this;
+		if (tree.expandLevel) {
+			dojo.lang.forEach(tree.children,
+				function(child) {
+					_this.expandToLevel(child, tree.expandLevel-1)
+				}
+			);
+		}
+	},
+
+	expandToLevel: function(node, level) {
+		if (level == 0) return;
+
+		var children = node.children;
+		var _this = this;
+
+		var handler = function(node, expandLevel) {
+			this.node = node;
+			this.expandLevel = expandLevel;
+			// recursively expand opened node
+			this.process = function() {
+				//dojo.debug("Process "+node+" level "+level);
+				for(var i=0; i<this.node.children.length; i++) {
+					var child = node.children[i];
+
+					_this.expandToLevel(child, this.expandLevel);
+				}
+			};
+		}
+
+		var h = new handler(node, level-1);
+
+
+		this.expand(node, false, h, h.process);
+
+	},
+
+
+
+
+	onTreeClick: function(message){
+		var node = message.source;
+
+		if(node.isLocked()) {
+			return false;
+		}
+
+		if (node.isExpanded){
+			this.collapse(node);
+		} else {
+			this.expand(node);
+		}
+	},
+
+	expand: function(node, sync, callObj, callFunc) {
+		node.expand();
+		if (callFunc) callFunc.apply(callObj, [node]);
+	},
+
+	collapse: function(node) {
+
+		node.collapse();
+	},
+
+// =============================== move ============================
+
+	/**
+	 * Checks whether it is ok to change parent of child to newParent
+	 * May incur type checks etc
+	 *
+	 * It should check only hierarchical possibility w/o index, etc
+	 * because in onDragOver event for Between DND mode we can't calculate index at once on onDragOVer.
+	 * index changes as client moves mouse up-down over the node
+	 */
+	canMove: function(child, newParent){
+
+		if (child.actionIsDisabled(child.actions.MOVE)) {
+			return false;
+		}
+
+		// if we move under same parent then no matter if ADDCHILD disabled for him
+		// but if we move to NEW parent then check if action is disabled for him
+		// also covers case for newParent being a non-folder in strict mode etc
+		if (child.parent !== newParent && newParent.actionIsDisabled(newParent.actions.ADDCHILD)) {
+			return false;
+		}
+
+		// Can't move parent under child. check whether new parent is child of "child".
+		var node = newParent;
+		while(node.isTreeNode) {
+			//dojo.debugShallow(node.title)
+			if (node === child) {
+				// parent of newParent is child
+				return false;
+			}
+			node = node.parent;
+		}
+
+		return true;
+	},
+
+
+	move: function(child, newParent, index) {
+
+		/* move sourceTreeNode to new parent */
+		if (!this.canMove(child, newParent)) {
+			return false;
+		}
+
+		var result = this.doMove(child, newParent, index);
+
+		if (!result) return result;
+
+		if (newParent.isTreeNode) {
+			this.expand(newParent);
+		}
+
+		return result;
+	},
+
+	doMove: function(child, newParent, index) {
+		child.tree.move(child, newParent, index);
+
+		return true;
+	},
+
+// =============================== removeNode ============================
+
+
+	canRemoveNode: function(child) {
+		if (child.actionIsDisabled(child.actions.REMOVE)) {
+			return false;
+		}
+
+		return true;
+	},
+
+
+	removeNode: function(node, callObj, callFunc) {
+		if (!this.canRemoveNode(node)) {
+			return false;
+		}
+
+		return this.doRemoveNode(node, callObj, callFunc);
+	},
+
+
+	doRemoveNode: function(node, callObj, callFunc) {
+		node.tree.removeNode(node);
+
+		if (callFunc) {
+			callFunc.apply(dojo.lang.isUndefined(callObj) ? this : callObj, [node]);
+		}
+	},
+
+
+	// -----------------------------------------------------------------------------
+	//                             Create node stuff
+	// -----------------------------------------------------------------------------
+
+
+	canCreateChild: function(parent, index, data) {
+		if (parent.actionIsDisabled(parent.actions.ADDCHILD)) return false;
+
+		return true;
+	},
+
+
+	/* send data to server and add child from server */
+	/* data may contain an almost ready child, or anything else, suggested to server */
+	/*in RPC controllers server responds with child data to be inserted */
+	createChild: function(parent, index, data, callObj, callFunc) {
+		if (!this.canCreateChild(parent, index, data)) {
+			return false;
+		}
+
+		return this.doCreateChild.apply(this, arguments);
+	},
+
+	doCreateChild: function(parent, index, data, callObj, callFunc) {
+
+		var widgetType = data.widgetType ? data.widgetType : "TreeNode";
+
+		var newChild = dojo.widget.createWidget(widgetType, data);
+
+		parent.addChild(newChild, index);
+
+		this.expand(parent);
+
+		if (callFunc) {
+			callFunc.apply(callObj, [newChild]);
+		}
+
+		return newChild;
+	}
+
+
+
+});

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

Added: tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/TreeControllerExtension.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/TreeControllerExtension.js?rev=413300&view=auto
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/TreeControllerExtension.js (added)
+++ tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/TreeControllerExtension.js Sat Jun 10 06:59:28 2006
@@ -0,0 +1,95 @@
+/*
+	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
+*/
+
+/**
+ * Additional tree utils
+ *
+ */
+dojo.provide("dojo.widget.TreeControllerExtension");
+
+
+dojo.widget.TreeControllerExtension = function() { }
+
+dojo.lang.extend(dojo.widget.TreeControllerExtension, {
+
+	saveExpandedIndices: function(node, field) {
+		var obj = {};
+
+		for(var i=0; i<node.children.length; i++) {
+			if (node.children[i].isExpanded) {
+				var key = dojo.lang.isUndefined(field) ? i : node.children[i][field];
+				obj[key] = this.saveExpandedIndices(node.children[i], field);
+			}
+		}
+
+		return obj;
+	},
+
+
+	restoreExpandedIndices: function(node, savedIndices, field) {
+		var _this = this;
+
+		var handler = function(node, savedIndices) {
+			this.node = node; //.children[i];
+			this.savedIndices = savedIndices; //[i];
+			// recursively read next savedIndices level and apply to opened node
+			this.process = function() {
+				//dojo.debug("Callback applied for "+this.node);
+				_this.restoreExpandedIndices(this.node, this.savedIndices, field);
+			};
+		}
+
+
+		for(var i=0; i<node.children.length; i++) {
+			var child = node.children[i];
+
+			var found = false;
+			var key = -1;
+
+			//dojo.debug("Check "+child)
+			// process field set case
+			if (dojo.lang.isUndefined(field) && savedIndices[i]) {
+				found = true;
+				key = i;
+			}
+
+			// process case when field is not set
+			if (field) {
+				for(var key in savedIndices) {
+					//dojo.debug("Compare "+key+" "+child[field])
+					if (key == child[field]) {
+						found = true;
+						break;
+					}
+				}
+			}
+
+			// if we found anything - expand it
+			if (found) {
+				//dojo.debug("Found at "+key)
+				var h = new handler(child, savedIndices[key]);
+				_this.expand(child, false, h, h.process);
+			} else if (child.isExpanded) { // not found, so collapse
+				//dojo.debug("Collapsing all descendants "+node.children[i])
+				dojo.lang.forEach(child.getDescendants(), function(elem) { _this.collapse(elem); });
+				//this.collapse(node.children[i]);
+			}
+
+		}
+
+
+	}
+
+});
+
+
+
+
+

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

Added: tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/TreeLoadingController.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/TreeLoadingController.js?rev=413300&view=auto
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/TreeLoadingController.js (added)
+++ tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/TreeLoadingController.js Sat Jun 10 06:59:28 2006
@@ -0,0 +1,217 @@
+/*
+	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.TreeLoadingController");
+
+dojo.require("dojo.widget.TreeBasicController");
+dojo.require("dojo.event.*");
+dojo.require("dojo.json")
+dojo.require("dojo.io.*");
+
+
+dojo.widget.tags.addParseTreeHandler("dojo:TreeLoadingController");
+
+
+dojo.widget.TreeLoadingController = function() {
+	dojo.widget.TreeBasicController.call(this);
+}
+
+dojo.inherits(dojo.widget.TreeLoadingController, dojo.widget.TreeBasicController);
+
+
+dojo.lang.extend(dojo.widget.TreeLoadingController, {
+	widgetType: "TreeLoadingController",
+
+	RPCUrl: "",
+
+	RPCActionParam: "action", // used for GET for RPCUrl
+
+
+	/**
+	 * Common RPC error handler (dies)
+	*/
+	RPCErrorHandler: function(type, obj, evt) {
+		alert( "RPC Error: " + (obj.message||"no message"));
+	},
+
+
+
+	getRPCUrl: function(action) {
+
+		// RPCUrl=local meant SOLELY for DEMO and LOCAL TESTS.
+		// May lead to widgetId collisions
+		if (this.RPCUrl == "local") {
+			var dir = document.location.href.substr(0, document.location.href.lastIndexOf('/'));
+			var localUrl = dir+"/"+action;
+			//dojo.debug(localUrl);
+			return localUrl;
+		}
+
+		if (!this.RPCUrl) {
+			dojo.raise("Empty RPCUrl: can't load");
+		}
+
+		return this.RPCUrl + ( this.RPCUrl.indexOf("?") > -1 ? "&" : "?") + this.RPCActionParam+"="+action;
+	},
+
+
+	/**
+	 * Add all loaded nodes from array obj as node children and expand it
+	*/
+	loadProcessResponse: function(node, result, callObj, callFunc) {
+
+		if (!dojo.lang.isUndefined(result.error)) {
+			this.RPCErrorHandler("server", result.error);
+			return false;
+		}
+
+		//dojo.debugShallow(result);
+
+		var newChildren = result;
+
+		if (!dojo.lang.isArray(newChildren)) {
+			dojo.raise('loadProcessResponse: Not array loaded: '+newChildren);
+		}
+
+		for(var i=0; i<newChildren.length; i++) {
+			// looks like dojo.widget.manager needs no special "add" command
+			newChildren[i] = dojo.widget.createWidget(node.widgetType, newChildren[i]);
+			node.addChild(newChildren[i]);
+		}
+
+
+		//node.addAllChildren(newChildren);
+
+		node.state = node.loadStates.LOADED;
+
+		//dojo.debug(callFunc);
+
+		if (dojo.lang.isFunction(callFunc)) {
+			callFunc.apply(dojo.lang.isUndefined(callObj) ? this : callObj, [node, newChildren]);
+		}
+		//this.expand(node);
+	},
+
+	getInfo: function(obj) {
+		return obj.getInfo();
+	},
+
+	runRPC: function(kw) {
+		var _this = this;
+
+		var handle = function(type, data, evt) {
+			// unlock BEFORE any processing is done
+			// so errorHandler may apply locking
+			if (kw.lock) {
+				dojo.lang.forEach(kw.lock,
+					function(t) { t.unlock() }
+				);
+			}
+
+			if(type == "load"){
+				kw.load.call(this, data);
+			}else{
+				this.RPCErrorHandler(type, data, evt);
+			}
+
+		}
+
+		if (kw.lock) {
+			dojo.lang.forEach(kw.lock,
+				function(t) { t.lock() }
+			);
+		}
+
+
+		dojo.io.bind({
+			url: kw.url,
+			/* I hitch to get this.loadOkHandler */
+			handle: dojo.lang.hitch(this, handle),
+			mimetype: "text/json",
+			preventCache: true,
+			sync: kw.sync,
+			content: { data: dojo.json.serialize(kw.params) }
+		});
+	},
+
+
+
+	/**
+	 * Load children of the node from server
+	 * Synchroneous loading doesn't break control flow
+	 * I need sync mode for DnD
+	*/
+	loadRemote: function(node, sync, callObj, callFunc){
+		var _this = this;
+
+		var params = {
+			node: this.getInfo(node),
+			tree: this.getInfo(node.tree)
+		};
+
+		//dojo.debug(callFunc)
+
+		this.runRPC({
+			url: this.getRPCUrl('getChildren'),
+			load: function(result) {
+				_this.loadProcessResponse(node, result, callObj, callFunc) ;
+			},
+			sync: sync,
+			lock: [node],
+			params: params
+		});
+
+	},
+
+
+	expand: function(node, sync, callObj, callFunc) {
+
+		if (node.state == node.loadStates.UNCHECKED && node.isFolder) {
+
+			this.loadRemote(node, sync,
+				this,
+				function(node, newChildren) {
+					this.expand(node, sync, callObj, callFunc);
+				}
+			);
+
+			return;
+		}
+
+		dojo.widget.TreeBasicController.prototype.expand.apply(this, arguments);
+
+	},
+
+
+
+	doMove: function(child, newParent, index) {
+		/* load nodes into newParent in sync mode, if needed, first */
+		if (newParent.isTreeNode && newParent.state == newParent.loadStates.UNCHECKED) {
+			this.loadRemote(newParent, true);
+		}
+
+		return dojo.widget.TreeBasicController.prototype.doMove.apply(this, arguments);
+	},
+
+
+	doCreateChild: function(parent, index, data, callObj, callFunc) {
+
+		/* load nodes into newParent in sync mode, if needed, first */
+		if (parent.state == parent.loadStates.UNCHECKED) {
+			this.loadRemote(parent, true);
+		}
+
+		return dojo.widget.TreeBasicController.prototype.doCreateChild.apply(this, arguments);
+	}
+
+
+
+});

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

Added: tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/TreeNode.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/TreeNode.js?rev=413300&view=auto
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/TreeNode.js (added)
+++ tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/TreeNode.js Sat Jun 10 06:59:28 2006
@@ -0,0 +1,534 @@
+/*
+	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.TreeNode");
+
+dojo.require("dojo.event.*");
+dojo.require("dojo.io.*");
+
+// make it a tag
+dojo.widget.tags.addParseTreeHandler("dojo:TreeNode");
+
+
+// # //////////
+
+dojo.widget.TreeNode = function() {
+	dojo.widget.HtmlWidget.call(this);
+
+	this.actionsDisabled = [];
+}
+
+dojo.inherits(dojo.widget.TreeNode, dojo.widget.HtmlWidget);
+
+dojo.lang.extend(dojo.widget.TreeNode, {
+	widgetType: "TreeNode",
+
+	loadStates: {
+		UNCHECKED: "UNCHECKED",
+    	LOADING: "LOADING",
+    	LOADED: "LOADED"
+	},
+
+
+	actions: {
+		MOVE: "MOVE",
+    	REMOVE: "REMOVE",
+    	EDIT: "EDIT",
+    	ADDCHILD: "ADDCHILD"
+	},
+
+	isContainer: true,
+
+	lockLevel: 0, // lock ++ unlock --, so nested locking works fine
+
+
+	templateString: ('<div class="dojoTreeNode"> '
+		+ '<span treeNode="${this.widgetId}" class="dojoTreeNodeLabel" dojoAttachPoint="labelNode"> '
+		+ '		<span dojoAttachPoint="titleNode" dojoAttachEvent="onClick: onTitleClick" class="dojoTreeNodeLabelTitle">${this.title}</span> '
+		+ '</span> '
+		+ '<span class="dojoTreeNodeAfterLabel" dojoAttachPoint="afterLabelNode">${this.afterLabel}</span> '
+		+ '<div dojoAttachPoint="containerNode" style="display:none"></div> '
+		+ '</div>').replace(/(>|<)\s+/g, '$1'), // strip whitespaces between nodes
+
+
+	childIconSrc: "",
+	childIconFolderSrc: dojo.uri.dojoUri("src/widget/templates/images/Tree/closed.gif"), // for under root parent item child icon,
+	childIconDocumentSrc: dojo.uri.dojoUri("src/widget/templates/images/Tree/document.gif"), // for under root parent item child icon,
+
+	childIcon: null,
+	isTreeNode: true,
+
+	objectId: "", // the widget represents an object
+
+	afterLabel: "",
+	afterLabelNode: null, // node to the left of labelNode
+
+	// an icon left from childIcon: imgs[-2].
+	// if +/- for folders, blank for leaves
+	expandIcon: null,
+
+	title: "",
+	object: "", // node may have object attached, settable from HTML
+	isFolder: false,
+
+	labelNode: null, // the item label
+	titleNode: null, // the item title
+	imgs: null, // an array of icons imgs
+
+	expandLevel: "", // expand to level
+
+	tree: null,
+
+	depth: 0,
+
+	isExpanded: false,
+
+	state: null,  // after creation will change to loadStates: "loaded/loading/unchecked"
+	domNodeInitialized: false,  // domnode is initialized with icons etc
+
+
+	isFirstNode: function() {
+		return this.getParentIndex() == 0 ? true: false;
+	},
+
+	isLastNode: function() {
+		return this.getParentIndex() == this.parent.children.length-1 ? true : false;
+	},
+
+	lock: function(){ return this.tree.lock.apply(this, arguments) },
+	unlock: function(){ return this.tree.unlock.apply(this, arguments) },
+	isLocked: function(){ return this.tree.isLocked.apply(this, arguments) },
+	cleanLock: function(){ return this.tree.cleanLock.apply(this, arguments) },
+
+	actionIsDisabled: function(action) {
+		var _this = this;
+
+		var disabled = false;
+
+		if (this.tree.strictFolders && action == this.actions.ADDCHILD && !this.isFolder) {
+			disabled = true;
+		}
+
+		if (dojo.lang.inArray(_this.actionsDisabled, action)) {
+			disabled = true;
+		}
+
+		if (this.isLocked()) {
+			disabled = true;
+		}
+
+		return disabled;
+	},
+
+	getInfo: function() {
+		// No title here (title may be widget)
+		var info = {
+			widgetId: this.widgetId,
+			objectId: this.objectId,
+			index: this.getParentIndex(),
+			isFolder: this.isFolder
+		}
+
+		return info;
+	},
+
+	initialize: function(args, frag){
+
+		//dojo.debug(this.title)
+
+		this.state = this.loadStates.UNCHECKED;
+
+		for(var i=0; i<this.actionsDisabled.length; i++) {
+			this.actionsDisabled[i] = this.actionsDisabled[i].toUpperCase();
+		}
+
+		this.expandLevel = parseInt(this.expandLevel);
+
+	},
+
+
+	/**
+	 * Change visible node depth by appending/prepending with blankImgs
+	 * @param depthDiff Integer positive => move right, negative => move left
+	*/
+	adjustDepth: function(depthDiff) {
+
+		for(var i=0; i<this.children.length; i++) {
+			this.children[i].adjustDepth(depthDiff);
+		}
+
+		this.depth += depthDiff;
+
+		if (depthDiff>0) {
+			for(var i=0; i<depthDiff; i++) {
+				var img = this.tree.makeBlankImg();
+				this.imgs.unshift(img);
+				//dojo.debugShallow(this.domNode);
+				dojo.dom.insertBefore(this.imgs[0], this.domNode.firstChild);
+
+			}
+		}
+		if (depthDiff<0) {
+			for(var i=0; i<-depthDiff;i++) {
+				this.imgs.shift();
+				dojo.dom.removeNode(this.domNode.firstChild);
+			}
+		}
+
+	},
+
+
+	markLoading: function() {
+		this._markLoadingSavedIcon = this.expandIcon.src;
+		this.expandIcon.src = this.tree.expandIconSrcLoading;
+	},
+
+	// if icon is "Loading" then
+	unMarkLoading: function() {
+		if (!this._markLoadingSavedIcon) return;
+
+		var im = new Image();
+		im.src = this.tree.expandIconSrcLoading;
+
+		//dojo.debug("Unmark "+this.expandIcon.src+" : "+im.src);
+		if (this.expandIcon.src == im.src) {
+			this.expandIcon.src = this._markLoadingSavedIcon;
+		}
+		this._markLoadingSavedIcon = null;
+	},
+
+
+	setFolder: function() {
+		dojo.event.connect(this.expandIcon, 'onclick', this, 'onTreeClick');
+		this.expandIcon.src = this.isExpanded ? this.tree.expandIconSrcMinus : this.tree.expandIconSrcPlus;
+		this.isFolder = true;
+	},
+
+
+	createDOMNode: function(tree, depth){
+
+		this.tree = tree;
+		this.depth = depth;
+
+
+		//
+		// add the tree icons
+		//
+
+		this.imgs = [];
+
+		for(var i=0; i<this.depth+1; i++){
+
+			var img = this.tree.makeBlankImg();
+
+			this.domNode.insertBefore(img, this.labelNode);
+
+			this.imgs.push(img);
+		}
+
+
+		this.expandIcon = this.imgs[this.imgs.length-1];
+
+
+		this.childIcon = this.tree.makeBlankImg();
+
+		// add to images before the title
+		this.imgs.push(this.childIcon);
+
+		dojo.dom.insertBefore(this.childIcon, this.titleNode);
+
+		// node with children(from source html) becomes folder on build stage.
+		if (this.children.length || this.isFolder) {
+			this.setFolder();
+		}
+		else {
+			// leaves are always loaded
+			//dojo.debug("Set "+this+" state to loaded");
+			this.state = this.loadStates.LOADED;
+		}
+
+		dojo.event.connect(this.childIcon, 'onclick', this, 'onIconClick');
+
+
+		//
+		// create the child rows
+		//
+
+
+		for(var i=0; i<this.children.length; i++){
+			this.children[i].parent = this;
+
+			var node = this.children[i].createDOMNode(this.tree, this.depth+1);
+
+			this.containerNode.appendChild(node);
+		}
+
+
+		if (this.children.length) {
+			this.state = this.loadStates.LOADED;
+		}
+
+		this.updateIcons();
+
+		this.domNodeInitialized = true;
+
+		dojo.event.topic.publish(this.tree.eventNames.createDOMNode, { source: this } );
+
+		return this.domNode;
+	},
+
+	onTreeClick: function(e){
+		dojo.event.topic.publish(this.tree.eventNames.treeClick, { source: this, event: e });
+	},
+
+	onIconClick: function(e){
+		dojo.event.topic.publish(this.tree.eventNames.iconClick, { source: this, event: e });
+	},
+
+	onTitleClick: function(e){
+		dojo.event.topic.publish(this.tree.eventNames.titleClick, { source: this, event: e });
+	},
+
+	markSelected: function() {
+		dojo.html.addClass(this.titleNode, 'dojoTreeNodeLabelSelected');
+	},
+
+
+	unMarkSelected: function() {
+		//dojo.debug('unmark')
+		dojo.html.removeClass(this.titleNode, 'dojoTreeNodeLabelSelected');
+	},
+
+	updateExpandIcon: function() {
+		if (this.isFolder){
+			this.expandIcon.src = this.isExpanded ? this.tree.expandIconSrcMinus : this.tree.expandIconSrcPlus;
+		} else {
+			this.expandIcon.src = this.tree.blankIconSrc;
+		}
+	},
+
+	/* set the grid under the expand icon */
+	updateExpandGrid: function() {
+
+		if (this.tree.showGrid){
+			if (this.depth){
+				this.setGridImage(-2, this.isLastNode() ? this.tree.gridIconSrcL : this.tree.gridIconSrcT);
+			}else{
+				if (this.isFirstNode()){
+					this.setGridImage(-2, this.isLastNode() ? this.tree.gridIconSrcX : this.tree.gridIconSrcY);
+				}else{
+					this.setGridImage(-2, this.isLastNode() ? this.tree.gridIconSrcL : this.tree.gridIconSrcT);
+				}
+			}
+		}else{
+			this.setGridImage(-2, this.tree.blankIconSrc);
+		}
+
+	},
+
+	/* set the grid under the child icon */
+	updateChildGrid: function() {
+
+		if ((this.depth || this.tree.showRootGrid) && this.tree.showGrid){
+			this.setGridImage(-1, (this.children.length && this.isExpanded) ? this.tree.gridIconSrcP : this.tree.gridIconSrcC);
+		}else{
+			if (this.tree.showGrid && !this.tree.showRootGrid){
+				this.setGridImage(-1, (this.children.length && this.isExpanded) ? this.tree.gridIconSrcZ : this.tree.blankIconSrc);
+			}else{
+				this.setGridImage(-1, this.tree.blankIconSrc);
+			}
+		}
+
+
+	},
+
+	updateParentGrid: function() {
+		var parent = this.parent;
+
+		//dojo.debug("updateParentGrid "+this);
+
+		for(var i=0; i<this.depth; i++){
+
+			//dojo.debug("Parent "+parent);
+
+			var idx = this.imgs.length-(3+i);
+			var img = (this.tree.showGrid && !parent.isLastNode()) ? this.tree.gridIconSrcV : this.tree.blankIconSrc;
+
+			//dojo.debug("Image "+img+" for "+idx);
+
+			this.setGridImage(idx, img);
+
+			parent = parent.parent;
+		}
+	},
+
+	updateExpandGridColumn: function() {
+		if (!this.tree.showGrid) return;
+
+		var _this = this;
+
+		var icon = this.isLastNode() ? this.tree.blankIconSrc : this.tree.gridIconSrcV;
+
+		dojo.lang.forEach(_this.getDescendants(),
+			function(node) { node.setGridImage(_this.depth, icon); }
+		);
+
+		this.updateExpandGrid();
+	},
+
+	updateIcons: function(){
+
+
+		//dojo.profile.start("updateIcons")
+
+		//dojo.debug("Update icons for "+this)
+		//dojo.debug(this.isFolder)
+
+		this.imgs[0].style.display = this.tree.showRootGrid ? 'inline' : 'none';
+
+
+		//
+		// set the expand icon
+		//
+
+
+		//
+		// set the child icon
+		//
+		this.buildChildIcon();
+
+		this.updateExpandGrid();
+		this.updateChildGrid();
+		this.updateParentGrid();
+
+
+
+		dojo.profile.stop("updateIcons")
+
+	},
+
+	buildChildIcon: function() {
+		// IE (others?) tries to download whatever is on src attribute so setting "url()" like before isnt a good idea
+		// Only results in a 404
+		if(this.childIconSrc){
+			this.childIcon.src = this.childIconSrc;
+		}
+		this.childIcon.style.display = this.childIconSrc ? 'inline' : 'none';
+	},
+
+	setGridImage: function(idx, src){
+
+		if (idx < 0){
+			idx = this.imgs.length + idx;
+		}
+
+		//if (idx >= this.imgs.length-2) return;
+		this.imgs[idx].style.backgroundImage = 'url(' + src + ')';
+	},
+
+
+	updateIconTree: function(){
+		this.tree.updateIconTree.call(this);
+	},
+
+
+
+
+	expand: function(){
+		if (this.isExpanded) return;
+
+		if (this.children.length) {
+			this.showChildren();
+		}
+
+		this.isExpanded = true;
+
+		this.updateExpandIcon();
+
+		dojo.event.topic.publish(this.tree.eventNames.expand, {source: this} );
+	},
+
+	collapse: function(){
+		if (!this.isExpanded) return;
+
+		this.hideChildren();
+		this.isExpanded = false;
+
+		this.updateExpandIcon();
+
+		dojo.event.topic.publish(this.tree.eventNames.collapse, {source: this} );
+	},
+
+	hideChildren: function(){
+		this.tree.toggleObj.hide(
+			this.containerNode, this.toggleDuration, this.explodeSrc, dojo.lang.hitch(this, "onHide")
+		);
+
+		/* if dnd is in action, recalculate changed coordinates */
+		if(dojo.exists(dojo, 'dnd.dragManager.dragObjects') && dojo.dnd.dragManager.dragObjects.length) {
+			dojo.dnd.dragManager.cacheTargetLocations();
+		}
+	},
+
+	showChildren: function(){
+		this.tree.toggleObj.show(
+			this.containerNode, this.toggleDuration, this.explodeSrc, dojo.lang.hitch(this, "onShow")
+		);
+
+		/* if dnd is in action, recalculate changed coordinates */
+		if(dojo.exists(dojo, 'dnd.dragManager.dragObjects') && dojo.dnd.dragManager.dragObjects.length) {
+			dojo.dnd.dragManager.cacheTargetLocations();
+		}
+	},
+
+	addChild: function(){
+		return this.tree.addChild.apply(this, arguments);
+	},
+
+	doAddChild: function(){
+		return this.tree.doAddChild.apply(this, arguments);
+	},
+
+
+
+	/* Edit current node : change properties and update contents */
+	edit: function(props) {
+		dojo.lang.mixin(this, props);
+		if (props.title) {
+			this.titleNode.innerHTML = this.title;
+		}
+
+		if (props.afterLabel) {
+			this.afterLabelNode.innerHTML = this.afterLabel;
+		}
+
+		if (props.childIconSrc) {
+			this.buildChildIcon();
+		}
+
+
+	},
+
+
+	removeNode: function(){ return this.tree.removeNode.apply(this, arguments) },
+	doRemoveNode: function(){ return this.tree.doRemoveNode.apply(this, arguments) },
+
+
+	toString: function() {
+		return "["+this.widgetType+" Tree:"+this.tree+" ID:"+this.widgetId+" Title:"+this.title+"]";
+
+	}
+
+});
+
+
+
+

Added: tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/TreeRPCController.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/TreeRPCController.js?rev=413300&view=auto
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/TreeRPCController.js (added)
+++ tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/TreeRPCController.js Sat Jun 10 06:59:28 2006
@@ -0,0 +1,171 @@
+/*
+	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.TreeRPCController");
+
+dojo.require("dojo.event.*");
+dojo.require("dojo.json")
+dojo.require("dojo.io.*");
+dojo.require("dojo.widget.TreeLoadingController");
+
+dojo.widget.tags.addParseTreeHandler("dojo:TreeRPCController");
+
+dojo.widget.TreeRPCController = function(){
+	dojo.widget.TreeLoadingController.call(this);
+}
+
+dojo.inherits(dojo.widget.TreeRPCController, dojo.widget.TreeLoadingController);
+
+dojo.lang.extend(dojo.widget.TreeRPCController, {
+	widgetType: "TreeRPCController",
+
+	/**
+	 * Make request to server about moving children.
+	 *
+	 * Request returns "true" if move succeeded,
+	 * object with error field if failed
+	 *
+	 * I can't leave DragObject floating until async request returns, need to return false/true
+	 * so making it sync way...
+	 *
+	 * Also, "loading" icon is not shown until function finishes execution, so no indication for remote request.
+	*/
+	doMove: function(child, newParent, index){
+
+		//if (newParent.isTreeNode) newParent.markLoading();
+
+		var params = {
+			// where from
+			child: this.getInfo(child),
+			childTree: this.getInfo(child.tree),
+			// where to
+			newParent: this.getInfo(newParent),
+			newParentTree: this.getInfo(newParent.tree),
+			newIndex: index
+		};
+
+		var success;
+
+		this.runRPC({		
+			url: this.getRPCUrl('move'),
+			/* I hitch to get this.loadOkHandler */
+			load: function(response){
+				success = this.doMoveProcessResponse(response, child, newParent, index) ;
+			},
+			sync: true,
+			lock: [child, newParent],
+			params: params
+		});
+
+
+		return success;
+	},
+
+	doMoveProcessResponse: function(response, child, newParent, index){
+
+		if(!dojo.lang.isUndefined(response.error)){
+			this.RPCErrorHandler("server", response.error);
+			return false;
+		}
+
+		var args = [child, newParent, index];
+		return dojo.widget.TreeLoadingController.prototype.doMove.apply(this, args);
+
+	},
+
+
+	doRemoveNode: function(node, callObj, callFunc){
+
+		var params = {
+			node: this.getInfo(node),
+			tree: this.getInfo(node.tree)
+		}
+
+		this.runRPC({
+				url: this.getRPCUrl('removeNode'),
+				/* I hitch to get this.loadOkHandler */
+				load: function(response){
+					this.doRemoveNodeProcessResponse(response, node, callObj, callFunc) 
+				},
+				params: params,
+				lock: [node]
+		});
+
+	},
+
+
+	doRemoveNodeProcessResponse: function(response, node, callObj, callFunc){
+		if(!dojo.lang.isUndefined(response.error)){
+			this.RPCErrorHandler("server", response.error);
+			return false;
+		}
+
+		if(!response){ return false; }
+
+		if(response == true){
+			/* change parent succeeded */
+			var args = [ node, callObj, callFunc ];
+			dojo.widget.TreeLoadingController.prototype.doRemoveNode.apply(this, args);
+
+			return;
+		}else if(dojo.lang.isObject(response)){
+			dojo.raise(response.error);
+		}else{
+			dojo.raise("Invalid response "+response)
+		}
+
+
+	},
+
+
+
+	// -----------------------------------------------------------------------------
+	//                             Create node stuff
+	// -----------------------------------------------------------------------------
+
+
+	doCreateChild: function(parent, index, output, callObj, callFunc){
+
+			var params = {
+				tree: this.getInfo(parent.tree),
+				parent: this.getInfo(parent),
+				index: index,
+				data: output
+			}
+
+			this.runRPC({
+				url: this.getRPCUrl('createChild'),
+				load: function(response) {
+					// suggested data is dead, fresh data from server is used
+					this.doCreateChildProcessResponse( response, parent, index, callObj, callFunc) 
+				},
+				params: params,
+				lock: [parent]
+			});
+
+	},
+
+	doCreateChildProcessResponse: function(response, parent, index, callObj, callFunc){
+
+		if(!dojo.lang.isUndefined(response.error)){
+			this.RPCErrorHandler("server",response.error);
+			return false;
+		}
+
+		if(!dojo.lang.isObject(response)){
+			dojo.raise("Invalid result "+response)
+		}
+
+		var args = [parent, index, response, callObj, callFunc];
+		
+		dojo.widget.TreeLoadingController.prototype.doCreateChild.apply(this, args);
+	}
+});

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

Added: tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/__package__.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/__package__.js?rev=413300&view=auto
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/__package__.js (added)
+++ tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/__package__.js Sat Jun 10 06:59:28 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/framework/src/js/dojo/src/widget/__package__.js
------------------------------------------------------------------------------
    svn:eol-style = native

Added: tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/demoEngine/DemoContainer.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/demoEngine/DemoContainer.js?rev=413300&view=auto
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/demoEngine/DemoContainer.js (added)
+++ tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/demoEngine/DemoContainer.js Sat Jun 10 06:59:28 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/framework/src/js/dojo/src/widget/demoEngine/DemoContainer.js
------------------------------------------------------------------------------
    svn:eol-style = native

Added: tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/demoEngine/DemoPane.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/demoEngine/DemoPane.js?rev=413300&view=auto
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/demoEngine/DemoPane.js (added)
+++ tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/demoEngine/DemoPane.js Sat Jun 10 06:59:28 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/framework/src/js/dojo/src/widget/demoEngine/DemoPane.js
------------------------------------------------------------------------------
    svn:eol-style = native

Added: tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/demoEngine/__package__.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/demoEngine/__package__.js?rev=413300&view=auto
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/demoEngine/__package__.js (added)
+++ tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/demoEngine/__package__.js Sat Jun 10 06:59:28 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/framework/src/js/dojo/src/widget/demoEngine/__package__.js
------------------------------------------------------------------------------
    svn:eol-style = native

Added: tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/demoEngine/templates/DemoNavigator.css
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/demoEngine/templates/DemoNavigator.css?rev=413300&view=auto
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/demoEngine/templates/DemoNavigator.css (added)
+++ tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/demoEngine/templates/DemoNavigator.css Sat Jun 10 06:59:28 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/framework/src/js/dojo/src/widget/demoEngine/templates/DemoNavigator.css
------------------------------------------------------------------------------
    svn:eol-style = native

Added: tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/demoEngine/templates/DemoPane.css
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/demoEngine/templates/DemoPane.css?rev=413300&view=auto
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/demoEngine/templates/DemoPane.css (added)
+++ tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/demoEngine/templates/DemoPane.css Sat Jun 10 06:59:28 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/framework/src/js/dojo/src/widget/demoEngine/templates/DemoPane.css
------------------------------------------------------------------------------
    svn:eol-style = native

Added: tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/demoEngine/templates/SourcePane.css
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/demoEngine/templates/SourcePane.css?rev=413300&view=auto
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/demoEngine/templates/SourcePane.css (added)
+++ tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/demoEngine/templates/SourcePane.css Sat Jun 10 06:59:28 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/framework/src/js/dojo/src/widget/demoEngine/templates/SourcePane.css
------------------------------------------------------------------------------
    svn:eol-style = native

Added: tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/demoEngine/templates/general.css
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/demoEngine/templates/general.css?rev=413300&view=auto
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/demoEngine/templates/general.css (added)
+++ tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/demoEngine/templates/general.css Sat Jun 10 06:59:28 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/framework/src/js/dojo/src/widget/demoEngine/templates/general.css
------------------------------------------------------------------------------
    svn:eol-style = native

Added: tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/html/Button2.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/html/Button2.js?rev=413300&view=auto
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/html/Button2.js (added)
+++ tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/html/Button2.js Sat Jun 10 06:59:28 2006
@@ -0,0 +1,25 @@
+/*
+	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
+*/
+
+// this is a stub that will be removed in 0.4, see ../Button2.html for details
+
+dojo.provide("dojo.widget.html.Button2");
+
+dojo.widget.html.Button2 = function(){}
+dojo.inherits(dojo.widget.html.Button2, dojo.widget.html.Button);
+dojo.lang.extend(dojo.widget.html.Button2, { widgetType: "Button2" });
+
+dojo.widget.html.DropDownButton2 = function(){}
+dojo.inherits(dojo.widget.html.DropDownButton2, dojo.widget.html.DropDownButton);
+dojo.lang.extend(dojo.widget.html.DropDownButton2, { widgetType: "DropDownButton2" });
+
+dojo.widget.html.ComboButton2 = function(){}
+dojo.inherits(dojo.widget.html.ComboButton2, dojo.widget.html.ComboButton);
+dojo.lang.extend(dojo.widget.html.ComboButton2, { widgetType: "ComboButton2" });
\ No newline at end of file

Added: tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/html/Checkbox.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/html/Checkbox.js?rev=413300&view=auto
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/html/Checkbox.js (added)
+++ tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/html/Checkbox.js Sat Jun 10 06:59:28 2006
@@ -0,0 +1,109 @@
+/*
+	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.Checkbox");
+
+dojo.require("dojo.widget.*");
+dojo.require("dojo.event");
+dojo.require("dojo.html");
+
+// FIXME: the input doesn't get taken out of the tab list (i think)
+// FIXME: the image doesn't get into the tab list (needs to steal the tabindex value from the input)
+
+dojo.widget.defineWidget(
+	"dojo.widget.html.Checkbox",
+	dojo.widget.HtmlWidget,
+	{
+		widgetType: "Checkbox",
+	
+		_testImg: null,
+	
+		_events: [
+			"onclick",
+			"onfocus",
+			"onblur",
+			"onselect",
+			"onchange",
+			"onclick",
+			"ondblclick",
+			"onmousedown",
+			"onmouseup",
+			"onmouseover",
+			"onmousemove",
+			"onmouseout",
+			"onkeypress",
+			"onkeydown",
+			"onkeyup"
+		],
+	
+		srcOn: dojo.uri.dojoUri('src/widget/templates/check_on.gif'),
+		srcOff: dojo.uri.dojoUri('src/widget/templates/check_off.gif'),
+		disabled: "enabled",
+	
+		fillInTemplate: function(){
+	
+			// FIXME: if images are disabled, we DON'T want to swap out the element
+			// we can use the usual 'load image to check' trick
+			// i don't know what image we can check yet, so we'll skip this for now...
+	
+			// this._testImg = document.createElement("img");
+			// document.body.appendChild(this._testImg);
+			// this._testImg.src = "spacer.gif?cachebust=" + new Date().valueOf();
+			// dojo.connect(this._testImg, 'onload', this, 'onImagesLoaded');
+	
+			this.onImagesLoaded();
+		},
+	
+		onImagesLoaded: function(){
+	
+			// FIXME: if we actually check for loading images, remove the thing here
+			// document.body.removeChild(this._testImg);
+	
+			// 'hide' the checkbox
+			this.domNode.style.position = "absolute";
+			this.domNode.style.left = "-9000px";
+	
+			// create a replacement image
+			this.imgNode = document.createElement("img");
+			dojo.html.addClass(this.imgNode, "dojoHtmlCheckbox");
+			this.updateImgSrc();
+			dojo.event.connect(this.imgNode, 'onclick', this, 'onClick');
+			dojo.event.connect(this.domNode, 'onchange', this, 'onChange');
+			this.domNode.parentNode.insertBefore(this.imgNode, this.domNode.nextSibling)
+	
+			// real ugly - make sure the image has all the events that the checkbox did
+			for(var i=0; i<this._events.length; i++){
+				if(this.domNode[this._events[i]]){
+					dojo.event.connect(	this.imgNode, this._events[i], 
+										this.domNode[this._events[i]]);
+				}
+			}
+		},
+	
+		onClick: function(){
+			if(this.disabled == "enabled"){
+				this.domNode.checked = !this.domNode.checked ? true : false;
+				this.updateImgSrc();
+			}
+		},
+	
+		onChange: function(){
+			if(this.disabled == "enabled"){
+				this.updateImgSrc();
+			}
+		},
+	
+		updateImgSrc: function(){
+	
+			this.imgNode.src = this.domNode.checked ? this.srcOn : this.srcOff;
+		}
+	}
+);
+

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

Added: tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/html/ContentPane.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/html/ContentPane.js?rev=413300&view=auto
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/html/ContentPane.js (added)
+++ tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/html/ContentPane.js Sat Jun 10 06:59:28 2006
@@ -0,0 +1,519 @@
+/*
+	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.ContentPane");
+
+dojo.require("dojo.widget.*");
+dojo.require("dojo.io.*");
+dojo.require("dojo.widget.HtmlWidget");
+dojo.require("dojo.widget.ContentPane");
+dojo.require("dojo.string");
+dojo.require("dojo.string.extras");
+dojo.require("dojo.style");
+
+dojo.widget.html.ContentPane = function(){
+	dojo.widget.HtmlWidget.call(this);
+}
+dojo.inherits(dojo.widget.html.ContentPane, dojo.widget.HtmlWidget);
+
+dojo.lang.extend(dojo.widget.html.ContentPane, {
+	widgetType: "ContentPane",
+	isContainer: true,
+
+	// remote loading options
+	href: "",
+	extractContent: true,
+	parseContent: true,
+	cacheContent: true,
+	preload: false,			// force load of data even if pane is hidden
+	refreshOnShow: false,
+	handler: "",			// generate pane content from a java function
+	executeScripts: false,	// if true scripts in content will be evaled after content is set and parsed
+	scriptScope: null,		// scopeContainer for downloaded scripts
+
+		// If the user want a global in the remote script he/she just omitts the var
+		// examples:
+		//--------------------------
+		// these gets collected by scriptScope and is reached by dojo.widget.byId('..').scriptScope.myCustomproperty
+		//	this.myString = "dojo is a great javascript toolkit!";
+		//
+		//	this.alertMyString = function(){
+		//		alert(myString);
+		//	}
+		// -------------------------
+		// these go into the global namespace (window) notice lack of var, equiv to window.myString
+		//	myString = "dojo is a javascript toolkit!";
+		//
+		//	alertMyString = function(){
+		//		alert(myString);
+		// }
+
+
+	// private
+	_remoteStyles: null,	// array of stylenodes inserted to document head
+							// by remote content, used when we clean up for new content
+
+	_callOnUnLoad: false,		// used by setContent and _handleDefults, makes sure onUnLoad is only called once
+
+
+	postCreate: function(args, frag, parentComp){
+		if ( this.handler != "" ){
+			this.setHandler(this.handler);
+		}
+		if(this.isShowing()||this.preload){ this.loadContents(); }
+	},
+
+	show: function(){
+		// if refreshOnShow is true, reload the contents every time; otherwise, load only the first time
+		if(this.refreshOnShow){
+			this.refresh();
+		}else{
+			this.loadContents();
+		}
+		dojo.widget.html.ContentPane.superclass.show.call(this);
+	},
+
+	refresh: function(){
+		this.isLoaded=false;
+		this.loadContents();
+	},
+
+	loadContents: function() {
+		if ( this.isLoaded ){
+			return;
+		}
+		this.isLoaded=true;
+		if ( dojo.lang.isFunction(this.handler)) {
+			this._runHandler();
+		} else if ( this.href != "" ) {
+			this._downloadExternalContent(this.href, this.cacheContent);
+		}
+	},
+
+	
+	setUrl: function(/*String*/ url) {
+		// summary:
+		// 	Reset the (external defined) content of this pane and replace with new url
+		this.href = url;
+		this.isLoaded = false;
+		if ( this.preload || this.isShowing() ){
+			this.loadContents();
+		}
+	},
+
+	_downloadExternalContent: function(url, useCache) {
+		this._handleDefaults("Loading...", "onDownloadStart");
+		var self = this;
+		dojo.io.bind({
+			url: url,
+			useCache: useCache,
+			preventCache: !useCache,
+			mimetype: "text/html",
+			handler: function(type, data, e) {
+				if(type == "load") {
+					self.onDownloadEnd.call(self, url, data);
+				} else {
+					// works best when from a live server instead of from file system
+					self._handleDefaults.call(self, "Error loading '" + url + "' (" + e.status + " "+  e.statusText + ")", "onDownloadError");
+					self.onLoad();
+				}
+			}
+		});
+	},
+
+	// called when setContent is finished
+	onLoad: function(e){ /*stub*/ },
+
+	// called before old content is cleared
+	onUnLoad: function(e){ 
+			this.scriptScope = null;
+	},
+
+	destroy: function(){
+		// make sure we call onUnLoad
+		this.onUnLoad();
+		dojo.widget.html.ContentPane.superclass.destroy.call(this);
+	},
+
+	// called when content script eval error or Java error occurs, preventDefault-able
+	onExecError: function(e){ /*stub*/ },
+
+	// called on DOM faults, require fault etc in content, preventDefault-able
+	onContentError: function(e){ /*stub*/ },
+
+	// called when download error occurs, preventDefault-able
+	onDownloadError: function(e){ /*stub*/ },
+
+	// called before download starts, preventDefault-able
+	onDownloadStart: function(e){ /*stub*/ },
+
+	// called when download is finished
+	onDownloadEnd: function(url, data){
+		data = this.splitAndFixPaths(data, url);
+		this.setContent(data);
+	},
+
+	// usefull if user wants to prevent default behaviour ie: _setContent("Error...")
+	_handleDefaults: function(e, handler, useAlert){
+		if(!handler){ handler = "onContentError"; }
+		if(dojo.lang.isString(e)){
+			e = {
+				"text": e,
+				"toString": function(){ return this.text; }
+			}
+		}
+		if(typeof e.returnValue != "boolean"){
+			e.returnValue = true; 
+		}
+		if(typeof e.preventDefault != "function"){
+			e.preventDefault = function(){
+				this.returnValue = false;
+			}
+		}
+		// call our handler
+		this[handler](e);
+		if(e.returnValue){
+			if(useAlert){
+				alert(e.toString());
+			}else{
+				if(this._callOnUnLoad){
+					this.onUnLoad(); // makes sure scripts can clean up after themselves, before we setContent
+				}
+				this._callOnUnLoad = false; // makes sure we dont try to call onUnLoad again on this event,
+											// ie onUnLoad before 'Loading...' but not before clearing 'Loading...'
+				this._setContent(e.toString());
+			}
+		}
+	},
+
+	
+	splitAndFixPaths: function(/*String*/s, /*dojo.uri.Uri?*/url){
+		// summary:
+		// 	fixes all remote paths in (hopefully) all cases for example images, remote scripts, links etc.
+		// 	splits up content in different pieces, scripts, title, style, link and whats left becomes .xml
+
+		if(!url) { url = "./"; } // point to this page if not set
+		if(!s) { return ""; }
+
+		// fix up paths in data
+		var titles = []; var scripts = []; var linkStyles = [];
+		var styles = []; var remoteScripts = []; var requires = [];
+
+		// khtml is much more picky about dom faults, you can't for example attach a style node under body of document
+		// must go into head, as does a title node, so we need to cut out those tags
+		// cut out title tags
+		var match = [];
+		while(match){
+			match = s.match(/<title[^>]*>([\s\S]*?)<\/title>/i); // can't match with dot as that 
+			if(!match){ break;}					//doesnt match newline in js
+			titles.push(match[1]);
+			s = s.replace(/<title[^>]*>[\s\S]*?<\/title>/i, "");
+		}
+
+		// cut out <style> url(...) </style>, as that bails out in khtml
+		var match = [];
+		while(match){
+			match = s.match(/<style[^>]*>([\s\S]*?)<\/style>/i);
+			if(!match){ break; }
+			styles.push(dojo.style.fixPathsInCssText(match[1], url));
+			s = s.replace(/<style[^>]*?>[\s\S]*?<\/style>/i, "");
+		}
+
+		// attributepaths one tag can have multiple paths example:
+		// <input src="..." style="url(..)"/> or <a style="url(..)" href="..">
+		// strip out the tag and run fix on that.
+		// this guarantees that we won't run replace another tag's attribute + it was easier do
+		var pos = 0; var pos2 = 0; var stop = 0 ;var str = ""; var fixedPath = "";
+		var attr = []; var fix = ""; var tagFix = ""; var tag = ""; var regex = ""; 
+		while(pos>-1){
+			pos = s.search(/<[a-z][a-z0-9]*[^>]*\s(?:(?:src|href|style)=[^>])+[^>]*>/i);
+			if(pos==-1){ break; }
+			str += s.substring(0, pos);
+			s = s.substring(pos, s.length);
+			tag = s.match(/^<[a-z][a-z0-9]*[^>]*>/i)[0];
+			s = s.substring(tag.length, s.length);
+
+			// loop through attributes
+			pos2 = 0; tagFix = ""; fix = ""; regex = ""; var regexlen = 0;
+			while(pos2!=-1){
+				// slices up before next attribute check, values from previous loop
+				tagFix += tag.substring(0, pos2) + fix;
+				tag = tag.substring(pos2+regexlen, tag.length);
+
+				// fix next attribute or bail out when done
+				// hopefully this charclass covers most urls
+				attr = tag.match(/ (src|href|style)=(['"]?)([\w()\[\]\/.,\\'"-:;#=&?\s@]+?)\2/i);
+				if(!attr){ break; }
+
+				switch(attr[1].toLowerCase()){
+					case "src":// falltrough
+					case "href":
+						// this hopefully covers most common protocols
+						if(attr[3].search(/^(?:[#]|(?:(?:https?|ftps?|file|javascript|mailto|news):))/)==-1){
+							fixedPath = (new dojo.uri.Uri(url, attr[3]).toString());
+						} else {
+							pos2 = pos2 + attr[3].length;
+							continue;
+						}
+						break;
+					case "style":// style
+						fixedPath = dojo.style.fixPathsInCssText(attr[3], url);
+						break;
+					default:
+						pos2 = pos2 + attr[3].length;
+						continue;
+				}
+
+				regex = " " + attr[1] + "=" + attr[2] + attr[3] + attr[2];
+				regexlen = regex.length;
+				fix = " " + attr[1] + "=" + attr[2] + fixedPath + attr[2];
+				pos2 = tag.search(new RegExp(dojo.string.escapeRegExp(regex)));
+			}
+			str += tagFix + tag;
+			pos = 0; // reset for next mainloop
+		}
+		s = str+s;
+
+		// cut out all script tags, push them into scripts array
+		match = []; var tmp = [];
+		while(match){
+			match = s.match(/<script([^>]*)>([\s\S]*?)<\/script>/i);
+			if(!match){ break; }
+			if(match[1]){
+				attr = match[1].match(/src=(['"]?)([^"']*)\1/i);
+				if(attr){
+					// remove a dojo.js or dojo.js.uncompressed.js from remoteScripts
+					// we declare all files with dojo.js as bad, regardless of folder
+					var tmp = attr[2].search(/.*(\bdojo\b(?:\.uncompressed)?\.js)$/);
+					if(tmp > -1){
+						dojo.debug("Security note! inhibit:"+attr[2]+" from  beeing loaded again.");
+					}else{
+						remoteScripts.push(attr[2]);
+					}
+				}
+			}
+			if(match[2]){
+				// strip out all djConfig variables from script tags nodeValue
+				// this is ABSOLUTLY needed as reinitialize djConfig after dojo is initialised
+				// makes a dissaster greater than Titanic, update remove writeIncludes() to
+				var sc = match[2].replace(/(?:var )?\bdjConfig\b(?:[\s]*=[\s]*\{[^}]+\}|\.[\w]*[\s]*=[\s]*[^;\n]*)?;?|dojo\.hostenv\.writeIncludes\(\s*\);?/g, "");
+				if(!sc){ continue; }
+
+				// cut out all dojo.require (...) calls, if we have execute 
+				// scripts false widgets dont get there require calls
+				// does suck out possible widgetpackage registration as well
+				tmp = [];
+				while(tmp && requires.length<100){
+					tmp = sc.match(/dojo\.(?:(?:require(?:After)?(?:If)?)|(?:widget\.(?:manager\.)?registerWidgetPackage)|(?:(?:hostenv\.)?setModulePrefix))\((['"]).*?\1\)\s*;?/);
+					if(!tmp){ break;}
+					requires.push(tmp[0]);
+					sc = sc.replace(tmp[0], "");
+				}
+				scripts.push(sc);
+			}
+			s = s.replace(/<script[^>]*>[\s\S]*?<\/script>/i, "");
+		}
+
+		// scan for scriptScope in html eventHandlers and replace with link to this pane
+		if(this.executeScripts){
+			var regex = /(<[a-zA-Z][a-zA-Z0-9]*\s[^>]*\S=(['"])[^>]*[^\.\]])scriptScope([^>]*>)/;
+			var pos = 0;var str = "";match = [];var cit = "";
+			while(pos > -1){
+				pos = s.search(regex);
+				if(pos > -1){
+					cit = ((RegExp.$2=="'") ? '"': "'");
+					str += s.substring(0, pos);
+					s = s.substr(pos).replace(regex, "$1dojo.widget.byId("+ cit + this.widgetId + cit + ").scriptScope$3");
+				}
+			}
+			s = str + s;
+		}
+
+		// cut out all <link rel="stylesheet" href="..">
+		match = [];
+		while(match){
+			match = s.match(/<link ([^>]*rel=['"]?stylesheet['"]?[^>]*)>/i);
+			if(!match){ break; }
+			attr = match[1].match(/href=(['"]?)([^'">]*)\1/i);
+			if(attr){
+				linkStyles.push(attr[2]);
+			}
+			s = s.replace(new RegExp(match[0]), "");
+		}
+
+		return {"xml": s, // Object
+			"styles": styles,
+			"linkStyles": linkStyles,
+			"titles": titles,
+			"requires": 	requires,
+			"scripts": scripts,
+			"remoteScripts": remoteScripts,
+			"url": url};
+	},
+
+	
+	_setContent: function(/*String*/ xml){
+		// summary: 
+		//		private internal function without path regExpCheck and no onLoad calls aftervards
+
+		// remove old children from current content
+		this.destroyChildren();
+
+		// remove old stylenodes from HEAD
+		if(this._remoteStyles){
+			for(var i = 0; i < this._remoteStyles.length; i++){
+				if(this._remoteStyles[i] && this._remoteStyles.parentNode){
+					this._remoteStyles[i].parentNode.removeChild(this._remoteStyles[i]);
+				}
+			}
+			this._remoteStyles = null;
+		}
+
+		var node = this.containerNode || this.domNode;
+		try{
+			if(typeof xml != "string"){
+				node.innerHTML = "";
+				node.appendChild(xml);
+			}else{
+				node.innerHTML = xml;
+			}
+		} catch(e){
+			e = "Could'nt load content:"+e;
+			this._handleDefaults(e, "onContentError");
+		}
+	},
+
+	setContent: function(/*String*/ data){
+		// summary:
+		// 	Destroys old content and setting new content, and possibly initialize any widgets within 'data'
+
+		if(this._callOnUnLoad){ // this tells a remote script clean up after itself
+			this.onUnLoad();
+		}
+		this._callOnUnLoad = true;
+
+		if(!data || dojo.dom.isNode(data)){
+			// if we do a clean using setContent(""); or setContent(#node) bypass all parseing, extractContent etc
+			this._setContent(data);
+			this.onResized();
+			this.onLoad();
+		}else{
+			// need to run splitAndFixPaths? ie. manually setting content
+			 if(!data.xml){
+				data = this.splitAndFixPaths(data);
+			}
+			if(this.extractContent) {
+				var matches = data.xml.match(/<body[^>]*>\s*([\s\S]+)\s*<\/body>/im);
+				if(matches) { data.xml = matches[1]; }
+			}
+			// insert styleNodes, from <style>....
+			for(var i = 0; i < data.styles.length; i++){
+				if(i==0){ 
+					this._remoteStyles = []; 
+				}
+				this._remoteStyles.push(dojo.style.insertCssText(data.styles[i]));
+			}
+			// insert styleNodes, from <link href="...">
+			for(var i = 0; i < data.linkStyles.length; i++){
+				if(i==0){ 
+					this._remoteStyles = []; 
+				}
+				this._remoteStyles.push(dojo.style.insertCssFile(data.linkStyles[i]));
+			}
+			this._setContent(data.xml);
+
+			if(this.parseContent){
+				for(var i = 0; i < data.requires.length; i++){
+					try{ 
+						eval(data.requires[i]);
+					} catch(e){
+						this._handleDefaults(e, "onContentError", true);
+					}
+				}
+			}
+			// need to allow async load, Xdomain uses it
+			// is inline function because we cant send args to addOnLoad function
+			var _self = this;
+			function asyncParse(){
+				if(_self.parseContent){
+					var node = _self.containerNode || _self.domNode;
+					var parser = new dojo.xml.Parse();
+					var frag = parser.parseElement(node, null, true);
+					// createSubComponents not createComponents because frag has already been created
+					dojo.widget.getParser().createSubComponents(frag, _self);
+				}
+		
+				if(_self.executeScripts){
+					_self._executeScripts(data);
+				}
+
+				_self.onResized();
+				_self.onLoad();
+			}
+			dojo.addOnLoad(asyncParse);
+		}
+	},
+
+	// Generate pane content from given java function
+	setHandler: function(handler) {
+		var fcn = dojo.lang.isFunction(handler) ? handler : window[handler];
+		if(!dojo.lang.isFunction(fcn)) {
+			// FIXME: needs testing! somebody with java knowledge needs to try this
+			this._handleDefaults("Unable to set handler, '" + handler + "' not a function.", "onExecError", true);
+			return;
+		}
+		this.handler = function() {
+			return fcn.apply(this, arguments);
+		}
+	},
+
+	_runHandler: function() {
+		if(dojo.lang.isFunction(this.handler)) {
+			this.handler(this, this.domNode);
+			return false;
+		}
+		return true;
+	},
+
+	_executeScripts: function(data) {
+		// do remoteScripts first
+		var self = this;
+		for(var i = 0; i < data.remoteScripts.length; i++){
+			dojo.io.bind({
+				"url": data.remoteScripts[i],
+				"useCash":	this.cacheContent,
+				"load":     function(type, scriptStr){
+						dojo.lang.hitch(self, data.scripts.push(scriptStr));
+				},
+				"error":    function(type, error){
+						self._handleDefaults.call(self, type + " downloading remote script", "onExecError", true);
+				},
+				"mimetype": "text/plain",
+				"sync":     true
+			});
+		}
+
+		var scripts = "";
+		for(var i = 0; i < data.scripts.length; i++){
+			scripts += data.scripts[i];
+		}
+
+		try{
+			// initialize a new anonymous container for our script, dont make it part of this widgets scope chain
+			// instead send in a variable that points to this widget, usefull to connect events to onLoad, onUnLoad etc..
+			this.scriptScope = null;
+			this.scriptScope = new (new Function('_container_', scripts+'; return this;'))(self);
+		}catch(e){
+			this._handleDefaults("Error running scripts from content:\n"+e, "onExecError", true);
+		}
+	}
+});
+
+dojo.widget.tags.addParseTreeHandler("dojo:ContentPane");

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

Added: tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/html/ContextMenu.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/html/ContextMenu.js?rev=413300&view=auto
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/html/ContextMenu.js (added)
+++ tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/html/ContextMenu.js Sat Jun 10 06:59:28 2006
@@ -0,0 +1,166 @@
+/*
+	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.ContextMenu");
+dojo.require("dojo.html");
+dojo.require("dojo.widget.HtmlWidget");
+dojo.require("dojo.widget.ContextMenu");
+dojo.require("dojo.lang");
+
+dojo.widget.html.ContextMenu = function(){
+	dojo.widget.ContextMenu.call(this);
+	dojo.widget.HtmlWidget.call(this);
+
+	this.isShowing = 0;
+	this.templatePath = dojo.uri.dojoUri("src/widget/templates/HtmlContextMenuTemplate.html");
+	this.templateCssPath = dojo.uri.dojoUri("src/widget/templates/Menu.css");
+
+	this.targetNodeIds = []; // fill this with nodeIds upon widget creation and it only responds to those nodes
+
+	// default event detection method 
+	var eventType = "oncontextmenu"; 
+
+	var doc = document.documentElement  || document.body; 
+
+	var _blockHide = false; 
+
+	this.fillInTemplate = function(args, frag){
+
+		var func = "onOpen";
+		var attached = false;
+
+		// connect with rightclick if oncontextmenu is not around
+		// NOTE: It would be very nice to have a dojo.event.browser.supportsEvent here
+		// NOTE: Opera does not have rightclick events, it is listed here only because
+		//     it bails out when connecting with oncontextmenu event
+
+		if((dojo.render.html.khtml && !dojo.render.html.safari) || (dojo.render.html.opera)){
+			eventType = "onmousedown";
+			func = "_checkRightClick";
+		}
+
+		// attach event listeners to our selected nodes
+		for(var i=0; i<this.targetNodeIds.length; i++){
+			var node = document.getElementById(this.targetNodeIds[i]);
+			if(node){
+				dojo.event.connect(node, eventType, this, func);
+				attached = true;
+			}else{
+				// remove this nodeId
+				dojo.debug("Couldent find "+this.targetNodeIds[i]+", cant do ContextMenu on this node");
+				this.targetNodeIds.splice(i,1);
+			}
+		}
+
+		// if we got attached to a node, hide on all non node contextevents
+		if(attached){ func = "_canHide"; }
+
+		dojo.event.connect(doc, eventType, this, func);
+	}
+
+	this.onOpen = function(evt){
+		// if (this.isShowing){ this.onHide(evt); } // propably not needed
+		this.isShowing = 1;
+
+		// if I do this, I cant preventDefault in khtml
+		//evt = dojo.event.browser.fixEvent(evt);
+ 
+		// stop default contextmenu, needed in khtml
+		if (evt.preventDefault){ evt.preventDefault(); }
+
+		// need to light up this one before we check width and height
+		this.domNode.style.left = "-9999px";
+		this.domNode.style.top  = "-9999px";
+		this.domNode.style.display = "block";
+
+		// calculate if menu is going to apear within window
+		// or if its partially out of visable area
+		with(dojo.html){
+
+			var menuW = getInnerWidth(this.domNode);
+			var menuH = getInnerHeight(this.domNode);
+
+			var viewport = getViewportSize();
+			var scrolloffset = getScrollOffset();
+		}
+
+		var minX = viewport[0];
+		var minY = viewport[1];
+
+		var maxX = (viewport[0] + scrolloffset[0]) - menuW;
+		var maxY = (viewport[1] + scrolloffset[1]) - menuH;
+
+		var posX = evt.clientX + scrolloffset[0];
+		var posY = evt.clientY + scrolloffset[1];
+
+		if (posX > maxX){ posX = posX - menuW; }
+		if (posY > maxY){ posY = posY - menuH; }
+
+		this.domNode.style.left = posX + "px";
+		this.domNode.style.top = posY + "px";
+
+
+		// block the onclick that follows this particular right click
+		// not if the eventtrigger is documentElement and always when
+		// we use onmousedown hack
+		_blockHide = (evt.currentTarget!=doc || eventType=='onmousedown');
+
+		//return false; // we propably doesnt need to return false as we dont stop the event as we did before
+	}
+
+	/*
+	* _canHide is meant to block the onHide call that follows the event that triggered
+	* onOpen. This is (hopefully) faster that event.connect and event.disconnect every
+	* time the code executes and it makes connecting with onmousedown event possible
+	* and we dont have to stop the event from bubbling further.
+	*
+	* this code is moved into a separete function because it makes it possible for the
+	* user to connect to a onHide event, if anyone would like that.
+	*/
+
+	this._canHide = function(evt){
+		// block the onclick that follows the same event that turn on contextmenu
+		if(_blockHide){
+			// the onclick check is needed to prevent displaying multiple
+			// menus when we have 2 or more contextmenus loaded and are using
+			// the onmousedown hack
+			if(evt.type=='click' || eventType=='oncontextmenu'){
+				_blockHide = false;
+				return;
+			}else{
+				return;
+			}
+		}
+
+		this.onHide(evt);
+	}
+	
+	this.onHide = function(evt){
+		// FIXME: use whatever we use to do more general style setting?
+		this.domNode.style.display = "none";
+		//dojo.event.disconnect(doc, "onclick", this, "onHide");
+		this.isShowing = 0;
+	}
+
+	// callback for rightclicks, needed for browsers that doesnt implement oncontextmenu, konqueror and more? 
+	this._checkRightClick = function(evt){ 
+
+		// for some reason konq comes here even when we are not clicking on the attached nodes 
+		// added check for targetnode 
+		if (evt.button==2 && (this.targetNodeIds.length==0 || (evt.currentTarget.id!="" && dojo.lang.inArray(this.targetNodeIds, evt.currentTarget.id)))){
+
+			return this.onOpen(evt);
+		}
+	}
+
+	dojo.event.connect(doc, "onclick", this, "_canHide");
+}
+
+dojo.inherits(dojo.widget.html.ContextMenu, dojo.widget.HtmlWidget);

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

Added: tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/html/DebugConsole.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/html/DebugConsole.js?rev=413300&view=auto
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/html/DebugConsole.js (added)
+++ tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/html/DebugConsole.js Sat Jun 10 06:59:28 2006
@@ -0,0 +1,31 @@
+/*
+	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.DebugConsole");
+
+dojo.require("dojo.widget.*");
+dojo.require("dojo.widget.FloatingPane");
+
+dojo.widget.html.DebugConsole= function(){
+
+	dojo.widget.html.FloatingPane.call(this);
+	dojo.widget.DebugConsole.call(this);
+}
+
+dojo.inherits(dojo.widget.html.DebugConsole, dojo.widget.html.FloatingPane);
+
+dojo.lang.extend(dojo.widget.html.DebugConsole, {
+	fillInTemplate: function() {
+		dojo.widget.html.DebugConsole.superclass.fillInTemplate.apply(this, arguments);
+		this.containerNode.id = "debugConsoleClientPane";
+		djConfig.isDebug = true;
+		djConfig.debugContainerId = this.containerNode.id;
+	}
+});

Added: tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/html/DropdownButton.js
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/html/DropdownButton.js?rev=413300&view=auto
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/html/DropdownButton.js (added)
+++ tapestry/tapestry4/trunk/framework/src/js/dojo/src/widget/html/DropdownButton.js Sat Jun 10 06:59:28 2006
@@ -0,0 +1,186 @@
+/*
+	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
+*/
+
+/* TODO:
+ * - make the dropdown "smart" so it can't get cutoff on bottom of page, sides of page, etc.
+ */
+
+dojo.provide("dojo.widget.html.DropdownButton");
+
+dojo.require("dojo.event.*");
+dojo.require("dojo.widget.*");
+dojo.require("dojo.widget.HtmlWidget");
+dojo.require("dojo.uri.Uri");
+dojo.require("dojo.dom");
+dojo.require("dojo.style");
+dojo.require("dojo.html");
+
+dojo.widget.html.DropdownButton = function() {
+	// mix in the button properties
+	dojo.widget.DropdownButton.call(this);
+	dojo.widget.HtmlWidget.call(this);
+}
+
+dojo.inherits(dojo.widget.html.DropdownButton, dojo.widget.HtmlWidget);
+
+dojo.lang.extend(dojo.widget.html.DropdownButton, {
+	
+	// In IE, event handlers on objects inside buttons don't work correctly, so
+	// we just set onClick on the button itself.
+	templatePath: dojo.uri.dojoUri("src/widget/templates/HtmlDropDownButtonTemplate.html"),
+	templateCssPath: dojo.uri.dojoUri("src/widget/templates/HtmlButtonTemplate.css"),
+
+	// attach points
+	button: null,
+	table: null,
+	labelCell: null,
+	borderCell: null,
+	arrowCell: null,
+	arrow: null,
+
+	fillInTemplate: function(args, frag) {
+		// input data (containing the anchor for the button itself, plus the
+		// thing to display when you push the down arrow)
+		var input = frag["dojo:"+this.widgetType.toLowerCase()]["nodeRef"];
+
+		// Recursively expand widgets inside of the <dojo:dropdownButton>
+		var parser = new dojo.xml.Parse();
+		var frag = parser.parseElement(input, null, true);
+		var ary = dojo.widget.getParser().createComponents(frag);
+
+		this.a = dojo.dom.getFirstChildElement(input);	// the button contents
+		this.menu = dojo.dom.getNextSiblingElement(this.a);	// the menu under the button
+		
+		this.disabled = dojo.html.hasClass(this.a, "disabled");
+		if( this.disabled ) {
+			dojo.html.addClass(this.button, "dojoDisabled");
+			this.domNode.setAttribute("disabled", "true");
+		}
+
+		dojo.html.disableSelection(this.a);
+		this.a.style["text-decoration"]="none";
+		this.labelCell.appendChild(this.a);
+
+		this.arrow.src =
+			dojo.uri.dojoUri("src/widget/templates/images/dropdownButtonsArrow" +
+			(this.disabled ? "-disabled" : "") + ".gif");
+
+		// Attach menu to body so that it appears above other buttons
+		this.menu.style.position="absolute";
+		this.menu.style.display="none";
+		this.menu.style["z-index"] = 99;
+		document.body.appendChild(this.menu);
+	},
+
+	postCreate: function() {
+		if ( dojo.render.html.ie ) {
+			// Compensate for IE's weird padding of button content, which seems to be relative
+			// to the length of the content
+			var contentWidth = dojo.style.getOuterWidth(this.table);
+			this.labelCell.style["left"] = "-" + (contentWidth / 10) + "px";
+			this.arrowCell.style["left"] = (contentWidth / 10) + "px";
+		}
+
+		// Make menu at least as wide as the button
+		var buttonWidth = dojo.style.getOuterWidth(this.button);
+		var menuWidth = dojo.style.getOuterWidth(this.menu);
+		if ( buttonWidth > menuWidth ) {
+			dojo.style.setOuterWidth(this.menu, buttonWidth);
+		}
+	},
+
+	// If someone clicks anywhere else on the screen (including another menu),
+	// then close this menu.
+	onCanvasMouseDown: function(e) {
+		if( !dojo.dom.isDescendantOf(e.target, this.button) &&
+			!dojo.dom.isDescendantOf(e.target, this.menu) ) {
+			this.hideMenu();
+		}
+	},
+
+	eventWasOverArrow: function(e) {
+		// want to use dojo.html.overElement() but also need to detect clicks
+		// on the area between the arrow and the edge of the button
+		var eventX = e.clientX;
+		var borderX = dojo.style.totalOffsetLeft(this.borderCell);
+		return (eventX > borderX );
+	},
+
+	onMouseOver: function(e) {
+		dojo.html.addClass(this.button, "dojoButtonHover");
+		dojo.html.removeClass(this.button, "dojoButtonNoHover");
+	},
+	
+	onMouseOut: function(e) {
+		dojo.html.removeClass(this.button, "dojoButtonHover");
+		dojo.html.addClass(this.button, "dojoButtonNoHover");
+	},
+
+	onClick: function(e) {
+		if ( this.eventWasOverArrow(e) ) {
+			this._onClickArrow();
+		} else {
+			this._onClickButton();
+		}
+	},
+
+	// Action when the user presses the button
+	_onClickButton: function(e) {
+		if ( this.a ) {
+			if ( this.a.click ) {
+				this.a.click();
+			} else if ( this.a.href ) {
+				location.href = this.a.href;
+			}
+		}
+	},
+
+	// Action when user presses the arrow
+	_onClickArrow: function() {
+		if ( this.menu.style.display == "none" ) {
+			this.showMenu();
+		} else {
+			this.hideMenu();
+		}
+	},
+	
+	showMenu: function() {
+		if ( this.disabled )
+			return;
+
+		// Position it accordingly, relative to screen root (since
+		// it's attached to document.body)
+		this.menu.style.left = dojo.style.totalOffsetLeft(this.button) + "px";
+		this.menu.style.top = dojo.style.totalOffsetTop(this.button) + dojo.style.getOuterHeight(this.button) + "px";
+
+		// Display the menu; do this funky code below to stop the menu from extending
+		// all the way to the right edge of the screen.
+		// TODO: retest simple display="" to confirm that it doesn't work.
+		try {
+			this.menu.style.display="table";	// mozilla
+		} catch(e) {
+			this.menu.style.display="block";	// IE
+		}
+
+		// If someone clicks somewhere else on the screen then close the menu
+		dojo.event.connect(document.documentElement, "onmousedown", this, "onCanvasMouseDown");
+		
+		// When someone clicks the menu, after the menu handles the event,
+		// close the menu (be careful not to close the menu too early or else
+		// the menu will never receive the event.)
+		dojo.event.connect(this.menu, "onclick", this, "hideMenu");
+	},
+
+	hideMenu: function() {
+		this.menu.style.display = "none";
+		dojo.event.disconnect(document.documentElement, "onmousedown", this, "onCanvasMouseDown");
+		dojo.event.disconnect(this.menu, "onclick", this, "hideMenu");
+	}
+});