You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tapestry.apache.org by jk...@apache.org on 2006/02/16 00:31:07 UTC

svn commit: r378118 [18/23] - in /jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/html/dojo: ./ src/ src/alg/ src/animation/ src/collections/ src/crypto/ src/data/ src/dnd/ src/event/ src/flash/ src/flash/flash6/ src/flash/flash8/ src/fx/...

Added: jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/widget/Toolbar.js
URL: http://svn.apache.org/viewcvs/jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/widget/Toolbar.js?rev=378118&view=auto
==============================================================================
--- jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/widget/Toolbar.js (added)
+++ jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/widget/Toolbar.js Wed Feb 15 15:30:01 2006
@@ -0,0 +1,960 @@
+/*
+	Copyright (c) 2004-2005, 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.ToolbarContainer");
+dojo.provide("dojo.widget.html.ToolbarContainer");
+dojo.provide("dojo.widget.Toolbar");
+dojo.provide("dojo.widget.html.Toolbar");
+dojo.provide("dojo.widget.ToolbarItem");
+dojo.provide("dojo.widget.html.ToolbarButtonGroup");
+dojo.provide("dojo.widget.html.ToolbarButton");
+dojo.provide("dojo.widget.html.ToolbarDialog");
+dojo.provide("dojo.widget.html.ToolbarMenu");
+dojo.provide("dojo.widget.html.ToolbarSeparator");
+dojo.provide("dojo.widget.html.ToolbarSpace");
+dojo.provide("dojo.widget.Icon");
+
+dojo.require("dojo.widget.*");
+dojo.require("dojo.html");
+
+/* ToolbarContainer
+ *******************/
+dojo.widget.html.ToolbarContainer = function() {
+	dojo.widget.HtmlWidget.call(this);
+
+	this.widgetType = "ToolbarContainer";
+	this.isContainer = true;
+
+	this.templateString = '<div class="toolbarContainer" dojoAttachPoint="containerNode"></div>';
+	this.templateCssPath = dojo.uri.dojoUri("src/widget/templates/HtmlToolbar.css");
+
+	this.getItem = function(name) {
+		if(name instanceof dojo.widget.ToolbarItem) { return name; }
+		for(var i = 0; i < this.children.length; i++) {
+			var child = this.children[i];
+			if(child instanceof dojo.widget.html.Toolbar) {
+				var item = child.getItem(name);
+				if(item) { return item; }
+			}
+		}
+		return null;
+	}
+
+	this.getItems = function() {
+		var items = [];
+		for(var i = 0; i < this.children.length; i++) {
+			var child = this.children[i];
+			if(child instanceof dojo.widget.html.Toolbar) {
+				items = items.concat(child.getItems());
+			}
+		}
+		return items;
+	}
+
+	this.enable = function() {
+		for(var i = 0; i < this.children.length; i++) {
+			var child = this.children[i];
+			if(child instanceof dojo.widget.html.Toolbar) {
+				child.enable.apply(child, arguments);
+			}
+		}
+	}
+
+	this.disable = function() {
+		for(var i = 0; i < this.children.length; i++) {
+			var child = this.children[i];
+			if(child instanceof dojo.widget.html.Toolbar) {
+				child.disable.apply(child, arguments);
+			}
+		}
+	}
+
+	this.select = function(name) {
+		for(var i = 0; i < this.children.length; i++) {
+			var child = this.children[i];
+			if(child instanceof dojo.widget.html.Toolbar) {
+				child.select(arguments);
+			}
+		}
+	}
+
+	this.deselect = function(name) {
+		for(var i = 0; i < this.children.length; i++) {
+			var child = this.children[i];
+			if(child instanceof dojo.widget.html.Toolbar) {
+				child.deselect(arguments);
+			}
+		}
+	}
+
+	this.getItemsState = function() {
+		var values = {};
+		for(var i = 0; i < this.children.length; i++) {
+			var child = this.children[i];
+			if(child instanceof dojo.widget.html.Toolbar) {
+				dojo.lang.mixin(values, child.getItemsState());
+			}
+		}
+		return values;
+	}
+
+	this.getItemsActiveState = function() {
+		var values = {};
+		for(var i = 0; i < this.children.length; i++) {
+			var child = this.children[i];
+			if(child instanceof dojo.widget.html.Toolbar) {
+				dojo.lang.mixin(values, child.getItemsActiveState());
+			}
+		}
+		return values;
+	}
+
+	this.getItemsSelectedState = function() {
+		var values = {};
+		for(var i = 0; i < this.children.length; i++) {
+			var child = this.children[i];
+			if(child instanceof dojo.widget.html.Toolbar) {
+				dojo.lang.mixin(values, child.getItemsSelectedState());
+			}
+		}
+		return values;
+	}
+}
+dojo.inherits(dojo.widget.html.ToolbarContainer, dojo.widget.HtmlWidget);
+dojo.widget.tags.addParseTreeHandler("dojo:toolbarContainer");
+
+/* Toolbar
+ **********/
+dojo.widget.html.Toolbar = function() {
+	dojo.widget.HtmlWidget.call(this);
+
+	this.widgetType = "Toolbar";
+	this.isContainer = true;
+
+	this.templateString = '<div class="toolbar" dojoAttachPoint="containerNode" unselectable="on" dojoOnMouseover="_onmouseover" dojoOnMouseout="_onmouseout" dojoOnClick="_onclick" dojoOnMousedown="_onmousedown" dojoOnMouseup="_onmouseup"></div>';
+	//this.templateString = '<div class="toolbar" dojoAttachPoint="containerNode" unselectable="on"></div>';
+
+	// given a node, tries to find it's toolbar item
+	this._getItem = function(node) {
+		var start = new Date();
+		var widget = null;
+		while(node && node != this.domNode) {
+			if(dojo.html.hasClass(node, "toolbarItem")) {
+				var widgets = dojo.widget.manager.getWidgetsByFilter(function(w) { return w.domNode == node; });
+				if(widgets.length == 1) {
+					widget = widgets[0];
+					break;
+				} else if(widgets.length > 1) {
+					dojo.raise("Toolbar._getItem: More than one widget matches the node");
+				}
+			}
+			node = node.parentNode;
+		}
+		return widget;
+	}
+
+	this._onmouseover = function(e) {
+		var widget = this._getItem(e.target);
+		if(widget && widget._onmouseover) { widget._onmouseover(e); }
+	}
+
+	this._onmouseout = function(e) {
+		var widget = this._getItem(e.target);
+		if(widget && widget._onmouseout) { widget._onmouseout(e); }
+	}
+
+	this._onclick = function(e) {
+		var widget = this._getItem(e.target);
+		if(widget && widget._onclick){ 
+			widget._onclick(e);
+		}
+	}
+
+	this._onmousedown = function(e) {
+		var widget = this._getItem(e.target);
+		if(widget && widget._onmousedown) { widget._onmousedown(e); }
+	}
+
+	this._onmouseup = function(e) {
+		var widget = this._getItem(e.target);
+		if(widget && widget._onmouseup) { widget._onmouseup(e); }
+	}
+
+	var oldAddChild = this.addChild;
+	this.addChild = function(item, pos, props) {
+		var widget = dojo.widget.ToolbarItem.make(item, null, props);
+		var ret = oldAddChild.call(this, widget, null, pos, null);
+		return ret;
+	}
+
+	this.push = function() {
+		for(var i = 0; i < arguments.length; i++) {
+			this.addChild(arguments[i]);
+		}
+	}
+
+	this.getItem = function(name) {
+		if(name instanceof dojo.widget.ToolbarItem) { return name; }
+		for(var i = 0; i < this.children.length; i++) {
+			var child = this.children[i];
+			if(child instanceof dojo.widget.ToolbarItem
+				&& child._name == name) { return child; }
+		}
+		return null;
+	}
+
+	this.getItems = function() {
+		var items = [];
+		for(var i = 0; i < this.children.length; i++) {
+			var child = this.children[i];
+			if(child instanceof dojo.widget.ToolbarItem) {
+				items.push(child);
+			}
+		}
+		return items;
+	}
+
+	this.getItemsState = function() {
+		var values = {};
+		for(var i = 0; i < this.children.length; i++) {
+			var child = this.children[i];
+			if(child instanceof dojo.widget.ToolbarItem) {
+				values[child._name] = {
+					selected: child._selected,
+					enabled: child._enabled
+				};
+			}
+		}
+		return values;
+	}
+
+	this.getItemsActiveState = function() {
+		var values = this.getItemsState();
+		for(var item in values) {
+			values[item] = values[item].enabled;
+		}
+		return values;
+	}
+
+	this.getItemsSelectedState = function() {
+		var values = this.getItemsState();
+		for(var item in values) {
+			values[item] = values[item].selected;
+		}
+		return values;
+	}
+
+	this.enable = function() {
+		var items = arguments.length ? arguments : this.children;
+		for(var i = 0; i < items.length; i++) {
+			var child = this.getItem(items[i]);
+			if(child instanceof dojo.widget.ToolbarItem) {
+				child.enable(false, true);
+			}
+		}
+	}
+
+	this.disable = function() {
+		var items = arguments.length ? arguments : this.children;
+		for(var i = 0; i < items.length; i++) {
+			var child = this.getItem(items[i]);
+			if(child instanceof dojo.widget.ToolbarItem) {
+				child.disable();
+			}
+		}
+	}
+
+	this.select = function() {
+		for(var i = 0; i < arguments.length; i++) {
+			var name = arguments[i];
+			var item = this.getItem(name);
+			if(item) { item.select(); }
+		}
+	}
+
+	this.deselect = function() {
+		for(var i = 0; i < arguments.length; i++) {
+			var name = arguments[i];
+			var item = this.getItem(name);
+			if(item) { item.disable(); }
+		}
+	}
+
+	this.setValue = function() {
+		for(var i = 0; i < arguments.length; i += 2) {
+			var name = arguments[i], value = arguments[i+1];
+			var item = this.getItem(name);
+			if(item) {
+				if(item instanceof dojo.widget.ToolbarItem) {
+					item.setValue(value);
+				}
+			}
+		}
+	}
+}
+dojo.inherits(dojo.widget.html.Toolbar, dojo.widget.HtmlWidget);
+dojo.widget.tags.addParseTreeHandler("dojo:toolbar");
+
+/* ToolbarItem hierarchy:
+	- ToolbarItem
+		- ToolbarButton
+		- ToolbarDialog
+			- ToolbarMenu
+		- ToolbarSeparator
+			- ToolbarSpace
+				- ToolbarFlexibleSpace
+*/
+
+
+/* ToolbarItem
+ **************/
+dojo.widget.ToolbarItem = function() {
+	dojo.widget.HtmlWidget.call(this);
+}
+dojo.inherits(dojo.widget.ToolbarItem, dojo.widget.HtmlWidget);
+
+dojo.lang.extend(dojo.widget.ToolbarItem, {
+	templateString: '<span unselectable="on" class="toolbarItem"></span>',
+
+	_name: null,
+	getName: function() { return this._name; },
+	setName: function(value) { return this._name = value; },
+	getValue: function() { return this.getName(); },
+	setValue: function(value) { return this.setName(value); },
+
+	_selected: false,
+	isSelected: function() { return this._selected; },
+	setSelected: function(is, force, preventEvent) {
+		if(!this._toggleItem && !force) { return; }
+		is = Boolean(is);
+		if(force || this._enabled && this._selected != is) {
+			this._selected = is;
+			this.update();
+			if(!preventEvent) {
+				this._fireEvent(is ? "onSelect" : "onDeselect");
+				this._fireEvent("onChangeSelect");
+			}
+		}
+	},
+	select: function(force, preventEvent) {
+		return this.setSelected(true, force, preventEvent);
+	},
+	deselect: function(force, preventEvent) {
+		return this.setSelected(false, force, preventEvent);
+	},
+
+	_toggleItem: false,
+	isToggleItem: function() { return this._toggleItem; },
+	setToggleItem: function(value) { this._toggleItem = Boolean(value); },
+
+	toggleSelected: function(force) {
+		return this.setSelected(!this._selected, force);
+	},
+
+	_enabled: true,
+	isEnabled: function() { return this._enabled; },
+	setEnabled: function(is, force, preventEvent) {
+		is = Boolean(is);
+		if(force || this._enabled != is) {
+			this._enabled = is;
+			this.update();
+			if(!preventEvent) {
+				this._fireEvent(this._enabled ? "onEnable" : "onDisable");
+				this._fireEvent("onChangeEnabled");
+			}
+		}
+		return this._enabled;
+	},
+	enable: function(force, preventEvent) {
+		return this.setEnabled(true, force, preventEvent);
+	},
+	disable: function(force, preventEvent) {
+		return this.setEnabled(false, force, preventEvent);
+	},
+	toggleEnabled: function(force, preventEvent) {
+		return this.setEnabled(!this._enabled, force, preventEvent);
+	},
+
+	_icon: null,
+	getIcon: function() { return this._icon; },
+	setIcon: function(value) {
+		var icon = dojo.widget.Icon.make(value);
+		if(this._icon) {
+			this._icon.setIcon(icon);
+		} else {
+			this._icon = icon;
+		}
+		var iconNode = this._icon.getNode();
+		if(iconNode.parentNode != this.domNode) {
+			if(this.domNode.hasChildNodes()) {
+				this.domNode.insertBefore(iconNode, this.domNode.firstChild);
+			} else {
+				this.domNode.appendChild(iconNode);
+			}
+		}
+		return this._icon;
+	},
+
+	// TODO: update the label node (this.labelNode?)
+	_label: "",
+	getLabel: function() { return this._label; },
+	setLabel: function(value) {
+		var ret = this._label = value;
+		if(!this.labelNode) {
+			this.labelNode = document.createElement("span");
+			this.domNode.appendChild(this.labelNode);
+		}
+		this.labelNode.innerHTML = "";
+		this.labelNode.appendChild(document.createTextNode(this._label));
+		this.update();
+		return ret;
+	},
+
+	// fired from: setSelected, setEnabled, setLabel
+	update: function() {
+		if(this._enabled) {
+			dojo.html.removeClass(this.domNode, "disabled");
+			if(this._selected) {
+				dojo.html.addClass(this.domNode, "selected");
+			} else {
+				dojo.html.removeClass(this.domNode, "selected");
+			}
+		} else {
+			this._selected = false;
+			dojo.html.addClass(this.domNode, "disabled");
+			dojo.html.removeClass(this.domNode, "down");
+			dojo.html.removeClass(this.domNode, "hover");
+		}
+		this._updateIcon();
+	},
+
+	_updateIcon: function() {
+		if(this._icon) {
+			if(this._enabled) {
+				if(this._cssHover) {
+					this._icon.hover();
+				} else if(this._selected) {
+					this._icon.select();
+				} else {
+					this._icon.enable();
+				}
+			} else {
+				this._icon.disable();
+			}
+		}
+	},
+
+	_fireEvent: function(evt) {
+		if(typeof this[evt] == "function") {
+			var args = [this];
+			for(var i = 1; i < arguments.length; i++) {
+				args.push(arguments[i]);
+			}
+			this[evt].apply(this, args);
+		}
+	},
+
+	_onmouseover: function(e) {
+		if(!this._enabled) { return };
+		dojo.html.addClass(this.domNode, "hover");
+	},
+
+	_onmouseout: function(e) {
+		dojo.html.removeClass(this.domNode, "hover");
+		dojo.html.removeClass(this.domNode, "down");
+		if(!this._selected) {
+			dojo.html.removeClass(this.domNode, "selected");
+		}
+	},
+
+	_onclick: function(e) {
+		// FIXME: buttons never seem to have this._enabled set to true on Opera 9
+		// dojo.debug("widget:", this.widgetType, ":", this.getName(), ", enabled:", this._enabled);
+		if(this._enabled && !this._toggleItem) {
+			this._fireEvent("onClick");
+		}
+	},
+
+	_onmousedown: function(e) {
+		if(e.preventDefault) { e.preventDefault(); }
+		if(!this._enabled) { return };
+		dojo.html.addClass(this.domNode, "down");
+		if(this._toggleItem) {
+			if(this.parent.preventDeselect && this._selected) {
+				return;
+			}
+			this.toggleSelected();
+		}
+	},
+
+	_onmouseup: function(e) {
+		dojo.html.removeClass(this.domNode, "down");
+	},
+
+	fillInTemplate: function(args, frag) {
+		if(args.name) { this._name = args.name; }
+		if(args.selected) { this.select(); }
+		if(args.disabled) { this.disable(); }
+		if(args.label) { this.setLabel(args.label); }
+		if(args.icon) { this.setIcon(args.icon); }
+		if(args.toggleitem||args.toggleItem) { this.setToggleItem(true); }
+	}
+});
+
+dojo.widget.ToolbarItem.make = function(wh, whIsType, props) {
+	var item = null;
+
+	if(wh instanceof Array) {
+		item = dojo.widget.createWidget("ToolbarButtonGroup", props);
+		item.setName(wh[0]);
+		for(var i = 1; i < wh.length; i++) {
+			item.addChild(wh[i]);
+		}
+	} else if(wh instanceof dojo.widget.ToolbarItem) {
+		item = wh;
+	} else if(wh instanceof dojo.uri.Uri) {
+		item = dojo.widget.createWidget("ToolbarButton",
+			dojo.lang.mixin(props||{}, {icon: new dojo.widget.Icon(wh.toString())}));
+	} else if(whIsType) {
+		item = dojo.widget.createWidget(wh, props)
+	} else if(typeof wh == "string" || wh instanceof String) {
+		switch(wh.charAt(0)) {
+			case "|":
+			case "-":
+			case "/":
+				item = dojo.widget.createWidget("ToolbarSeparator", props);
+				break;
+			case " ":
+				if(wh.length == 1) {
+					item = dojo.widget.createWidget("ToolbarSpace", props);
+				} else {
+					item = dojo.widget.createWidget("ToolbarFlexibleSpace", props);
+				}
+				break;
+			default:
+				if(/\.(gif|jpg|jpeg|png)$/i.test(wh)) {
+					item = dojo.widget.createWidget("ToolbarButton",
+						dojo.lang.mixin(props||{}, {icon: new dojo.widget.Icon(wh.toString())}));
+				} else {
+					item = dojo.widget.createWidget("ToolbarButton",
+						dojo.lang.mixin(props||{}, {label: wh.toString()}));
+				}
+		}
+	} else if(wh && wh.tagName && /^img$/i.test(wh.tagName)) {
+		item = dojo.widget.createWidget("ToolbarButton",
+			dojo.lang.mixin(props||{}, {icon: wh}));
+	} else {
+		item = dojo.widget.createWidget("ToolbarButton",
+			dojo.lang.mixin(props||{}, {label: wh.toString()}));
+	}
+	return item;
+}
+
+/* ToolbarButtonGroup
+ *********************/
+dojo.widget.html.ToolbarButtonGroup = function() {
+	dojo.widget.ToolbarItem.call(this);
+
+	this.widgetType = "ToolbarButtonGroup";
+	this.isContainer = true;
+
+	this.templateString = '<span unselectable="on" class="toolbarButtonGroup" dojoAttachPoint="containerNode"></span>';
+
+	// if a button has the same name, it will be selected
+	// if this is set to a number, the button at that index will be selected
+	this.defaultButton = "";
+
+	var oldAddChild = this.addChild;
+	this.addChild = function(item, pos, props) {
+		var widget = dojo.widget.ToolbarItem.make(item, null, dojo.lang.mixin(props||{}, {toggleItem:true}));
+		dojo.event.connect(widget, "onSelect", this, "onChildSelected");
+		var ret = oldAddChild.call(this, widget, null, pos, null);
+		if(widget._name == this.defaultButton
+			|| (typeof this.defaultButton == "number"
+			&& this.children.length-1 == this.defaultButton)) {
+			widget.select(false, true);
+		}
+		return ret;
+	}
+
+	this.getItem = function(name) {
+		if(name instanceof dojo.widget.ToolbarItem) { return name; }
+		for(var i = 0; i < this.children.length; i++) {
+			var child = this.children[i];
+			if(child instanceof dojo.widget.ToolbarItem
+				&& child._name == name) { return child; }
+		}
+		return null;
+	}
+
+	this.getItems = function() {
+		var items = [];
+		for(var i = 0; i < this.children.length; i++) {
+			var child = this.children[i];
+			if(child instanceof dojo.widget.ToolbarItem) {
+				items.push(child);
+			}
+		}
+		return items;
+	}
+
+	this.onChildSelected = function(e) {
+		this.select(e._name);
+	}
+
+	this.enable = function(force, preventEvent) {
+		for(var i = 0; i < this.children.length; i++) {
+			var child = this.children[i];
+			if(child instanceof dojo.widget.ToolbarItem) {
+				child.enable(force, preventEvent);
+				if(child._name == this._value) {
+					child.select(force, preventEvent);
+				}
+			}
+		}
+	}
+
+	this.disable = function(force, preventEvent) {
+		for(var i = 0; i < this.children.length; i++) {
+			var child = this.children[i];
+			if(child instanceof dojo.widget.ToolbarItem) {
+				child.disable(force, preventEvent);
+			}
+		}
+	}
+
+	this._value = "";
+	this.getValue = function() { return this._value; }
+
+	this.select = function(name, force, preventEvent) {
+		for(var i = 0; i < this.children.length; i++) {
+			var child = this.children[i];
+			if(child instanceof dojo.widget.ToolbarItem) {
+				if(child._name == name) {
+					child.select(force, preventEvent);
+					this._value = name;
+				} else {
+					child.deselect(true, preventEvent);
+				}
+			}
+		}
+		if(!preventEvent) {
+			this._fireEvent("onSelect", this._value);
+			this._fireEvent("onChangeSelect", this._value);
+		}
+	}
+	this.setValue = this.select;
+
+	this.preventDeselect = false; // if true, once you select one, you can't have none selected
+}
+dojo.inherits(dojo.widget.html.ToolbarButtonGroup, dojo.widget.ToolbarItem);
+dojo.widget.tags.addParseTreeHandler("dojo:toolbarButtonGroup");
+
+/* ToolbarButton
+ ***********************/
+dojo.widget.html.ToolbarButton = function() {
+	dojo.widget.ToolbarItem.call(this);
+}
+dojo.inherits(dojo.widget.html.ToolbarButton, dojo.widget.ToolbarItem);
+dojo.widget.tags.addParseTreeHandler("dojo:toolbarButton");
+
+dojo.lang.extend(dojo.widget.html.ToolbarButton, {
+	widgetType: "ToolbarButton",
+
+	fillInTemplate: function(args, frag) {
+		dojo.widget.html.ToolbarButton.superclass.fillInTemplate.call(this, args, frag);
+		dojo.html.addClass(this.domNode, "toolbarButton");
+		if(this._icon) {
+			this.setIcon(this._icon);
+		}
+		if(this._label) {
+			this.setLabel(this._label);
+		}
+
+		if(!this._name) {
+			if(this._label) {
+				this.setName(this._label);
+			} else if(this._icon) {
+				var src = this._icon.getSrc("enabled").match(/[\/^]([^\.\/]+)\.(gif|jpg|jpeg|png)$/i);
+				if(src) { this.setName(src[1]); }
+			} else {
+				this._name = this._widgetId;
+			}
+		}
+	}
+});
+
+/* ToolbarDialog
+ **********************/
+dojo.widget.html.ToolbarDialog = function() {
+	dojo.widget.html.ToolbarButton.call(this);
+}
+dojo.inherits(dojo.widget.html.ToolbarDialog, dojo.widget.html.ToolbarButton);
+dojo.widget.tags.addParseTreeHandler("dojo:toolbarDialog");
+
+dojo.lang.extend(dojo.widget.html.ToolbarDialog, {
+	widgetType: "ToolbarDialog",
+	
+	fillInTemplate: function (args, frag) {
+		dojo.widget.html.ToolbarDialog.superclass.fillInTemplate.call(this, args, frag);
+		dojo.event.connect(this, "onSelect", this, "showDialog");
+		dojo.event.connect(this, "onDeselect", this, "hideDialog");
+	},
+	
+	showDialog: function (e) {
+		dojo.lang.setTimeout(dojo.event.connect, 1, document, "onmousedown", this, "deselect");
+	},
+	
+	hideDialog: function (e) {
+		dojo.event.disconnect(document, "onmousedown", this, "deselect");
+	}
+
+});
+
+/* ToolbarMenu
+ **********************/
+dojo.widget.html.ToolbarMenu = function() {
+	dojo.widget.html.ToolbarDialog.call(this);
+
+	this.widgetType = "ToolbarMenu";
+}
+dojo.inherits(dojo.widget.html.ToolbarMenu, dojo.widget.html.ToolbarDialog);
+dojo.widget.tags.addParseTreeHandler("dojo:toolbarMenu");
+
+/* ToolbarMenuItem
+ ******************/
+dojo.widget.ToolbarMenuItem = function() {
+}
+
+/* ToolbarSeparator
+ **********************/
+dojo.widget.html.ToolbarSeparator = function() {
+	dojo.widget.ToolbarItem.call(this);
+
+	this.widgetType = "ToolbarSeparator";
+	this.templateString = '<span unselectable="on" class="toolbarItem toolbarSeparator"></span>';
+
+	this.defaultIconPath = new dojo.uri.dojoUri("src/widget/templates/buttons/-.gif");
+
+	var oldFillInTemplate = this.fillInTemplate;
+	this.fillInTemplate = function(args, frag, skip) {
+		oldFillInTemplate.call(this, args, frag);
+		this._name = this.widgetId;
+		if(!skip) {
+			if(!this._icon) {
+				this.setIcon(this.defaultIconPath);
+			}
+			this.domNode.appendChild(this._icon.getNode());
+		}
+	}
+
+	// don't want events!
+	this._onmouseover = this._onmouseout = this._onclick
+		= this._onmousedown = this._onmouseup = null;
+}
+dojo.inherits(dojo.widget.html.ToolbarSeparator, dojo.widget.ToolbarItem);
+dojo.widget.tags.addParseTreeHandler("dojo:toolbarSeparator");
+
+/* ToolbarSpace
+ **********************/
+dojo.widget.html.ToolbarSpace = function() {
+	dojo.widget.html.ToolbarSeparator.call(this);
+
+	this.widgetType = "ToolbarSpace";
+
+	var oldFillInTemplate = this.fillInTemplate;
+	this.fillInTemplate = function(args, frag, skip) {
+		oldFillInTemplate.call(this, args, frag, true);
+		if(!skip) {
+			dojo.html.addClass(this.domNode, "toolbarSpace");
+		}
+	}
+}
+dojo.inherits(dojo.widget.html.ToolbarSpace, dojo.widget.html.ToolbarSeparator);
+dojo.widget.tags.addParseTreeHandler("dojo:toolbarSpace");
+
+/* ToolbarSelect
+ ******************/
+ 
+/*dojo.widget.html.ToolbarSelect = function() {
+	dojo.widget.html.ToolbarDialog.call(this);
+
+	// fix inheritence chain
+	for (var method in this.constructor.prototype) {
+		this[method] = this.constructor.prototype[method];
+	}
+}
+dojo.inherits(dojo.widget.html.ToolbarSelect, dojo.widget.html.ToolbarDialog);
+dojo.widget.tags.addParseTreeHandler("dojo:toolbarSelect");
+
+dojo.lang.extend(dojo.widget.html.ToolbarSelect, {
+	widgetType: "ToolbarSelect",
+	
+	fillInTemplate: function (args, frag) {
+		dojo.widget.html.ToolbarSelect.superclass.fillInTemplate.call(this, args, frag);
+		
+		this.dialog = document.createElement("ul");
+		for(var value in args.values) {
+			var li = document.createElement("li");
+			li.value = args.values[value];
+			li.appendChild(document.createTextNode(value));
+			this.dialog.appendChild(li);
+		}
+	},
+	
+	showDialog: function (e) {
+		dojo.widget.html.ToolbarSelect.superclass.showDialog.call(this, e);
+		with (dojo.html) {
+			var x = getAbsoluteX(this.domNode);
+			var y = getAbsoluteY(this.domNode) + getInnerHeight(this.domNode);
+		}
+		with (this.domNode.style) { top = y + "px"; left = x + "px"; }
+		document.body.appendChild(this.dialog);
+	},
+	
+	hideDialog: function (e) {
+		dojo.widget.html.ToolbarSelect.superclass.hideDialog.call(this, e);
+		this.dialog.parentNode.removeChild(this.dialog);
+	}
+
+});*/
+
+dojo.widget.html.ToolbarSelect = function() {
+	dojo.widget.ToolbarItem.call(this);
+	this.widgetType = "ToolbarSelect";
+	this.templateString = '<span class="toolbarItem toolbarSelect" unselectable="on"><select dojoAttachPoint="selectBox" dojoOnChange="changed"></select></span>';
+
+	var oldFillInTemplate = this.fillInTemplate;
+	this.fillInTemplate = function(args, frag) {
+		oldFillInTemplate.call(this, args, frag, true);
+		var keys = args.values;
+		var i = 0;
+		for(var val in keys) {
+			var opt = document.createElement("option");
+			opt.setAttribute("value", keys[val]);
+			opt.innerHTML = val;
+			this.selectBox.appendChild(opt);
+		}
+	}
+
+	this.changed = function(e) {
+		this._fireEvent("onSetValue", this.selectBox.value);
+	}
+
+	var oldSetEnabled = this.setEnabled;
+	this.setEnabled = function(is, force, preventEvent) {
+		var ret = oldSetEnabled.call(this, is, force, preventEvent);
+		this.selectBox.disabled = !this._enabled;
+		return ret;
+	}
+
+	// don't want events!
+	this._onmouseover = this._onmouseout = this._onclick
+		= this._onmousedown = this._onmouseup = null;
+}
+dojo.inherits(dojo.widget.html.ToolbarSelect, dojo.widget.ToolbarItem);
+dojo.widget.tags.addParseTreeHandler("dojo:toolbarSelect");
+
+/* Icon
+ *********/
+// arguments can be IMG nodes, Image() instances or URLs -- enabled is the only one required
+dojo.widget.Icon = function(enabled, disabled, hover, selected) {
+	if(arguments.length == 0) {
+		throw new Error("Icon must have at least an enabled state");
+	}
+	var states = ["enabled", "disabled", "hover", "selected"];
+	var currentState = "enabled";
+	var domNode = document.createElement("img");
+
+	this.getState = function() { return currentState; }
+	this.setState = function(value) {
+		if(dojo.lang.inArray(value, states)) {
+			if(this[value]) {
+				currentState = value;
+				domNode.setAttribute("src", this[currentState].src);
+			}
+		} else {
+			throw new Error("Invalid state set on Icon (state: " + value + ")");
+		}
+	}
+
+	this.setSrc = function(state, value) {
+		if(/^img$/i.test(value.tagName)) {
+			this[state] = value;
+		} else if(typeof value == "string" || value instanceof String
+			|| value instanceof dojo.uri.Uri) {
+			this[state] = new Image();
+			this[state].src = value.toString();
+		}
+		return this[state];
+	}
+
+	this.setIcon = function(icon) {
+		for(var i = 0; i < states.length; i++) {
+			if(icon[states[i]]) {
+				this.setSrc(states[i], icon[states[i]]);
+			}
+		}
+		this.update();
+	}
+
+	this.enable = function() { this.setState("enabled"); }
+	this.disable = function() { this.setState("disabled"); }
+	this.hover = function() { this.setState("hover"); }
+	this.select = function() { this.setState("selected"); }
+
+	this.getSize = function() {
+		return {
+			width: domNode.width||domNode.offsetWidth,
+			height: domNode.height||domNode.offsetHeight
+		};
+	}
+
+	this.setSize = function(w, h) {
+		domNode.width = w;
+		domNode.height = h;
+		return { width: w, height: h };
+	}
+
+	this.getNode = function() {
+		return domNode;
+	}
+
+	this.getSrc = function(state) {
+		if(state) { return this[state].src; }
+		return domNode.src||"";
+	}
+
+	this.update = function() {
+		this.setState(currentState);
+	}
+
+	for(var i = 0; i < states.length; i++) {
+		var arg = arguments[i];
+		var state = states[i];
+		this[state] = null;
+		if(!arg) { continue; }
+		this.setSrc(state, arg);
+	}
+
+	this.enable();
+}
+
+dojo.widget.Icon.make = function(a,b,c,d) {
+	for(var i = 0; i < arguments.length; i++) {
+		if(arguments[i] instanceof dojo.widget.Icon) {
+			return arguments[i];
+		} else if(!arguments[i]) {
+			nullArgs++;
+		}
+	}
+
+	return new dojo.widget.Icon(a,b,c,d);
+}

Added: jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/widget/Tooltip.js
URL: http://svn.apache.org/viewcvs/jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/widget/Tooltip.js?rev=378118&view=auto
==============================================================================
--- jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/widget/Tooltip.js (added)
+++ jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/widget/Tooltip.js Wed Feb 15 15:30:01 2006
@@ -0,0 +1,24 @@
+/*
+	Copyright (c) 2004-2005, 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.Tooltip");
+dojo.require("dojo.widget.Widget");
+
+dojo.widget.tags.addParseTreeHandler("dojo:tooltip");
+
+dojo.widget.Tooltip = function(){
+	dojo.widget.Widget.call(this);
+
+	this.widgetType = "Tooltip";
+	this.isContainer = true;
+}
+dojo.inherits(dojo.widget.Tooltip, dojo.widget.Widget);
+
+dojo.requireAfterIf("html", "dojo.widget.html.Tooltip");

Added: jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/widget/Tree.js
URL: http://svn.apache.org/viewcvs/jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/widget/Tree.js?rev=378118&view=auto
==============================================================================
--- jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/widget/Tree.js (added)
+++ jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/widget/Tree.js Wed Feb 15 15:30:01 2006
@@ -0,0 +1,512 @@
+/*
+	Copyright (c) 2004-2005, 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.Tree");
+dojo.provide("dojo.widget.HtmlTree");
+dojo.provide("dojo.widget.TreeNode");
+dojo.provide("dojo.widget.HtmlTreeNode");
+
+dojo.require("dojo.event.*");
+dojo.require("dojo.fx.html");
+dojo.require("dojo.widget.HtmlWidget");
+
+// make it a tag
+dojo.widget.tags.addParseTreeHandler("dojo:Tree");
+dojo.widget.tags.addParseTreeHandler("dojo:TreeNode");
+
+dojo.widget.HtmlTree = function() {
+	dojo.widget.HtmlWidget.call(this);
+}
+dojo.inherits(dojo.widget.HtmlTree, dojo.widget.HtmlWidget);
+
+dojo.lang.extend(dojo.widget.HtmlTree, {
+	widgetType: "Tree",
+	isContainer: true,
+
+	templateCssPath: dojo.uri.dojoUri("src/widget/templates/Tree.css"),
+	templateString: '<div class="dojoTree"></div>',
+
+	selectedNode: null,
+
+	//
+	// these icons control the grid and expando buttons for the whole tree
+	//
+
+	blankIconSrc: dojo.uri.dojoUri("src/widget/templates/images/treenode_blank.gif").toString(),
+
+	gridIconSrcT: dojo.uri.dojoUri("src/widget/templates/images/treenode_grid_t.gif").toString(), // for non-last child grid
+	gridIconSrcL: dojo.uri.dojoUri("src/widget/templates/images/treenode_grid_l.gif").toString(), // for last child grid
+	gridIconSrcV: dojo.uri.dojoUri("src/widget/templates/images/treenode_grid_v.gif").toString(), // vertical line
+	gridIconSrcP: dojo.uri.dojoUri("src/widget/templates/images/treenode_grid_p.gif").toString(), // for under parent item child icons
+	gridIconSrcC: dojo.uri.dojoUri("src/widget/templates/images/treenode_grid_c.gif").toString(), // for under child item child icons
+	gridIconSrcX: dojo.uri.dojoUri("src/widget/templates/images/treenode_grid_x.gif").toString(), // grid for sole root item
+	gridIconSrcY: dojo.uri.dojoUri("src/widget/templates/images/treenode_grid_y.gif").toString(), // grid for last rrot item
+	gridIconSrcZ: dojo.uri.dojoUri("src/widget/templates/images/treenode_grid_z.gif").toString(), // for under root parent item child icon
+
+	expandIconSrcPlus: dojo.uri.dojoUri("src/widget/templates/images/treenode_expand_plus.gif").toString(),
+	expandIconSrcMinus: dojo.uri.dojoUri("src/widget/templates/images/treenode_expand_minus.gif").toString(),
+
+	iconWidth: 18,
+	iconHeight: 18,
+
+
+	//
+	// tree options
+	//
+
+	showGrid: true,
+	showRootGrid: true,
+
+	toggle: "default",
+	toggleDuration: 150,
+
+
+	//
+	// subscribable events
+	//
+
+	publishSelectionTopic: "",
+	publishExpandedTopic: "",
+	publishCollapsedTopic: "",
+
+
+	initialize: function(args, frag){
+		switch (this.toggle) {
+			case "fade": this.toggler = new dojo.widget.Tree.FadeToggle(); break;
+			case "wipe": this.toggler = new dojo.widget.Tree.WipeToggle(); break;
+			default    : this.toggler = new dojo.widget.Tree.DefaultToggle();
+		}
+	},
+
+	postCreate: function(){
+		this.buildTree();
+	},
+
+	buildTree: function(){
+
+		dojo.html.disableSelection(this.domNode);
+
+		for(var i=0; i<this.children.length; i++){
+
+			this.children[i].isFirstNode = (i == 0) ? true : false;
+			this.children[i].isLastNode = (i == this.children.length-1) ? true : false;
+
+			var node = this.children[i].buildNode(this, 0);
+
+			this.domNode.appendChild(node);
+		}
+
+
+		//
+		// when we don't show root toggles, we need to auto-expand root nodes
+		//
+
+		if (!this.showRootGrid){
+			for(var i=0; i<this.children.length; i++){
+				this.children[i].expand();
+			}
+		}
+
+		for(var i=0; i<this.children.length; i++){
+			this.children[i].startMe();
+		}
+	},
+
+	addChild: function(child){
+
+		//
+		// this function gets called to add nodes to both trees and nodes, so it's a little confusing :)
+		//
+
+		if (child.widgetType != 'TreeNode'){
+			dojo.raise("You can only add TreeNode widgets to a "+this.widgetType+" widget!");
+			return;
+		}
+
+		if (this.children.length){
+
+			var lastChild = this.children[this.children.length-1];
+			lastChild.isLastNode = false;
+			lastChild.updateIconTree();
+		}else{
+
+			if (this.widgetType == 'TreeNode'){
+				this.isParent = true;
+				this.isExpanded = false;
+				this.updateIcons();
+			}
+
+			child.isFirstNode = true;
+		}
+
+
+
+		if (this.widgetType == 'TreeNode'){
+
+			var childDepth = this.depth+1;
+			var childTree = this.tree;
+
+			child.parentNode = this;
+			child.isLastNode = true;
+
+		}else{
+			var childDepth = 0;
+			var childTree = this;
+
+			child.isLastNode = true;
+		}
+
+		this.children.push(child);
+		var node = child.buildNode(childTree, childDepth);
+
+		if (this.widgetType == 'Tree'){
+			this.domNode.appendChild(node);
+		}else{
+			this.containerNode.appendChild(node);
+		}
+
+		child.startMe();
+	}
+});
+
+
+dojo.widget.HtmlTreeNode = function() {
+	dojo.widget.HtmlWidget.call(this);
+}
+
+dojo.inherits(dojo.widget.HtmlTreeNode, dojo.widget.HtmlWidget);
+
+dojo.lang.extend(dojo.widget.HtmlTreeNode, {
+	widgetType: "TreeNode",
+	isContainer: true,
+	messWithMyChildren: true,
+
+	domNode: null,
+	continerNode: null,
+
+	templateString: '<div class="dojoTreeNode"><div dojoAttachPoint="containerNode"></div></div>',
+
+	childIconSrc: '',
+
+	childIcon: null,
+	underChildIcon: null,
+	expandIcon: null,
+
+	title: "",
+
+	labelNode: null, // the item label
+	imgs: null, // an array of icons imgs
+	rowNode: null, // the tr
+
+	tree: null,
+	parentNode: null,
+	depth: 0,
+
+	isFirstNode: false,
+	isLastNode: false,
+	isExpanded: false,
+	isParent: false,
+	booted: false,
+
+	buildNode: function(tree, depth){
+
+		this.tree = tree;
+		this.depth = depth;
+
+
+		//
+		// add the tree icons
+		//
+
+		this.imgs = [];
+
+		for(var i=0; i<this.depth+2; i++){
+
+			var img = document.createElement('img');
+
+			img.style.width = this.tree.iconWidth + 'px';
+			img.style.height = this.tree.iconHeight + 'px';
+			img.src = this.tree.blankIconSrc;
+			img.style.verticalAlign = 'middle';
+
+			this.domNode.insertBefore(img, this.containerNode);
+
+			this.imgs.push(img);
+		}
+
+		this.expandIcon = this.imgs[this.imgs.length-2];
+		this.childIcon = this.imgs[this.imgs.length-1];
+
+
+		//
+		// add the cell label
+		//
+
+
+		this.labelNode = document.createElement('span');
+
+		this.labelNode.appendChild(document.createTextNode(this.title));
+
+		this.domNode.insertBefore(this.labelNode, this.containerNode);
+
+		dojo.html.addClass(this.labelNode, 'dojoTreeNodeLabel');
+
+
+		dojo.event.connect(this.expandIcon, 'onclick', this, 'onTreeClick');
+		dojo.event.connect(this.childIcon, 'onclick', this, 'onIconClick');
+		dojo.event.connect(this.labelNode, 'onclick', this, 'onLabelClick');
+
+
+		//
+		// create the child rows
+		//
+
+		for(var i=0; i<this.children.length; i++){
+
+			this.children[i].isFirstNode = (i == 0) ? true : false;
+			this.children[i].isLastNode = (i == this.children.length-1) ? true : false;
+			this.children[i].parentNode = this;
+			var node = this.children[i].buildNode(this.tree, this.depth+1);
+
+			this.containerNode.appendChild(node);
+		}
+
+		this.isParent = (this.children.length > 0) ? true : false;
+
+		this.collapse();
+
+		return this.domNode;
+	},
+
+	onTreeClick: function(e){
+
+		if (this.isExpanded){
+			this.collapse();
+		}else{
+			this.expand();
+		}
+	},
+
+	onIconClick: function(){
+		this.onLabelClick();
+	},
+
+	onLabelClick: function(){
+
+		if (this.tree.selectedNode == this){
+
+			//this.editInline();
+			dojo.debug('TODO: start inline edit here!');
+			return;
+		}
+
+		if (this.tree.selectedNode){ this.tree.selectedNode.deselect(); }
+
+		this.tree.selectedNode = this;
+		this.tree.selectedNode.select();
+	},
+
+	select: function(){
+
+		dojo.html.addClass(this.labelNode, 'dojoTreeNodeLabelSelected');
+
+		dojo.event.topic.publish(this.tree.publishSelectionTopic, this.widgetId);
+	},
+
+	deselect: function(){
+
+		dojo.html.removeClass(this.labelNode, 'dojoTreeNodeLabelSelected');
+	},
+
+	updateIcons: function(){
+
+		this.imgs[0].style.display = this.tree.showRootGrid ? 'inline' : 'none';
+
+
+		//
+		// set the expand icon
+		//
+
+		if (this.isParent){
+			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
+		//
+
+		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 child icon
+		//
+
+		if (this.childIconSrc){
+			this.childIcon.style.display = 'inline';
+			this.childIcon.src = this.childIconSrc;
+		}else{
+			this.childIcon.style.display = 'none';
+		}
+
+
+		//
+		// set the grid under the child icon
+		//
+
+		if ((this.depth || this.tree.showRootGrid) && this.tree.showGrid){
+
+			this.setGridImage(-1, (this.isParent && this.isExpanded) ? this.tree.gridIconSrcP : this.tree.gridIconSrcC);
+		}else{
+			if (this.tree.showGrid && !this.tree.showRootGrid){
+
+				this.setGridImage(-1, (this.isParent && this.isExpanded) ? this.tree.gridIconSrcZ : this.tree.blankIconSrc);
+			}else{
+				this.setGridImage(-1, this.tree.blankIconSrc);
+			}
+		}
+
+
+		//
+		// set the vertical grid icons
+		//
+
+		var parent = this.parentNode;
+
+		for(var i=0; i<this.depth; i++){
+
+			var idx = this.imgs.length-(3+i);
+
+			this.setGridImage(idx, (this.tree.showGrid && !parent.isLastNode) ? this.tree.gridIconSrcV : this.tree.blankIconSrc);
+
+			parent = parent.parentNode;
+		}
+
+	},
+
+	setGridImage: function(idx, src){
+
+		if (idx < 0){
+			idx = this.imgs.length + idx;
+		}
+
+		this.imgs[idx].style.backgroundImage = 'url(' + src + ')';
+	},
+
+	updateIconTree: function(){
+
+		this.updateIcons();
+
+		for(var i=0; i<this.children.length; i++){
+			this.children[i].updateIconTree();
+		}
+	},
+
+	expand: function(){
+		this.showChildren();
+		this.isExpanded = true;
+		this.updateIcons();
+	},
+
+	collapse: function(){
+		this.hideChildren();
+		this.isExpanded = false;
+		this.updateIcons();
+	},
+
+	hideChildren: function(){
+
+		if (this.booted){
+			this.tree.toggler.hide(this.containerNode);
+		}else{
+			this.containerNode.style.display = 'none';
+		}
+		dojo.event.topic.publish(this.tree.publishCollapsedTopic, this.widgetId);
+	},
+
+	showChildren: function(){
+
+		if (this.booted){
+			this.tree.toggler.show(this.containerNode);
+		}else{
+			this.containerNode.style.display = 'block';
+		}
+		dojo.event.topic.publish(this.tree.publishExpandedTopic, this.widgetId);
+	},
+
+	startMe: function(){
+
+		this.booted = true;
+		for(var i=0; i<this.children.length; i++){
+			this.children[i].startMe();
+		}
+	},
+
+	addChild: function(child){
+
+		this.tree.addChild.call(this, child);
+	}
+
+});
+
+dojo.widget.Tree.DefaultToggle = function(){
+
+	this.show = function(node){
+		node.style.display = 'block';
+	}
+
+	this.hide = function(node){
+		node.style.display = 'none';
+	}
+}
+
+dojo.widget.Tree.FadeToggle = function(duration){
+	this.toggleDuration = duration ? duration : 150;
+
+	this.show = function(node){
+		node.style.display = 'block';
+		dojo.fx.html.fade(node, this.toggleDuration, 0, 1);
+	}
+
+	this.hide = function(node){
+		dojo.fx.html.fadeOut(node, this.toggleDuration, function(node){ node.style.display = 'none'; });
+	}
+}
+
+dojo.widget.Tree.WipeToggle = function(duration){
+	this.toggleDuration = duration ? duration : 150;
+
+	this.show = function(node){
+		node.style.display = 'block';
+		dojo.fx.html.wipeIn(node, this.toggleDuration);
+	}
+
+	this.hide = function(node){
+		dojo.fx.html.wipeOut(node, this.toggleDuration, function(node){ node.style.display = 'none'; });
+	}
+}
+
+

Added: jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/widget/Widget.js
URL: http://svn.apache.org/viewcvs/jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/widget/Widget.js?rev=378118&view=auto
==============================================================================
--- jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/widget/Widget.js (added)
+++ jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/widget/Widget.js Wed Feb 15 15:30:01 2006
@@ -0,0 +1,498 @@
+/*
+	Copyright (c) 2004-2005, 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.widget.Manager");
+dojo.require("dojo.event.*");
+
+dojo.widget.Widget = function(){
+	// these properties aren't primitives and need to be created on a per-item
+	// basis.
+	this.children = [];
+	// this.selection = new dojo.widget.Selection();
+	// FIXME: need to replace this with context menu stuff
+	this.extraArgs = {};
+}
+// FIXME: need to be able to disambiguate what our rendering context is
+//        here!
+
+// needs to be a string with the end classname. Every subclass MUST
+// over-ride.
+dojo.lang.extend(dojo.widget.Widget, {
+	// base widget properties
+	parent: null,
+	// obviously, top-level and modal widgets should set these appropriately
+	isTopLevel:  false,
+	isModal: false,
+
+	isEnabled: true,
+	isHidden: false,
+	isContainer: false, // can we contain other widgets?
+	widgetId: "",
+	widgetType: "Widget", // used for building generic widgets
+
+	toString: function() {
+		return '[Widget ' + this.widgetType + ', ' + (this.widgetId || 'NO ID') + ']';
+	},
+
+	repr: function(){
+		return this.toString();
+	},
+
+	enable: function(){
+		// should be over-ridden
+		this.isEnabled = true;
+	},
+
+	disable: function(){
+		// should be over-ridden
+		this.isEnabled = false;
+	},
+
+	hide: function(){
+		// should be over-ridden
+		this.isHidden = true;
+	},
+
+	show: function(){
+		// should be over-ridden
+		this.isHidden = false;
+	},
+
+	onResized: function(){
+		// Clients should override this function to do special processing,
+		// then call this.notifyChildrenOfResize() to notify children of resize
+		this.notifyChildrenOfResize();
+	},
+	
+	notifyChildrenOfResize: function(){
+		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(args, fragment, parentComp){
+		// dojo.debug(this.widgetType, "create");
+		this.satisfyPropertySets(args, fragment, parentComp);
+		// dojo.debug(this.widgetType, "-> mixInProperties");
+		this.mixInProperties(args, fragment, parentComp);
+		// dojo.debug(this.widgetType, "-> postMixInProperties");
+		this.postMixInProperties(args, fragment, parentComp);
+		// dojo.debug(this.widgetType, "-> dojo.widget.manager.add");
+		dojo.widget.manager.add(this);
+		// dojo.debug(this.widgetType, "-> buildRendering");
+		this.buildRendering(args, fragment, parentComp);
+		// dojo.debug(this.widgetType, "-> initialize");
+		this.initialize(args, fragment, parentComp);
+		// dojo.debug(this.widgetType, "-> postInitialize");
+		this.postInitialize(args, fragment, parentComp);
+		// dojo.debug(this.widgetType, "-> postCreate");
+		this.postCreate(args, fragment, parentComp);
+		// dojo.debug(this.widgetType, "done!");
+		return this;
+	},
+
+	// Destroy this widget and it's descendants
+	destroy: function(finalize){
+		// FIXME: this is woefully incomplete
+		this.destroyChildren();
+		this.uninitialize();
+		this.destroyRendering(finalize);
+		dojo.widget.manager.removeById(this.widgetId);
+	},
+
+	// Destroy the children of this widget, and their descendents
+	destroyChildren: function(){
+		while(this.children.length > 0){
+			var tc = this.children[0];
+			this.removeChild(tc);
+			tc.destroy();
+		}
+	},
+
+	getChildrenOfType: function(type, recurse){
+		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;
+	},
+
+	getDescendants: function(){
+		// FIXME: this does not appear to be recursive. Shouldn't a function 
+		// with this signature get *all* descendants?
+		var result = [];
+		var stack = [this];
+		var elem;
+		while (elem = stack.pop()){
+			result.push(elem);
+			dojo.lang.forEach(elem.children, function(elem) { stack.push(elem); });
+		}
+		return result;
+	},
+
+	satisfyPropertySets: function(args){
+		// 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(args, frag){
+		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");
+		/*
+		 * the actual mix-in code attempts to do some type-assignment based on
+		 * PRE-EXISTING properties of the "this" object. When a named property
+		 * of a propset is located, it is first tested to make sure that the
+		 * current object already "has one". Properties which are undefined in
+		 * the base widget are NOT settable here. The next step is to try to
+		 * determine type of the pre-existing property. If it's a string, the
+		 * property value is simply assigned. If a function, the property is
+		 * replaced with a "new Function()" declaration. If an Array, the
+		 * system attempts to split the string value on ";" chars, and no
+		 * further processing is attempted (conversion of array elements to a
+		 * integers, for instance). If the property value is an Object
+		 * (testObj.constructor === Object), the property is split first on ";"
+		 * chars, secondly on ":" chars, and the resulting key/value pairs are
+		 * assigned to an object in a map style. The onus is on the property
+		 * user to ensure that all property values are converted to the
+		 * expected type before usage.
+		 */
+
+		var undef;
+
+		// 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.
+						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?
+
+						// 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] = args[x];
+			}
+		}
+		// dojo.profile.end("mixInProperties");
+	},
+	
+	postMixInProperties: function(){
+	},
+
+	initialize: function(args, frag){
+		// dj_unimplemented("dojo.widget.Widget.initialize");
+		return false;
+	},
+
+	postInitialize: function(args, frag){
+		return false;
+	},
+
+	postCreate: function(args, frag){
+		return false;
+	},
+
+	uninitialize: function(){
+		// dj_unimplemented("dojo.widget.Widget.uninitialize");
+		return false;
+	},
+
+	buildRendering: function(){
+		// SUBCLASSES MUST IMPLEMENT
+		dj_unimplemented("dojo.widget.Widget.buildRendering, on "+this.toString()+", ");
+		return false;
+	},
+
+	destroyRendering: function(){
+		// SUBCLASSES MUST IMPLEMENT
+		dj_unimplemented("dojo.widget.Widget.destroyRendering");
+		return false;
+	},
+
+	cleanUp: function(){
+		// SUBCLASSES MUST IMPLEMENT
+		dj_unimplemented("dojo.widget.Widget.cleanUp");
+		return false;
+	},
+
+	addedTo: function(parent){
+		// this is just a signal that can be caught
+	},
+
+	addChild: function(child){
+		// SUBCLASSES MUST IMPLEMENT
+		dj_unimplemented("dojo.widget.Widget.addChild");
+		return false;
+	},
+
+	// Detach the given child widget from me, but don't destroy it
+	removeChild: function(widget){
+		for(var x=0; x<this.children.length; x++){
+			if(this.children[x] === widget){
+				this.children.splice(x, 1);
+				break;
+			}
+		}
+		return widget;
+	},
+
+	resize: function(width, height){
+		// both width and height may be set as percentages. The setWidth and
+		// setHeight  functions attempt to determine if the passed param is
+		// specified in percentage or native units. Integers without a
+		// measurement are assumed to be in the native unit of measure.
+		this.setWidth(width);
+		this.setHeight(height);
+	},
+
+	setWidth: function(width){
+		if((typeof width == "string")&&(width.substr(-1) == "%")){
+			this.setPercentageWidth(width);
+		}else{
+			this.setNativeWidth(width);
+		}
+	},
+
+	setHeight: function(height){
+		if((typeof height == "string")&&(height.substr(-1) == "%")){
+			this.setPercentageHeight(height);
+		}else{
+			this.setNativeHeight(height);
+		}
+	},
+
+	setPercentageHeight: function(height){
+		// SUBCLASSES MUST IMPLEMENT
+		return false;
+	},
+
+	setNativeHeight: function(height){
+		// SUBCLASSES MUST IMPLEMENT
+		return false;
+	},
+
+	setPercentageWidth: function(width){
+		// SUBCLASSES MUST IMPLEMENT
+		return false;
+	},
+
+	setNativeWidth: function(width){
+		// SUBCLASSES MUST IMPLEMENT
+		return false;
+	},
+
+	getPreviousSibling: function() {
+		var idx = this.getParentIndex();
+ 
+		 // first node is idx=0 not found is idx<0
+		if (idx<=0) return null;
+ 
+		return this.getSiblings()[idx-1];
+	},
+ 
+	getSiblings: function() {
+		return this.parent.children;
+	},
+ 
+	getParentIndex: function() {
+		return dojo.lang.indexOf( this.getSiblings(), this, true);
+	},
+ 
+	getNextSibling: function() {
+ 
+		var idx = this.getParentIndex();
+ 
+		if (idx == this.getSiblings().length-1) return null; // last node
+		if (idx < 0) return null; // not found
+ 
+		return this.getSiblings()[idx+1];
+ 
+	}
+});
+
+// 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(type){
+	var ltype = type.toLowerCase();
+	this[ltype] = function(fragment, widgetParser, parentComp, insertionIndex, localProps){ 
+		return dojo.widget.buildWidgetFromParseTree(ltype, fragment, widgetParser, parentComp, insertionIndex, localProps);
+	}
+}
+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"]);
+}
+
+dojo.widget.buildWidgetFromParseTree = function(type, frag, 
+												parser, parentComp, 
+												insertionIndex, localProps){
+	var stype = type.split(":");
+	stype = (stype.length == 2) ? stype[1] : type;
+	// FIXME: we don't seem to be doing anything with this!
+	// var propertySets = parser.getPropertySets(frag);
+	var localProperties = localProps || parser.parseProperties(frag["dojo:"+stype]);
+	// var tic = new Date();
+	var twidget = dojo.widget.manager.getImplementation(stype);
+	if(!twidget){
+		throw new Error("cannot find \"" + stype + "\" widget");
+	}else if (!twidget.create){
+		throw new Error("\"" + stype + "\" widget object does not appear to implement *Widget");
+	}
+	localProperties["dojoinsertionindex"] = insertionIndex;
+	// FIXME: we loose no less than 5ms in construction!
+	var ret = twidget.create(localProperties, frag, parentComp);
+	// dojo.debug(new Date() - tic);
+	return ret;
+}

Added: jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/widget/Wizard.js
URL: http://svn.apache.org/viewcvs/jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/widget/Wizard.js?rev=378118&view=auto
==============================================================================
--- jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/widget/Wizard.js (added)
+++ jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/widget/Wizard.js Wed Feb 15 15:30:01 2006
@@ -0,0 +1,209 @@
+/*
+	Copyright (c) 2004-2005, 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.LayoutPane");
+dojo.require("dojo.event.*");
+dojo.require("dojo.html");
+dojo.require("dojo.style");
+
+//////////////////////////////////////////
+// Wizard -- a set of panels
+//////////////////////////////////////////
+dojo.widget.Wizard = function() {
+	dojo.widget.html.LayoutPane.call(this);
+}
+dojo.inherits(dojo.widget.Wizard, dojo.widget.html.LayoutPane);
+
+dojo.lang.extend(dojo.widget.Wizard, {
+
+	widgetType: "Wizard",
+
+	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.Wizard.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();
+	}
+});
+dojo.widget.tags.addParseTreeHandler("dojo:Wizard");
+
+//////////////////////////////////////////
+// WizardPane -- a panel in a wizard
+//////////////////////////////////////////
+dojo.widget.WizardPane = function() {
+	dojo.widget.html.LayoutPane.call(this);
+}
+dojo.inherits(dojo.widget.WizardPane, dojo.widget.html.LayoutPane);
+
+dojo.lang.extend(dojo.widget.WizardPane, {
+	widgetType: "WizardPane",
+
+	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();
+		}
+	}
+});
+
+dojo.widget.tags.addParseTreeHandler("dojo:WizardPane");

Added: jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/widget/__package__.js
URL: http://svn.apache.org/viewcvs/jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/widget/__package__.js?rev=378118&view=auto
==============================================================================
--- jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/widget/__package__.js (added)
+++ jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/widget/__package__.js Wed Feb 15 15:30:01 2006
@@ -0,0 +1,22 @@
+/*
+	Copyright (c) 2004-2005, 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.hostenv.conditionalLoadModule({
+	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"]
+});
+dojo.hostenv.moduleLoaded("dojo.widget.*");

Added: jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/widget/html/Button.js
URL: http://svn.apache.org/viewcvs/jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/widget/html/Button.js?rev=378118&view=auto
==============================================================================
--- jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/widget/html/Button.js (added)
+++ jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/widget/html/Button.js Wed Feb 15 15:30:01 2006
@@ -0,0 +1,63 @@
+/*
+	Copyright (c) 2004-2005, 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.Button");
+dojo.require("dojo.widget.Button");
+
+dojo.deprecated("dojo.widget.Button",  "use dojo.widget.Button2", "0.4");
+
+dojo.widget.html.Button = function(){
+	// mix in the button properties
+	dojo.widget.Button.call(this);
+	dojo.widget.HtmlWidget.call(this);
+}
+dojo.inherits(dojo.widget.html.Button, dojo.widget.HtmlWidget);
+dojo.lang.extend(dojo.widget.html.Button, {
+
+	templatePath: dojo.uri.dojoUri("src/widget/templates/HtmlButtonTemplate.html"),
+	templateCssPath: dojo.uri.dojoUri("src/widget/templates/HtmlButtonTemplate.css"),
+
+	label: "",
+	labelNode: null,
+	containerNode: null,
+
+	postCreate: function(args, frag){
+		this.labelNode = this.containerNode;
+		/*
+		if(this.label != "undefined"){
+			this.domNode.appendChild(document.createTextNode(this.label));
+		}
+		*/
+	},
+	
+	onMouseOver: function(e){
+		dojo.html.addClass(this.domNode, "dojoButtonHover");
+		dojo.html.removeClass(this.domNode, "dojoButtonNoHover");
+	},
+	
+	onMouseOut: function(e){
+		dojo.html.removeClass(this.domNode, "dojoButtonHover");
+		dojo.html.addClass(this.domNode, "dojoButtonNoHover");
+	},
+
+	// By default, when I am clicked, click the item (link) inside of me.
+	// By default, a button is a disguised link.
+	// Todo: support actual submit and reset buttons.
+	onClick: function (e) {
+		var child = dojo.dom.getFirstChildElement(this.domNode);
+		if(child){
+			if(child.click){
+				child.click();
+			}else if(child.href){
+				location.href = child.href;
+			}
+		}
+	}
+});

Added: jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/widget/html/Button2.js
URL: http://svn.apache.org/viewcvs/jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/widget/html/Button2.js?rev=378118&view=auto
==============================================================================
--- jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/widget/html/Button2.js (added)
+++ jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/widget/html/Button2.js Wed Feb 15 15:30:01 2006
@@ -0,0 +1,280 @@
+/*
+	Copyright (c) 2004-2005, 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.Button2");
+dojo.require("dojo.lang.extras");
+dojo.require("dojo.html");
+dojo.require("dojo.style");
+
+dojo.require("dojo.widget.HtmlWidget");
+dojo.require("dojo.widget.Button2");
+
+dojo.widget.html.Button2 = function(){
+	// call superclass constructors
+	dojo.widget.HtmlWidget.call(this);
+	dojo.widget.Button2.call(this);
+}
+dojo.inherits(dojo.widget.html.Button2, dojo.widget.HtmlWidget);
+dojo.lang.extend(dojo.widget.html.Button2, dojo.widget.Button2.prototype);
+dojo.lang.extend(dojo.widget.html.Button2, {
+
+	templatePath: dojo.uri.dojoUri("src/widget/templates/HtmlButton2Template.html"),
+	templateCssPath: dojo.uri.dojoUri("src/widget/templates/HtmlButton2Template.css"),
+	
+	// button images
+	inactiveImg: "src/widget/templates/images/pill-button-blue_benji-",
+	activeImg: "src/widget/templates/images/pill-button-seagreen_benji-",
+	pressedImg: "src/widget/templates/images/pill-button-purple_benji-",
+	disabledImg: "src/widget/templates/images/pill-button-gray_benji-",
+	width2height: 1.0/3.0,
+
+	// attach points
+	containerNode: null,
+	leftImage: null,
+	centerImage: null,
+	rightImage: null,
+
+	fillInTemplate: function(args, frag){
+		if(this.caption != ""){
+			this.containerNode.appendChild(document.createTextNode(this.caption));
+		}
+		dojo.html.disableSelection(this.containerNode);
+		if ( this.disabled ) {
+			dojo.html.prependClass(this.domNode, "dojoButtonDisabled");
+		}
+		
+		// after the browser has had a little time to calculate the size needed
+		// for the button contents, size the button
+		dojo.lang.setTimeout(this, this.sizeMyself, 0);
+	},
+
+	onResized: function(){
+		this.sizeMyself();
+	},
+
+	sizeMyself: function(e){
+		this.height = dojo.style.getOuterHeight(this.containerNode);
+		this.containerWidth = dojo.style.getOuterWidth(this.containerNode);
+		var endWidth= this.height * this.width2height;
+
+		this.containerNode.style.left=endWidth+"px";
+
+		this.leftImage.height = this.rightImage.height = this.centerImage.height = this.height;
+		this.leftImage.width = this.rightImage.width = endWidth+1;
+		this.centerImage.width = this.containerWidth;
+		this.centerImage.style.left=endWidth+"px";
+		this._setImage(this.disabled ? this.disabledImg : this.inactiveImg);
+			
+		this.domNode.style.height=this.height + "px";
+		this.domNode.style.width= (this.containerWidth+2*endWidth) + "px";
+	},
+
+	onMouseOver: function(e){
+		if( this.disabled ){ return; }
+		dojo.html.prependClass(this.domNode, "dojoButtonHover");
+		this._setImage(this.activeImg);
+	},
+
+	onMouseDown: function(e){
+		if( this.disabled ){ return; }
+		dojo.html.prependClass(this.domNode, "dojoButtonDepressed");
+		dojo.html.removeClass(this.domNode, "dojoButtonHover");
+		this._setImage(this.pressedImg);
+	},
+	onMouseUp: function(e){
+		if( this.disabled ){ return; }
+		dojo.html.prependClass(this.domNode, "dojoButtonHover");
+		dojo.html.removeClass(this.domNode, "dojoButtonDepressed");
+		this._setImage(this.activeImg);
+	},
+
+	onMouseOut: function(e){
+		if( this.disabled ){ return; }
+		dojo.html.removeClass(this.domNode, "dojoButtonHover");
+		this._setImage(this.inactiveImg);
+	},
+
+	buttonClick: function(e){
+		if( !this.disabled && this.onClick ) { this.onClick(e); }
+	},
+
+	_setImage: function(prefix){
+		this.leftImage.src=dojo.uri.dojoUri(prefix + "l.gif");
+		this.centerImage.src=dojo.uri.dojoUri(prefix + "c.gif");
+		this.rightImage.src=dojo.uri.dojoUri(prefix + "r.gif");
+	},
+	
+	_toggleMenu: function(menuId){
+		var menu = dojo.widget.getWidgetById(menuId);
+		if ( !menu ) { return; }
+
+		if ( menu.open && !menu.isShowing) {
+			var x = dojo.style.getAbsoluteX(this.domNode, true);
+			var y = dojo.style.getAbsoluteY(this.domNode, true) + this.height;
+			menu.open(x, y, null, this.domNode);
+		} else if ( menu.close && menu.isShowing ){
+			menu.close();
+		} else {
+			menu.toggle();
+		}
+	}
+});
+
+/**** DropDownButton - push the button and a menu shows up *****/
+dojo.widget.html.DropDownButton2 = function(){
+	// call constructors of superclasses
+	dojo.widget.DropDownButton2.call(this);
+	dojo.widget.html.Button2.call(this);
+}
+dojo.inherits(dojo.widget.html.DropDownButton2, dojo.widget.html.Button2);
+dojo.lang.extend(dojo.widget.html.DropDownButton2, dojo.widget.DropDownButton2.prototype);
+
+dojo.lang.extend(dojo.widget.html.DropDownButton2, {
+
+	downArrow: "src/widget/templates/images/whiteDownArrow.gif",
+	disabledDownArrow: "src/widget/templates/images/whiteDownArrow.gif",
+
+	fillInTemplate: function(args, frag){
+		dojo.widget.html.DropDownButton2.superclass.fillInTemplate.call(this, args, frag);
+
+		// draw the arrow
+		var arrow = document.createElement("img");
+		arrow.src = dojo.uri.dojoUri(this.disabled ? this.disabledDownArrow : this.downArrow);
+		dojo.html.setClass(arrow, "downArrow");
+		this.containerNode.appendChild(arrow);
+	},
+
+	onClick: function (e){
+		if( this.disabled ){ return; }
+		this._toggleMenu(this.menuId);
+	}
+});
+
+/**** ComboButton - left side is normal button, right side shows menu *****/
+dojo.widget.html.ComboButton2 = function(){
+	// call constructors of superclasses
+	dojo.widget.html.Button2.call(this);
+	dojo.widget.ComboButton2.call(this);
+}
+dojo.inherits(dojo.widget.html.ComboButton2, dojo.widget.html.Button2);
+dojo.lang.extend(dojo.widget.html.ComboButton2, dojo.widget.ComboButton2.prototype);
+dojo.lang.extend(dojo.widget.html.ComboButton2, {
+
+	templatePath: dojo.uri.dojoUri("src/widget/templates/HtmlComboButton2Template.html"),
+
+	// attach points
+	leftPart: null,
+	rightPart: null,
+	arrowBackgroundImage: null,
+
+	// constants
+	splitWidth: 1,		// pixels between left&right part of button
+	arrowWidth: 10,		// width of segment holding down arrow
+
+	sizeMyself: function(e){
+		this.height = dojo.style.getOuterHeight(this.containerNode);
+		this.containerWidth = dojo.style.getOuterWidth(this.containerNode);
+		var endWidth= this.height/3;
+
+		// left part
+		this.leftImage.height = this.rightImage.height = this.centerImage.height = 
+			this.arrowBackgroundImage.height = this.height;
+		this.leftImage.width = endWidth+1;
+		this.centerImage.width = this.containerWidth;
+		this.leftPart.style.height = this.height + "px";
+		this.leftPart.style.width = endWidth + this.containerWidth + "px";
+		this._setImageL(this.disabled ? this.disabledImg : this.inactiveImg);
+
+		// right part
+		this.arrowBackgroundImage.width=this.arrowWidth;
+		this.rightImage.width = endWidth+1;
+		this.rightPart.style.height = this.height + "px";
+		this.rightPart.style.width = this.arrowWidth + endWidth + "px";
+		this._setImageR(this.disabled ? this.disabledImg : this.inactiveImg);
+
+		// outer container
+		this.domNode.style.height=this.height + "px";
+		var totalWidth = this.containerWidth+this.splitWidth+this.arrowWidth+2*endWidth;
+		this.domNode.style.width= totalWidth + "px";
+	},
+
+	/** functions on left part of button**/
+	leftOver: function(e){
+		if( this.disabled ){ return; }
+		dojo.html.prependClass(this.leftPart, "dojoButtonHover");
+		this._setImageL(this.activeImg);
+	},
+
+	leftDown: function(e){
+		if( this.disabled ){ return; }
+		dojo.html.prependClass(this.leftPart, "dojoButtonDepressed");
+		dojo.html.removeClass(this.leftPart, "dojoButtonHover");
+		this._setImageL(this.pressedImg);
+	},
+	leftUp: function(e){
+		if( this.disabled ){ return; }
+		dojo.html.prependClass(this.leftPart, "dojoButtonHover");
+		dojo.html.removeClass(this.leftPart, "dojoButtonDepressed");
+		this._setImageL(this.activeImg);
+	},
+
+	leftOut: function(e){
+		if( this.disabled ){ return; }
+		dojo.html.removeClass(this.leftPart, "dojoButtonHover");
+		this._setImageL(this.inactiveImg);
+	},
+
+	leftClick: function(e){
+		if ( !this.disabled && this.onClick ) {
+			this.onClick(e);
+		}
+	},
+
+	_setImageL: function(prefix){
+		this.leftImage.src=dojo.uri.dojoUri(prefix + "l.gif");
+		this.centerImage.src=dojo.uri.dojoUri(prefix + "c.gif");
+	},
+
+	/*** functions on right part of button ***/
+	rightOver: function(e){
+		if( this.disabled ){ return; }
+		dojo.html.prependClass(this.rightPart, "dojoButtonHover");
+		this._setImageR(this.activeImg);
+	},
+
+	rightDown: function(e){
+		if( this.disabled ){ return; }
+		dojo.html.prependClass(this.rightPart, "dojoButtonDepressed");
+		dojo.html.removeClass(this.rightPart, "dojoButtonHover");
+		this._setImageR(this.pressedImg);
+	},
+	rightUp: function(e){
+		if( this.disabled ){ return; }
+		dojo.html.prependClass(this.rightPart, "dojoButtonHover");
+		dojo.html.removeClass(this.rightPart, "dojoButtonDepressed");
+		this._setImageR(this.activeImg);
+	},
+
+	rightOut: function(e){
+		if( this.disabled ){ return; }
+		dojo.html.removeClass(this.rightPart, "dojoButtonHover");
+		this._setImageR(this.inactiveImg);
+	},
+
+	rightClick: function(e){
+		if( this.disabled ){ return; }
+		this._toggleMenu(this.menuId);
+	},
+
+	_setImageR: function(prefix){
+		this.arrowBackgroundImage.src=dojo.uri.dojoUri(prefix + "c.gif");
+		this.rightImage.src=dojo.uri.dojoUri(prefix + "r.gif");
+	}
+});

Added: jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/widget/html/Checkbox.js
URL: http://svn.apache.org/viewcvs/jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/widget/html/Checkbox.js?rev=378118&view=auto
==============================================================================
--- jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/widget/html/Checkbox.js (added)
+++ jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/html/dojo/src/widget/html/Checkbox.js Wed Feb 15 15:30:01 2006
@@ -0,0 +1,105 @@
+/*
+	Copyright (c) 2004-2005, The Dojo Foundation
+	All Rights Reserved.
+
+	Licensed under the Academic Free License version 2.1 or above OR the
+	modified BSD license. For more information on Dojo licensing, see:
+
+		http://dojotoolkit.org/community/licensing.shtml
+*/
+
+dojo.require("dojo.widget.Checkbox");
+dojo.provide("dojo.widget.html.Checkbox");
+
+// 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.html.Checkbox = function(){
+	dojo.widget.HtmlWidget.call(this);
+}
+
+dojo.inherits(dojo.widget.html.Checkbox, dojo.widget.HtmlWidget);
+
+dojo.lang.extend(dojo.widget.html.Checkbox, {
+	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'),
+
+	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(){
+
+		this.domNode.checked = !this.domNode.checked ? true : false;
+		this.updateImgSrc();
+	},
+
+	onChange: function(){
+
+		this.updateImgSrc();
+	},
+
+	updateImgSrc: function(){
+
+		this.imgNode.src = this.domNode.checked ? this.srcOn : this.srcOff;
+	}
+});
+



---------------------------------------------------------------------
To unsubscribe, e-mail: tapestry-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: tapestry-dev-help@jakarta.apache.org