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

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

Modified: struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/TimePicker.js
URL: http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/TimePicker.js?view=diff&rev=474551&r1=474550&r2=474551
==============================================================================
--- struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/TimePicker.js (original)
+++ struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/TimePicker.js Mon Nov 13 14:54:45 2006
@@ -1,5 +1,5 @@
 /*
-	Copyright (c) 2004-2005, The Dojo Foundation
+	Copyright (c) 2004-2006, The Dojo Foundation
 	All Rights Reserved.
 
 	Licensed under the Academic Free License version 2.1 or above OR the
@@ -9,24 +9,284 @@
 */
 
 dojo.provide("dojo.widget.TimePicker");
-dojo.provide("dojo.widget.TimePicker.util");
-dojo.require("dojo.widget.DomWidget");
+dojo.require("dojo.widget.*");
+dojo.require("dojo.widget.HtmlWidget");
+dojo.require("dojo.event.*");
+dojo.require("dojo.date.serialize");
+dojo.require("dojo.date.format");
+dojo.require("dojo.dom");
+dojo.require("dojo.html.style");
 
-dojo.widget.TimePicker = function(){
-	dojo.widget.Widget.call(this);
-	this.widgetType = "TimePicker";
-	this.isContainer = false;
-	// the following aliases prevent breaking people using 0.2.x
-	this.toRfcDateTime = dojo.widget.TimePicker.util.toRfcDateTime;
-	this.fromRfcDateTime = dojo.widget.TimePicker.util.fromRfcDateTime;
-	this.toAmPmHour = dojo.widget.TimePicker.util.toAmPmHour;
-	this.fromAmPmHour = dojo.widget.TimePicker.util.fromAmPmHour;
-}
+dojo.requireLocalization("dojo.i18n.calendar", "gregorian");
+dojo.requireLocalization("dojo.widget", "TimePicker");
 
-dojo.inherits(dojo.widget.TimePicker, dojo.widget.Widget);
-dojo.widget.tags.addParseTreeHandler("dojo:timepicker");
+dojo.widget.defineWidget(
+	"dojo.widget.TimePicker",
+	dojo.widget.HtmlWidget,
+	function(){
+		// selected time, JS Date object
+		this.time = "";
+		// set following flag to true if a default time should be set
+		this.useDefaultTime = false;
+		// set the following to true to set default minutes to current time, false to // use zero
+		this.useDefaultMinutes = false;
+		// rfc 3339 date
+		this.storedTime = "";
+		// time currently selected in the UI, stored in hours, minutes, seconds in the format that will be actually displayed
+		this.currentTime = {};
+		this.classNames = {
+			selectedTime: "selectedItem"
+		};
+		this.any = "any"; //FIXME: never used?
+		// dom node indecies for selected hour, minute, amPm, and "any time option"
+		this.selectedTime = {
+			hour: "",
+			minute: "",
+			amPm: "",
+			anyTime: false
+		};
 
-dojo.requireAfterIf("html", "dojo.widget.html.TimePicker");
+		// minutes are ordered as follows: ["12", "6", "1", "7", "2", "8", "3", "9", "4", "10", "5", "11"]
+		this.hourIndexMap = ["", 2, 4, 6, 8, 10, 1, 3, 5, 7, 9, 11, 0];
+		// minutes are ordered as follows: ["00", "30", "05", "35", "10", "40", "15", "45", "20", "50", "25", "55"]
+		this.minuteIndexMap = [0, 2, 4, 6, 8, 10, 1, 3, 5, 7, 9, 11];
+	},
+{
+	isContainer: false,
+	templatePath: dojo.uri.dojoUri("src/widget/templates/TimePicker.html"),
+	templateCssPath: dojo.uri.dojoUri("src/widget/templates/TimePicker.css"),
+
+	fillInTemplate: function(args, frag){
+		// Copy style info from input node to output node
+		var source = this.getFragNodeRef(frag);
+		dojo.html.copyStyle(this.domNode, source);
+
+		this.initData();
+		this.initUI();
+	},
+
+	postMixInProperties: function(localProperties, frag) {
+		dojo.widget.TimePicker.superclass.postMixInProperties.apply(this, arguments);
+		this.calendar = dojo.i18n.getLocalization("dojo.i18n.calendar", "gregorian", this.lang); // "am","pm"
+		this.widgetStrings = dojo.i18n.getLocalization("dojo.widget", "TimePicker", this.lang); // "any"
+	},
+
+	initData: function() {
+		// FIXME: doesn't currently validate the time before trying to set it
+		// Determine the date/time from stored info, or by default don't 
+		//  have a set time
+		// FIXME: should normalize against whitespace on storedTime... for now 
+		// just a lame hack
+		if(this.storedTime.indexOf("T")!=-1 && this.storedTime.split("T")[1] && this.storedTime!=" " && this.storedTime.split("T")[1]!="any") {
+			this.time = dojo.widget.TimePicker.util.fromRfcDateTime(this.storedTime, this.useDefaultMinutes, this.selectedTime.anyTime);
+		} else if (this.useDefaultTime) {
+			this.time = dojo.widget.TimePicker.util.fromRfcDateTime("", this.useDefaultMinutes, this.selectedTime.anyTime);
+		} else {
+			this.selectedTime.anyTime = true;
+			this.time = dojo.widget.TimePicker.util.fromRfcDateTime("", 0, 1);
+		}
+	},
+
+	initUI: function() {
+		// set UI to match the currently selected time
+		if(!this.selectedTime.anyTime && this.time) {
+			var amPmHour = dojo.widget.TimePicker.util.toAmPmHour(this.time.getHours());
+			var hour = amPmHour[0];
+			var isAm = amPmHour[1];
+			var minute = this.time.getMinutes();
+			var minuteIndex = parseInt(minute/5);
+			this.onSetSelectedHour(this.hourIndexMap[hour]);
+			this.onSetSelectedMinute(this.minuteIndexMap[minuteIndex]);
+			this.onSetSelectedAmPm(isAm);
+		} else {
+			this.onSetSelectedAnyTime();
+		}
+	},
+	
+	setTime: function(date) {
+		if(date) {
+			this.selectedTime.anyTime = false;
+			this.setDateTime(dojo.date.toRfc3339(date));
+		} else {
+			this.selectedTime.anyTime = true;
+		}
+		this.initData();
+		this.initUI();
+	},
+
+	setDateTime: function(rfcDate) {
+		this.storedTime = rfcDate;
+	},
+	
+	onClearSelectedHour: function(evt) {
+		this.clearSelectedHour();
+	},
+
+	onClearSelectedMinute: function(evt) {
+		this.clearSelectedMinute();
+	},
+
+	onClearSelectedAmPm: function(evt) {
+		this.clearSelectedAmPm();
+	},
+
+	onClearSelectedAnyTime: function(evt) {
+		this.clearSelectedAnyTime();
+		if(this.selectedTime.anyTime) {
+			this.selectedTime.anyTime = false;
+			this.time = dojo.widget.TimePicker.util.fromRfcDateTime("", this.useDefaultMinutes);
+			this.initUI();
+		}
+	},
+
+	clearSelectedHour: function() {
+		var hourNodes = this.hourContainerNode.getElementsByTagName("td");
+		for (var i=0; i<hourNodes.length; i++) {
+			dojo.html.setClass(hourNodes.item(i), "");
+		}
+	},
+
+	clearSelectedMinute: function() {
+		var minuteNodes = this.minuteContainerNode.getElementsByTagName("td");
+		for (var i=0; i<minuteNodes.length; i++) {
+			dojo.html.setClass(minuteNodes.item(i), "");
+		}
+	},
+
+	clearSelectedAmPm: function() {
+		var amPmNodes = this.amPmContainerNode.getElementsByTagName("td");
+		for (var i=0; i<amPmNodes.length; i++) {
+			dojo.html.setClass(amPmNodes.item(i), "");
+		}
+	},
+
+	clearSelectedAnyTime: function() {
+		dojo.html.setClass(this.anyTimeContainerNode, "anyTimeContainer");
+	},
+
+	onSetSelectedHour: function(evt) {
+		this.onClearSelectedAnyTime();
+		this.onClearSelectedHour();
+		this.setSelectedHour(evt);
+		this.onSetTime();
+	},
+
+	setSelectedHour: function(evt) {
+		if(evt && evt.target) {
+			if(evt.target.nodeType == dojo.dom.ELEMENT_NODE) {
+				var eventTarget = evt.target;
+			} else {
+				var eventTarget = evt.target.parentNode;
+			}
+			dojo.event.browser.stopEvent(evt);
+			dojo.html.setClass(eventTarget, this.classNames.selectedTime);
+			this.selectedTime["hour"] = eventTarget.innerHTML;
+		} else if (!isNaN(evt)) {
+			var hourNodes = this.hourContainerNode.getElementsByTagName("td");
+			if(hourNodes.item(evt)) {
+				dojo.html.setClass(hourNodes.item(evt), this.classNames.selectedTime);
+				this.selectedTime["hour"] = hourNodes.item(evt).innerHTML;
+			}
+		}
+		this.selectedTime.anyTime = false;
+	},
+
+	onSetSelectedMinute: function(evt) {
+		this.onClearSelectedAnyTime();
+		this.onClearSelectedMinute();
+		this.setSelectedMinute(evt);
+		this.selectedTime.anyTime = false;
+		this.onSetTime();
+	},
+
+	setSelectedMinute: function(evt) {
+		if(evt && evt.target) {
+			if(evt.target.nodeType == dojo.dom.ELEMENT_NODE) {
+				var eventTarget = evt.target;
+			} else {
+				var eventTarget = evt.target.parentNode;
+			}
+			dojo.event.browser.stopEvent(evt);
+			dojo.html.setClass(eventTarget, this.classNames.selectedTime);
+			this.selectedTime["minute"] = eventTarget.innerHTML;
+		} else if (!isNaN(evt)) {
+			var minuteNodes = this.minuteContainerNode.getElementsByTagName("td");
+			if(minuteNodes.item(evt)) {
+				dojo.html.setClass(minuteNodes.item(evt), this.classNames.selectedTime);
+				this.selectedTime["minute"] = minuteNodes.item(evt).innerHTML;
+			}
+		}
+	},
+
+	onSetSelectedAmPm: function(evt) {
+		this.onClearSelectedAnyTime();
+		this.onClearSelectedAmPm();
+		this.setSelectedAmPm(evt);
+		this.selectedTime.anyTime = false;
+		this.onSetTime();
+	},
+
+	setSelectedAmPm: function(evt) {
+		var eventTarget = evt.target;
+		if(evt && eventTarget) {
+			if(eventTarget.nodeType != dojo.dom.ELEMENT_NODE) {
+				eventTarget = eventTarget.parentNode;
+			}
+			dojo.event.browser.stopEvent(evt);
+			this.selectedTime.amPm = eventTarget.id;
+			dojo.html.setClass(eventTarget, this.classNames.selectedTime);
+		} else {
+			evt = evt ? 0 : 1;
+			var amPmNodes = this.amPmContainerNode.getElementsByTagName("td");
+			if(amPmNodes.item(evt)) {
+				this.selectedTime.amPm = amPmNodes.item(evt).id;
+				dojo.html.setClass(amPmNodes.item(evt), this.classNames.selectedTime);
+			}
+		}
+	},
+
+	onSetSelectedAnyTime: function(evt) {
+		this.onClearSelectedHour();
+		this.onClearSelectedMinute();
+		this.onClearSelectedAmPm();
+		this.setSelectedAnyTime();
+		this.onSetTime();
+	},
+
+	setSelectedAnyTime: function(evt) {
+		this.selectedTime.anyTime = true;
+		dojo.html.setClass(this.anyTimeContainerNode, this.classNames.selectedTime + " " + "anyTimeContainer");
+	},
+
+	onClick: function(evt) {
+		dojo.event.browser.stopEvent(evt);
+	},
+
+	onSetTime: function() {
+		if(this.selectedTime.anyTime) {
+			this.time = new Date();
+			var tempDateTime = dojo.widget.TimePicker.util.toRfcDateTime(this.time);
+			this.setDateTime(tempDateTime.split("T")[0]);
+		} else {
+			var hour = 12;
+			var minute = 0;
+			var isAm = false;
+			if(this.selectedTime["hour"]) {
+				hour = parseInt(this.selectedTime["hour"], 10);
+			}
+			if(this.selectedTime["minute"]) {
+				minute = parseInt(this.selectedTime["minute"], 10);
+			}
+			if(this.selectedTime["amPm"]) {
+				isAm = (this.selectedTime["amPm"].toLowerCase() == "am");
+			}
+			this.time = new Date();
+			this.time.setHours(dojo.widget.TimePicker.util.fromAmPmHour(hour, isAm));
+			this.time.setMinutes(minute);
+			this.setDateTime(dojo.widget.TimePicker.util.toRfcDateTime(this.time));
+		}
+	}
+});
 
 dojo.widget.TimePicker.util = new function() {
 	// utility functions
@@ -34,44 +294,13 @@
 		if(!jsDate) {
 			jsDate = new Date();
 		}
-		var year = jsDate.getFullYear();
-		var month = jsDate.getMonth() + 1;
-		if (month < 10) {
-			month = "0" + month.toString();
-		}
-		var date = jsDate.getDate();
-		if (date < 10) {
-			date = "0" + date.toString();
-		}
-		var hour = jsDate.getHours();
-		if (hour < 10) {
-			hour = "0" + hour.toString();
-		}
-		var minute = jsDate.getMinutes();
-		if (minute < 10) {
-			minute = "0" + minute.toString();
-		}
-		// no way to set seconds, so set to zero
-		var second = "00";
-		var timeZone = jsDate.getTimezoneOffset();
-		var timeZoneHour = parseInt(timeZone/60);
-		if(timeZoneHour > -10 && timeZoneHour < 0) {
-			timeZoneHour = "-0" + Math.abs(timeZoneHour);
-		} else if(timeZoneHour < 10) {
-			timeZoneHour = "+0" + timeZoneHour.toString();
-		} else if(timeZoneHour >= 10) {
-			timeZoneHour = "+" + timeZoneHour.toString();
-		}
-		var timeZoneMinute = timeZone%60;
-		if(timeZoneMinute < 10) {
-			timeZoneMinute = "0" + timeZoneMinute.toString();
-		}
-		return year + "-" + month + "-" + date + "T" + hour + ":" + minute + ":" + second + timeZoneHour +":" + timeZoneMinute;
+		jsDate.setSeconds(0);
+		return dojo.date.strftime(jsDate, "%Y-%m-%dT%H:%M:00%z"); //FIXME: use dojo.date.toRfc3339 instead
 	}
 
-	this.fromRfcDateTime = function(rfcDate, useDefaultMinutes) {
+	this.fromRfcDateTime = function(rfcDate, useDefaultMinutes, isAnyTime) {
 		var tempDate = new Date();
-		if(!rfcDate || !rfcDate.split("T")[1]) {
+		if(!rfcDate || rfcDate.indexOf("T")==-1) {
 			if(useDefaultMinutes) {
 				tempDate.setMinutes(Math.floor(tempDate.getMinutes()/5)*5);
 			} else {

Added: struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/TitlePane.js
URL: http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/TitlePane.js?view=auto&rev=474551
==============================================================================
--- struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/TitlePane.js (added)
+++ struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/TitlePane.js Mon Nov 13 14:54:45 2006
@@ -0,0 +1,61 @@
+/*
+	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.TitlePane");
+dojo.require("dojo.widget.*");
+dojo.require("dojo.widget.ContentPane");
+dojo.require("dojo.html.style");
+dojo.require("dojo.lfx.*");
+
+dojo.widget.defineWidget(
+	"dojo.widget.TitlePane",
+	dojo.widget.ContentPane,
+{
+	labelNode: "",
+	labelNodeClass: "",
+	containerNodeClass: "",
+	label: "",
+	
+	open: true,
+	templatePath: dojo.uri.dojoUri("src/widget/templates/TitlePane.html"),
+
+	postCreate: function() {
+		if (this.label) {
+			this.labelNode.appendChild(document.createTextNode(this.label));
+		}
+
+		if (this.labelNodeClass) {
+			dojo.html.addClass(this.labelNode, this.labelNodeClass);
+		}	
+
+		if (this.containerNodeClass) {
+			dojo.html.addClass(this.containerNode, this.containerNodeClass);
+		}	
+
+		if (!this.open) {
+			dojo.html.hide(this.containerNode);
+		}
+		dojo.widget.TitlePane.superclass.postCreate.apply(this, arguments);
+	},
+
+	onLabelClick: function() {
+		if (this.open) {
+			dojo.lfx.wipeOut(this.containerNode, 250).play();
+			this.open=false;
+		} else {
+			dojo.lfx.wipeIn(this.containerNode, 250).play();
+			this.open=true;
+		}
+	},
+
+	setLabel: function(label) {
+		this.labelNode.innerHTML=label;
+	}
+});

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

Added: struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/Toaster.js
URL: http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/Toaster.js?view=auto&rev=474551
==============================================================================
--- struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/Toaster.js (added)
+++ struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/Toaster.js Mon Nov 13 14:54:45 2006
@@ -0,0 +1,245 @@
+/*
+	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.Toaster");
+
+dojo.require("dojo.widget.*");
+dojo.require("dojo.lfx.*");
+dojo.require("dojo.html.iframe");
+
+// This is mostly taken from Jesse Kuhnert's MessageNotifier.
+// Modified by Bryan Forbes to support topics and a variable delay.
+
+dojo.widget.defineWidget(
+	"dojo.widget.Toaster",
+	dojo.widget.HtmlWidget,
+	{
+		templateString: '<div dojoAttachPoint="clipNode"><div dojoAttachPoint="containerNode" dojoAttachEvent="onClick:onSelect"><div dojoAttachPoint="contentNode"></div></div></div>',
+		templateCssPath: dojo.uri.dojoUri("src/widget/templates/Toaster.css"),
+		
+		clipNode: null,
+
+		messageTopic: "",
+		contentNode: null,
+
+		_scrollConnected: false,
+		
+		// possible message types
+		messageTypes: {
+			MESSAGE: "MESSAGE",
+			WARNING: "WARNING",
+			ERROR: "ERROR",
+			FATAL: "FATAL"
+		},
+		defaultType: "MESSAGE",
+
+		// css classes
+		clipCssClass: "dojoToasterClip",
+		containerCssClass: "dojoToasterContainer",
+		contentCssClass: "dojoToasterContent",
+		messageCssClass: "dojoToasterMessage",
+		warningCssClass: "dojoToasterWarning",
+		errorCssClass: "dojoToasterError",
+		fatalCssClass: "dojoToasterFatal",
+		
+		positionDirection: "br-up",
+		positionDirectionTypes: ["br-up", "br-left", "bl-up", "bl-right", "tr-down", "tr-left", "tl-down", "tl-right"],
+		showDelay: 2000,
+
+		slideAnim: null,
+		fadeAnim: null,
+
+		bgIframe: null,
+
+		postCreate: function(){
+			this.hide();
+			dojo.html.setClass(this.clipNode, this.clipCssClass);
+			dojo.html.addClass(this.containerNode, this.containerCssClass);
+			dojo.html.setClass(this.contentNode, this.contentCssClass);
+			if(this.messageTopic){
+				dojo.event.topic.subscribe(this.messageTopic, this, "handleMessage");
+			}
+			if(!this.positionDirection || !dojo.lang.inArray(this.positionDirectionTypes, this.positionDirection)){
+				this.positionDirection = this.positionDirectionTypes.BRU;
+			}
+		},
+
+		handleMessage: function(msg){
+			if(dojo.lang.isString(msg)){
+				this.setContent(msg);
+			}else{
+				this.setContent(msg["message"], msg["type"], msg["delay"]);
+			}
+		},
+
+		setContent: function(msg, messageType, delay){
+			var delay = delay||this.showDelay;
+			// sync animations so there are no ghosted fades and such
+			if(this.slideAnim && this.slideAnim.status() == "playing"){
+				dojo.lang.setTimeout(50, dojo.lang.hitch(this, function(){
+					this.setContent(msg, messageType);
+				}));
+				return;
+			}else if(this.slideAnim){
+				this.slideAnim.stop();
+				if(this.fadeAnim) this.fadeAnim.stop();
+			}
+			if(!msg){
+				dojo.debug(this.widgetId + ".setContent() incoming content was null, ignoring.");
+				return;
+			}
+			if(!this.positionDirection || !dojo.lang.inArray(this.positionDirectionTypes, this.positionDirection)){
+				dojo.raise(this.widgetId + ".positionDirection is an invalid value: " + this.positionDirection);
+			}
+
+			// determine type of content and apply appropriately
+			dojo.html.removeClass(this.containerNode, this.messageCssClass);
+			dojo.html.removeClass(this.containerNode, this.warningCssClass);
+			dojo.html.removeClass(this.containerNode, this.errorCssClass);
+			dojo.html.removeClass(this.containerNode, this.fatalCssClass);
+
+			dojo.html.clearOpacity(this.containerNode);
+			
+			if(msg instanceof String || typeof msg == "string"){
+				this.contentNode.innerHTML = msg;
+			}else if(dojo.html.isNode(msg)){
+				this.contentNode.innerHTML = dojo.html.getContentAsString(msg);
+			}else{
+				dojo.raise("Toaster.setContent(): msg is of unknown type:" + msg);
+			}
+
+			switch(messageType){
+				case this.messageTypes.WARNING:
+					dojo.html.addClass(this.containerNode, this.warningCssClass);
+					break;
+				case this.messageTypes.ERROR:
+					dojo.html.addClass(this.containerNode, this.errorCssClass);
+					break
+				case this.messageTypes.FATAL:
+					dojo.html.addClass(this.containerNode, this.fatalCssClass);
+					break;
+				case this.messageTypes.MESSAGE:
+				default:
+					dojo.html.addClass(this.containerNode, this.messageCssClass);
+					break;
+			}
+
+			// now do funky animation of widget appearing from
+			// bottom right of page and up
+			this.show();
+
+			var nodeSize = dojo.html.getMarginBox(this.containerNode);
+
+			// sets up initial position of container node and slide-out direction
+			if(this.positionDirection.indexOf("-up") >= 0){
+				this.containerNode.style.left=0+"px";
+				this.containerNode.style.top=nodeSize.height + 10 + "px";
+			}else if(this.positionDirection.indexOf("-left") >= 0){
+				this.containerNode.style.left=nodeSize.width + 10 +"px";
+				this.containerNode.style.top=0+"px";
+			}else if(this.positionDirection.indexOf("-right") >= 0){
+				this.containerNode.style.left = 0 - nodeSize.width - 10 + "px";
+				this.containerNode.style.top = 0+"px";
+			}else if(this.positionDirection.indexOf("-down") >= 0){
+				this.containerNode.style.left = 0+"px";
+				this.containerNode.style.top = 0 - nodeSize.height - 10 + "px";
+			}else{
+				dojo.raise(this.widgetId + ".positionDirection is an invalid value: " + this.positionDirection);
+			}
+
+			this.slideAnim = dojo.lfx.html.slideTo(
+				this.containerNode,
+				{ top: 0, left: 0 },
+				450,
+				null,
+				dojo.lang.hitch(this, function(nodes, anim){
+					dojo.lang.setTimeout(dojo.lang.hitch(this, function(evt){
+						// we must hide the iframe in order to fade
+						// TODO: figure out how to fade with a BackgroundIframe
+						if(this.bgIframe){
+							this.bgIframe.hide();
+						}
+						// can't do a fadeHide because we're fading the
+						// inner node rather than the clipping node
+						this.fadeAnim = dojo.lfx.html.fadeOut(
+							this.containerNode,
+							1000,
+							null,
+							dojo.lang.hitch(this, function(evt){
+								this.hide();
+							})).play();
+					}), delay);
+				})).play();
+		},
+
+		placeClip: function(){
+			var scroll = dojo.html.getScroll();
+			var view = dojo.html.getViewport();
+
+			var nodeSize = dojo.html.getMarginBox(this.containerNode);
+
+			// sets up the size of the clipping node
+			this.clipNode.style.height = nodeSize.height+"px";
+			this.clipNode.style.width = nodeSize.width+"px";
+
+			// sets up the position of the clipping node
+			if(this.positionDirection.match(/^t/)){
+				this.clipNode.style.top = scroll.top+"px";
+			}else if(this.positionDirection.match(/^b/)){
+				this.clipNode.style.top = (view.height - nodeSize.height - 2 + scroll.top)+"px";
+			}
+			if(this.positionDirection.match(/^[tb]r-/)){
+				this.clipNode.style.left = (view.width - nodeSize.width - 1 - scroll.left)+"px";
+			}else if(this.positionDirection.match(/^[tb]l-/)){
+				this.clipNode.style.left = 0 + "px";
+			}
+
+			this.clipNode.style.clip = "rect(0px, " + nodeSize.width + "px, " + nodeSize.height + "px, 0px)";
+
+			if(dojo.render.html.ie){
+				if(!this.bgIframe){
+					this.bgIframe = new dojo.html.BackgroundIframe(this.containerNode);
+					this.bgIframe.setZIndex(this.containerNode);
+				}
+				this.bgIframe.onResized();
+				this.bgIframe.show();
+			}
+		},
+
+		onSelect: function(e) { },
+
+		onScroll: function(){
+			this.placeClip();
+		},
+
+		show: function(){
+			dojo.widget.Toaster.superclass.show.call(this);
+
+			this.placeClip();
+
+			if(!this._scrollConnected){
+				this._scrollConnected = true;
+				dojo.event.connect(window, "onscroll", this, "onScroll");
+			}
+		},
+
+		hide: function(){
+			dojo.widget.Toaster.superclass.hide.call(this);
+
+			if(this._scrollConnected){
+				this._scrollConnected = false;
+				dojo.event.disconnect(window, "onscroll", this, "onScroll");
+			}
+
+			dojo.html.setOpacity(this.containerNode, 1.0);
+		}
+	},
+	"html"
+);

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

Modified: struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/Toggler.js
URL: http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/Toggler.js?view=diff&rev=474551&r1=474550&r2=474551
==============================================================================
--- struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/Toggler.js (original)
+++ struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/Toggler.js Mon Nov 13 14:54:45 2006
@@ -1,5 +1,5 @@
 /*
-	Copyright (c) 2004-2005, The Dojo Foundation
+	Copyright (c) 2004-2006, The Dojo Foundation
 	All Rights Reserved.
 
 	Licensed under the Academic Free License version 2.1 or above OR the
@@ -8,33 +8,27 @@
 		http://dojotoolkit.org/community/licensing.shtml
 */
 
-dojo.provide("dojo.widget.Toggler");
-dojo.require("dojo.widget.*");
-dojo.require("dojo.event.*");
-
-// clicking on this node shows/hides another widget
-
-dojo.widget.Toggler = function(){
-	dojo.widget.DomWidget.call(this);
-}
-
-dojo.inherits(dojo.widget.Toggler, dojo.widget.DomWidget);
-
-dojo.lang.extend(dojo.widget.Toggler, {
-	widgetType: "Toggler",
-	
-	// Associated widget 
-	targetId: '',
-	
-	fillInTemplate: function() {
-		dojo.event.connect(this.domNode, "onclick", this, "onClick");
-	},
-	
-	onClick: function() {
-		var pane = dojo.widget.getWidgetById(this.targetId);
-		if ( !pane || !pane.toggle ) { return; }
-		pane.explodeSrc = this.domNode;
-		pane.doToggle();
-	}
-});
-dojo.widget.tags.addParseTreeHandler("dojo:toggler");
+dojo.provide("dojo.widget.Toggler");
+dojo.require("dojo.widget.*");
+dojo.require("dojo.event.*");
+
+// clicking on this node shows/hides another widget
+
+dojo.widget.defineWidget(
+	"dojo.widget.Toggler",
+	dojo.widget.HtmlWidget,
+{
+	// Associated widget 
+	targetId: '',
+	
+	fillInTemplate: function() {
+		dojo.event.connect(this.domNode, "onclick", this, "onClick");
+	},
+	
+	onClick: function() {
+		var pane = dojo.widget.byId(this.targetId);
+		if(!pane){ return; }
+		pane.explodeSrc = this.domNode;
+		pane.toggleShowing();
+	}
+});

Modified: struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/Toolbar.js
URL: http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/Toolbar.js?view=diff&rev=474551&r1=474550&r2=474551
==============================================================================
--- struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/Toolbar.js (original)
+++ struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/Toolbar.js Mon Nov 13 14:54:45 2006
@@ -1,5 +1,5 @@
 /*
-	Copyright (c) 2004-2005, The Dojo Foundation
+	Copyright (c) 2004-2006, The Dojo Foundation
 	All Rights Reserved.
 
 	Licensed under the Academic Free License version 2.1 or above OR the
@@ -8,141 +8,128 @@
 		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");
+dojo.require("dojo.html.style");
 
 /* ToolbarContainer
  *******************/
-dojo.widget.html.ToolbarContainer = function() {
-	dojo.widget.HtmlWidget.call(this);
+dojo.widget.defineWidget(
+	"dojo.widget.ToolbarContainer",
+	dojo.widget.HtmlWidget,
+{
+	isContainer: true,
 
-	this.widgetType = "ToolbarContainer";
-	this.isContainer = true;
+	templateString: '<div class="toolbarContainer" dojoAttachPoint="containerNode"></div>',
+	templateCssPath: dojo.uri.dojoUri("src/widget/templates/Toolbar.css"),
 
-	this.templateString = '<div class="toolbarContainer" dojoAttachPoint="containerNode"></div>';
-	this.templateCssPath = dojo.uri.dojoUri("src/widget/templates/HtmlToolbar.css");
-
-	this.getItem = function(name) {
+	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) {
+			if(child instanceof dojo.widget.Toolbar) {
 				var item = child.getItem(name);
 				if(item) { return item; }
 			}
 		}
 		return null;
-	}
+	},
 
-	this.getItems = function() {
+	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) {
+			if(child instanceof dojo.widget.Toolbar) {
 				items = items.concat(child.getItems());
 			}
 		}
 		return items;
-	}
+	},
 
-	this.enable = function() {
+	enable: function() {
 		for(var i = 0; i < this.children.length; i++) {
 			var child = this.children[i];
-			if(child instanceof dojo.widget.html.Toolbar) {
+			if(child instanceof dojo.widget.Toolbar) {
 				child.enable.apply(child, arguments);
 			}
 		}
-	}
+	},
 
-	this.disable = function() {
+	disable: function() {
 		for(var i = 0; i < this.children.length; i++) {
 			var child = this.children[i];
-			if(child instanceof dojo.widget.html.Toolbar) {
+			if(child instanceof dojo.widget.Toolbar) {
 				child.disable.apply(child, arguments);
 			}
 		}
-	}
+	},
 
-	this.select = function(name) {
+	select: function(name) {
 		for(var i = 0; i < this.children.length; i++) {
 			var child = this.children[i];
-			if(child instanceof dojo.widget.html.Toolbar) {
+			if(child instanceof dojo.widget.Toolbar) {
 				child.select(arguments);
 			}
 		}
-	}
+	},
 
-	this.deselect = function(name) {
+	deselect: function(name) {
 		for(var i = 0; i < this.children.length; i++) {
 			var child = this.children[i];
-			if(child instanceof dojo.widget.html.Toolbar) {
+			if(child instanceof dojo.widget.Toolbar) {
 				child.deselect(arguments);
 			}
 		}
-	}
+	},
 
-	this.getItemsState = function() {
+	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) {
+			if(child instanceof dojo.widget.Toolbar) {
 				dojo.lang.mixin(values, child.getItemsState());
 			}
 		}
 		return values;
-	}
+	},
 
-	this.getItemsActiveState = function() {
+	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) {
+			if(child instanceof dojo.widget.Toolbar) {
 				dojo.lang.mixin(values, child.getItemsActiveState());
 			}
 		}
 		return values;
-	}
+	},
 
-	this.getItemsSelectedState = function() {
+	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) {
+			if(child instanceof dojo.widget.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;
+dojo.widget.defineWidget(
+	"dojo.widget.Toolbar",
+	dojo.widget.HtmlWidget,
+{
+	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>';
+	templateString: '<div class="toolbar" dojoAttachPoint="containerNode" unselectable="on" dojoOnMouseover="_onmouseover" dojoOnMouseout="_onmouseout" dojoOnClick="_onclick" dojoOnMousedown="_onmousedown" dojoOnMouseup="_onmouseup"></div>',
 
 	// given a node, tries to find it's toolbar item
-	this._getItem = function(node) {
+	_getItem: function(node) {
 		var start = new Date();
 		var widget = null;
 		while(node && node != this.domNode) {
@@ -158,49 +145,48 @@
 			node = node.parentNode;
 		}
 		return widget;
-	}
+	},
 
-	this._onmouseover = function(e) {
+	_onmouseover: function(e) {
 		var widget = this._getItem(e.target);
 		if(widget && widget._onmouseover) { widget._onmouseover(e); }
-	}
+	},
 
-	this._onmouseout = function(e) {
+	_onmouseout: function(e) {
 		var widget = this._getItem(e.target);
 		if(widget && widget._onmouseout) { widget._onmouseout(e); }
-	}
+	},
 
-	this._onclick = function(e) {
+	_onclick: function(e) {
 		var widget = this._getItem(e.target);
-		if(widget && widget._onclick){ 
+		if(widget && widget._onclick){
 			widget._onclick(e);
 		}
-	}
+	},
 
-	this._onmousedown = function(e) {
+	_onmousedown: function(e) {
 		var widget = this._getItem(e.target);
 		if(widget && widget._onmousedown) { widget._onmousedown(e); }
-	}
+	},
 
-	this._onmouseup = function(e) {
+	_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) {
+	addChild: function(item, pos, props) {
 		var widget = dojo.widget.ToolbarItem.make(item, null, props);
-		var ret = oldAddChild.call(this, widget, null, pos, null);
+		var ret = dojo.widget.Toolbar.superclass.addChild.call(this, widget, null, pos, null);
 		return ret;
-	}
+	},
 
-	this.push = function() {
+	push: function() {
 		for(var i = 0; i < arguments.length; i++) {
 			this.addChild(arguments[i]);
 		}
-	}
+	},
 
-	this.getItem = function(name) {
+	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];
@@ -208,9 +194,9 @@
 				&& child._name == name) { return child; }
 		}
 		return null;
-	}
+	},
 
-	this.getItems = function() {
+	getItems: function() {
 		var items = [];
 		for(var i = 0; i < this.children.length; i++) {
 			var child = this.children[i];
@@ -219,9 +205,9 @@
 			}
 		}
 		return items;
-	}
+	},
 
-	this.getItemsState = function() {
+	getItemsState: function() {
 		var values = {};
 		for(var i = 0; i < this.children.length; i++) {
 			var child = this.children[i];
@@ -233,25 +219,25 @@
 			}
 		}
 		return values;
-	}
+	},
 
-	this.getItemsActiveState = function() {
+	getItemsActiveState: function() {
 		var values = this.getItemsState();
 		for(var item in values) {
 			values[item] = values[item].enabled;
 		}
 		return values;
-	}
+	},
 
-	this.getItemsSelectedState = function() {
+	getItemsSelectedState: function() {
 		var values = this.getItemsState();
 		for(var item in values) {
 			values[item] = values[item].selected;
 		}
 		return values;
-	}
+	},
 
-	this.enable = function() {
+	enable: function() {
 		var items = arguments.length ? arguments : this.children;
 		for(var i = 0; i < items.length; i++) {
 			var child = this.getItem(items[i]);
@@ -259,9 +245,9 @@
 				child.enable(false, true);
 			}
 		}
-	}
+	},
 
-	this.disable = function() {
+	disable: function() {
 		var items = arguments.length ? arguments : this.children;
 		for(var i = 0; i < items.length; i++) {
 			var child = this.getItem(items[i]);
@@ -269,25 +255,25 @@
 				child.disable();
 			}
 		}
-	}
+	},
 
-	this.select = function() {
+	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() {
+	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() {
+	setValue: function() {
 		for(var i = 0; i < arguments.length; i += 2) {
 			var name = arguments[i], value = arguments[i+1];
 			var item = this.getItem(name);
@@ -298,9 +284,7 @@
 			}
 		}
 	}
-}
-dojo.inherits(dojo.widget.html.Toolbar, dojo.widget.HtmlWidget);
-dojo.widget.tags.addParseTreeHandler("dojo:toolbar");
+});
 
 /* ToolbarItem hierarchy:
 	- ToolbarItem
@@ -315,17 +299,15 @@
 
 /* ToolbarItem
  **************/
-dojo.widget.ToolbarItem = function() {
-	dojo.widget.HtmlWidget.call(this);
-}
-dojo.inherits(dojo.widget.ToolbarItem, dojo.widget.HtmlWidget);
-
-dojo.lang.extend(dojo.widget.ToolbarItem, {
+dojo.widget.defineWidget(
+	"dojo.widget.ToolbarItem",
+	dojo.widget.HtmlWidget,
+{
 	templateString: '<span unselectable="on" class="toolbarItem"></span>',
 
 	_name: null,
 	getName: function() { return this._name; },
-	setName: function(value) { return this._name = value; },
+	setName: function(value) { return (this._name = value); },
 	getValue: function() { return this.getName(); },
 	setValue: function(value) { return this.setName(value); },
 
@@ -406,7 +388,7 @@
 	_label: "",
 	getLabel: function() { return this._label; },
 	setLabel: function(value) {
-		var ret = this._label = value;
+		var ret = (this._label = value);
 		if(!this.labelNode) {
 			this.labelNode = document.createElement("span");
 			this.domNode.appendChild(this.labelNode);
@@ -462,8 +444,9 @@
 	},
 
 	_onmouseover: function(e) {
-		if(!this._enabled) { return };
+		if(!this._enabled) { return; }
 		dojo.html.addClass(this.domNode, "hover");
+		this._fireEvent("onMouseOver");
 	},
 
 	_onmouseout: function(e) {
@@ -472,6 +455,7 @@
 		if(!this._selected) {
 			dojo.html.removeClass(this.domNode, "selected");
 		}
+		this._fireEvent("onMouseOut");
 	},
 
 	_onclick: function(e) {
@@ -484,7 +468,7 @@
 
 	_onmousedown: function(e) {
 		if(e.preventDefault) { e.preventDefault(); }
-		if(!this._enabled) { return };
+		if(!this._enabled) { return; }
 		dojo.html.addClass(this.domNode, "down");
 		if(this._toggleItem) {
 			if(this.parent.preventDeselect && this._selected) {
@@ -492,12 +476,20 @@
 			}
 			this.toggleSelected();
 		}
+		this._fireEvent("onMouseDown");
 	},
 
 	_onmouseup: function(e) {
 		dojo.html.removeClass(this.domNode, "down");
+		this._fireEvent("onMouseUp");
 	},
 
+	onClick: function() { },
+	onMouseOver: function() { },
+	onMouseOut: function() { },
+	onMouseDown: function() { },
+	onMouseUp: function() { },
+
 	fillInTemplate: function(args, frag) {
 		if(args.name) { this._name = args.name; }
 		if(args.selected) { this.select(); }
@@ -523,7 +515,7 @@
 		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)
+		item = dojo.widget.createWidget(wh, props);
 	} else if(typeof wh == "string" || wh instanceof String) {
 		switch(wh.charAt(0)) {
 			case "|":
@@ -559,32 +551,42 @@
 
 /* ToolbarButtonGroup
  *********************/
-dojo.widget.html.ToolbarButtonGroup = function() {
-	dojo.widget.ToolbarItem.call(this);
+dojo.widget.defineWidget(
+	"dojo.widget.ToolbarButtonGroup",
+	dojo.widget.ToolbarItem,
+{
+	isContainer: true,
 
-	this.widgetType = "ToolbarButtonGroup";
-	this.isContainer = true;
-
-	this.templateString = '<span unselectable="on" class="toolbarButtonGroup" dojoAttachPoint="containerNode"></span>';
+	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 = "";
+	defaultButton: "",
+
+    postCreate: function() {
+        for (var i = 0; i < this.children.length; i++) {
+            this._injectChild(this.children[i]);
+        }
+    },
 
-	var oldAddChild = this.addChild;
-	this.addChild = function(item, pos, props) {
+	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
+		var ret = dojo.widget.ToolbarButtonGroup.superclass.addChild.call(this, widget, null, pos, null);
+        this._injectChild(widget);
+        return ret;
+    },
+
+    _injectChild: function(widget) {
+        dojo.event.connect(widget, "onSelect", this, "onChildSelected");
+        dojo.event.connect(widget, "onDeselect", this, "onChildDeSelected");
+        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) {
+	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];
@@ -592,9 +594,9 @@
 				&& child._name == name) { return child; }
 		}
 		return null;
-	}
+	},
 
-	this.getItems = function() {
+	getItems: function() {
 		var items = [];
 		for(var i = 0; i < this.children.length; i++) {
 			var child = this.children[i];
@@ -603,13 +605,17 @@
 			}
 		}
 		return items;
-	}
+	},
 
-	this.onChildSelected = function(e) {
+	onChildSelected: function(e) {
 		this.select(e._name);
-	}
+	},
 
-	this.enable = function(force, preventEvent) {
+	onChildDeSelected: function(e) {
+		this._fireEvent("onChangeSelect", this._value);
+	},
+
+	enable: function(force, preventEvent) {
 		for(var i = 0; i < this.children.length; i++) {
 			var child = this.children[i];
 			if(child instanceof dojo.widget.ToolbarItem) {
@@ -619,21 +625,21 @@
 				}
 			}
 		}
-	}
+	},
 
-	this.disable = function(force, preventEvent) {
+	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; }
+	_value: "",
+	getValue: function() { return this._value; },
 
-	this.select = function(name, force, preventEvent) {
+	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) {
@@ -641,7 +647,7 @@
 					child.select(force, preventEvent);
 					this._value = name;
 				} else {
-					child.deselect(true, preventEvent);
+					child.deselect(true, true);
 				}
 			}
 		}
@@ -649,27 +655,20 @@
 			this._fireEvent("onSelect", this._value);
 			this._fireEvent("onChangeSelect", this._value);
 		}
-	}
-	this.setValue = this.select;
+	},
+	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");
+	preventDeselect: false // if true, once you select one, you can't have none selected
+});
 
 /* 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",
-
+dojo.widget.defineWidget(
+	"dojo.widget.ToolbarButton",
+	dojo.widget.ToolbarItem,
+{
 	fillInTemplate: function(args, frag) {
-		dojo.widget.html.ToolbarButton.superclass.fillInTemplate.call(this, args, frag);
+		dojo.widget.ToolbarButton.superclass.fillInTemplate.call(this, args, frag);
 		dojo.html.addClass(this.domNode, "toolbarButton");
 		if(this._icon) {
 			this.setIcon(this._icon);
@@ -693,25 +692,20 @@
 
 /* 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",
-	
+dojo.widget.defineWidget(
+	"dojo.widget.ToolbarDialog",
+	dojo.widget.ToolbarButton,
+{
 	fillInTemplate: function (args, frag) {
-		dojo.widget.html.ToolbarDialog.superclass.fillInTemplate.call(this, args, frag);
+		dojo.widget.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");
 	}
@@ -720,13 +714,11 @@
 
 /* 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");
+dojo.widget.defineWidget(
+	"dojo.widget.ToolbarMenu",
+	dojo.widget.ToolbarDialog,
+	{}
+);
 
 /* ToolbarMenuItem
  ******************/
@@ -735,17 +727,16 @@
 
 /* ToolbarSeparator
  **********************/
-dojo.widget.html.ToolbarSeparator = function() {
-	dojo.widget.ToolbarItem.call(this);
+dojo.widget.defineWidget(
+	"dojo.widget.ToolbarSeparator",
+	dojo.widget.ToolbarItem,
+{
+	templateString: '<span unselectable="on" class="toolbarItem toolbarSeparator"></span>',
 
-	this.widgetType = "ToolbarSeparator";
-	this.templateString = '<span unselectable="on" class="toolbarItem toolbarSeparator"></span>';
+	defaultIconPath: new dojo.uri.dojoUri("src/widget/templates/buttons/sep.gif"),
 
-	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);
+	fillInTemplate: function(args, frag, skip) {
+		dojo.widget.ToolbarSeparator.superclass.fillInTemplate.call(this, args, frag);
 		this._name = this.widgetId;
 		if(!skip) {
 			if(!this._icon) {
@@ -753,87 +744,41 @@
 			}
 			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");
+	_onmouseover: null,
+    _onmouseout: null,
+    _onclick: null,
+    _onmousedown: null,
+    _onmouseup: null
+});
 
 /* 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);
+dojo.widget.defineWidget(
+	"dojo.widget.ToolbarSpace",
+	dojo.widget.ToolbarSeparator,
+{
+	fillInTemplate: function(args, frag, skip) {
+		dojo.widget.ToolbarSpace.superclass.fillInTemplate.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"; }
-		dojo.html.body().appendChild(this.dialog);
-	},
-	
-	hideDialog: function (e) {
-		dojo.widget.html.ToolbarSelect.superclass.hideDialog.call(this, e);
-		this.dialog.parentNode.removeChild(this.dialog);
-	}
-
-});*/
+dojo.widget.defineWidget(
+	"dojo.widget.ToolbarSelect",
+	dojo.widget.ToolbarItem,
+{
+	templateString: '<span class="toolbarItem toolbarSelect" unselectable="on"><select dojoAttachPoint="selectBox" dojoOnChange="changed"></select></span>',
 
-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);
+	fillInTemplate: function(args, frag) {
+		dojo.widget.ToolbarSelect.superclass.fillInTemplate.call(this, args, frag, true);
 		var keys = args.values;
 		var i = 0;
 		for(var val in keys) {
@@ -842,119 +787,160 @@
 			opt.innerHTML = val;
 			this.selectBox.appendChild(opt);
 		}
-	}
+	},
 
-	this.changed = function(e) {
+	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);
+	setEnabled: function(is, force, preventEvent) {
+		var ret = dojo.widget.ToolbarSelect.superclass.setEnabled.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");
+	_onmouseover: null,
+    _onmouseout: null,
+    _onclick: null,
+    _onmousedown: null,
+    _onmouseup: null
+});
 
 /* 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) {
+dojo.widget.Icon = function(enabled, disabled, hovered, selected){
+	if(!arguments.length){
+		// FIXME: should this be dojo.raise?
 		throw new Error("Icon must have at least an enabled state");
 	}
-	var states = ["enabled", "disabled", "hover", "selected"];
+	var states = ["enabled", "disabled", "hovered", "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]) {
+	this.getState = function(){ return currentState; }
+	this.setState = function(value){
+		if(dojo.lang.inArray(states, value)){
+			if(this[value]){
 				currentState = value;
-				domNode.setAttribute("src", this[currentState].src);
+				var img = this[currentState];
+				if ((dojo.render.html.ie55 || dojo.render.html.ie60) && img.src && img.src.match(/[.]png$/i) ) {
+					domNode.width = img.width||img.offsetWidth;
+					domNode.height = img.height||img.offsetHeight;
+					domNode.setAttribute("src", dojo.uri.dojoUri("src/widget/templates/images/blank.gif").uri);
+					domNode.style.filter="progid:DXImageTransform.Microsoft.AlphaImageLoader(src='"+img.src+"',sizingMethod='image')";
+				} else {
+					domNode.setAttribute("src", img.src);
+				}
 			}
-		} else {
+		}else{
 			throw new Error("Invalid state set on Icon (state: " + value + ")");
 		}
 	}
 
-	this.setSrc = function(state, value) {
-		if(/^img$/i.test(value.tagName)) {
+	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) {
+		}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.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.enable = function(){ this.setState("enabled"); }
+	this.disable = function(){ this.setState("disabled"); }
+	this.hover = function(){ this.setState("hovered"); }
+	this.select = function(){ this.setState("selected"); }
 
-	this.getSize = function() {
+	this.getSize = function(){
 		return {
 			width: domNode.width||domNode.offsetWidth,
 			height: domNode.height||domNode.offsetHeight
 		};
 	}
 
-	this.setSize = function(w, h) {
+	this.setSize = function(w, h){
 		domNode.width = w;
 		domNode.height = h;
 		return { width: w, height: h };
 	}
 
-	this.getNode = function() {
+	this.getNode = function(){
 		return domNode;
 	}
 
-	this.getSrc = function(state) {
-		if(state) { return this[state].src; }
+	this.getSrc = function(state){
+		if(state){ return this[state].src; }
 		return domNode.src||"";
 	}
 
-	this.update = function() {
+	this.update = function(){
 		this.setState(currentState);
 	}
 
-	for(var i = 0; i < states.length; i++) {
+	for(var i = 0; i < states.length; i++){
 		var arg = arguments[i];
 		var state = states[i];
 		this[state] = null;
-		if(!arg) { continue; }
+		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) {
+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);
 }
+
+/* ToolbarColorDialog
+ ******************/
+dojo.widget.defineWidget(
+	"dojo.widget.ToolbarColorDialog",
+	dojo.widget.ToolbarDialog,
+{
+ 	palette: "7x10",
+
+	fillInTemplate: function (args, frag) {
+		dojo.widget.ToolbarColorDialog.superclass.fillInTemplate.call(this, args, frag);
+		this.dialog = dojo.widget.createWidget("ColorPalette", {palette: this.palette});
+		this.dialog.domNode.style.position = "absolute";
+
+		dojo.event.connect(this.dialog, "onColorSelect", this, "_setValue");
+	},
+
+	_setValue: function(color) {
+		this._value = color;
+		this._fireEvent("onSetValue", color);
+	},
+
+	showDialog: function (e) {
+		dojo.widget.ToolbarColorDialog.superclass.showDialog.call(this, e);
+		var abs = dojo.html.getAbsolutePosition(this.domNode, true);
+		var y = abs.y + dojo.html.getBorderBox(this.domNode).height;
+		this.dialog.showAt(abs.x, y);
+	},
+
+	hideDialog: function (e) {
+		dojo.widget.ToolbarColorDialog.superclass.hideDialog.call(this, e);
+		this.dialog.hide();
+	}
+});
\ No newline at end of file

Modified: struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/Tooltip.js
URL: http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/Tooltip.js?view=diff&rev=474551&r1=474550&r2=474551
==============================================================================
--- struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/Tooltip.js (original)
+++ struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/Tooltip.js Mon Nov 13 14:54:45 2006
@@ -1,5 +1,5 @@
 /*
-	Copyright (c) 2004-2005, The Dojo Foundation
+	Copyright (c) 2004-2006, The Dojo Foundation
 	All Rights Reserved.
 
 	Licensed under the Academic Free License version 2.1 or above OR the
@@ -8,17 +8,158 @@
 		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");
+dojo.provide("dojo.widget.Tooltip");
+dojo.require("dojo.widget.ContentPane");
+dojo.require("dojo.widget.PopupContainer");
+dojo.require("dojo.uri.Uri");
+dojo.require("dojo.widget.*");
+dojo.require("dojo.event.*");
+dojo.require("dojo.html.style");
+dojo.require("dojo.html.util");
+dojo.require("dojo.html.iframe");
+
+dojo.widget.defineWidget(
+	"dojo.widget.Tooltip",
+	[dojo.widget.ContentPane, dojo.widget.PopupContainerBase],
+	{
+		isContainer: true,
+
+		// Constructor arguments
+		caption: "",
+		showDelay: 500,
+		hideDelay: 100,
+		connectId: "",
+
+		templateCssPath: dojo.uri.dojoUri("src/widget/templates/TooltipTemplate.css"),
+
+		fillInTemplate: function(args, frag){
+			if(this.caption != ""){
+				this.domNode.appendChild(document.createTextNode(this.caption));
+			}
+			this._connectNode = dojo.byId(this.connectId);
+			dojo.widget.Tooltip.superclass.fillInTemplate.call(this, args, frag);
+
+			this.addOnLoad(this, "_loadedContent");
+			dojo.html.addClass(this.domNode, "dojoTooltip");
+
+			//copy style from input node to output node
+			var source = this.getFragNodeRef(frag);
+			dojo.html.copyStyle(this.domNode, source);
+
+			//apply the necessary css rules to the node so that it can popup
+			this.applyPopupBasicStyle();
+		},
+
+		postCreate: function(args, frag){
+			dojo.event.connect(this._connectNode, "onmouseover", this, "onMouseOver");
+			dojo.widget.Tooltip.superclass.postCreate.call(this, args, frag);
+		},
+
+		onMouseOver: function(e){
+			this._mouse = {x: e.pageX, y: e.pageY};
+
+			// Start tracking mouse movements, so we know when to cancel timers or erase the tooltip
+			if(!this._tracking){
+				dojo.event.connect(document.documentElement, "onmousemove", this, "onMouseMove");
+				this.tracking=true;
+			}
+
+			this._onHover(e);			
+		},
+
+		onMouseMove: function(e) {
+			this._mouse = {x: e.pageX, y: e.pageY};
+
+			if(dojo.html.overElement(this._connectNode, e) || dojo.html.overElement(this.domNode, e)){
+				this._onHover(e);
+			} else {
+				// mouse has been moved off the element/tooltip
+				// note: can't use onMouseOut to detect this because the "explode" effect causes
+				// spurious onMouseOut events (due to interference from outline), w/out corresponding onMouseOver
+				this._onUnHover(e);
+			}
+		},
+
+		_onHover: function(e) {
+			if(this._hover){ return; }
+			this._hover=true;
+
+			// If the tooltip has been scheduled to be erased, cancel that timer
+			// since we are hovering over element/tooltip again
+			if(this._hideTimer) {
+				clearTimeout(this._hideTimer);
+				delete this._hideTimer;
+			}
+			
+			// If tooltip not showing yet then set a timer to show it shortly
+			if(!this.isShowingNow && !this._showTimer){
+				this._showTimer = setTimeout(dojo.lang.hitch(this, "open"), this.showDelay);
+			}
+		},
+
+		_onUnHover: function(e){
+			if(!this._hover){ return; }
+			this._hover=false;
+
+			if(this._showTimer){
+				clearTimeout(this._showTimer);
+				delete this._showTimer;
+			}
+			if(this.isShowingNow && !this._hideTimer){
+				this._hideTimer = setTimeout(dojo.lang.hitch(this, "close"), this.hideDelay);
+			}
+			
+			// If we aren't showing the tooltip, then we can stop tracking the mouse now;
+			// otherwise must track the mouse until tooltip disappears
+			if(!this.isShowingNow){
+				dojo.event.disconnect(document.documentElement, "onmousemove", this, "onMouseMove");
+				this._tracking=false;
+			}
+		},
+
+		open: function() {
+			if (this.isShowingNow) { return; }
+
+			dojo.widget.PopupContainerBase.prototype.open.call(this, this._mouse.x, this._mouse.y, null, [this._mouse.x, this._mouse.y], "TL,TR,BL,BR", [10,15]);
+		},
+
+		close: function() {
+			if (this.isShowingNow) {
+				if ( this._showTimer ) {
+					clearTimeout(this._showTimer);
+					delete this._showTimer;
+				}
+				if ( this._hideTimer ) {
+					clearTimeout(this._hideTimer);
+					delete this._hideTimer;
+				}
+				dojo.event.disconnect(document.documentElement, "onmousemove", this, "onMouseMove");
+				this._tracking=false;
+				dojo.widget.PopupContainerBase.prototype.close.call(this);
+			}
+		},
+
+		_position: function(){
+			this.move(this._mouse.x, this._mouse.y, [10,15], "TL,TR,BL,BR");
+		},
+
+		_loadedContent: function(){
+			if(this.isShowingNow){
+				// the tooltip has changed size due to downloaded contents, so reposition it
+				this._position();
+			}
+		},
+
+		checkSize: function(){
+			// checkSize() is called when the user has resized the browser window,
+			// but that doesn't affect this widget (or this widget's children)
+			// so it can be safely ignored
+		},
+
+		uninitialize: function(){
+			this.close();
+			dojo.event.disconnect(this._connectNode, "onmouseover", this, "onMouseOver");
+		}
+
+	}
+);

Modified: struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/Tree.js
URL: http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/Tree.js?view=diff&rev=474551&r1=474550&r2=474551
==============================================================================
--- struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/Tree.js (original)
+++ struts/struts2/trunk/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/Tree.js Mon Nov 13 14:54:45 2006
@@ -1,5 +1,5 @@
 /*
-	Copyright (c) 2004-2005, The Dojo Foundation
+	Copyright (c) 2004-2006, The Dojo Foundation
 	All Rights Reserved.
 
 	Licensed under the Academic Free License version 2.1 or above OR the
@@ -8,53 +8,122 @@
 		http://dojotoolkit.org/community/licensing.shtml
 */
 
+/**
+ * Tree model does all the drawing, visual node management etc.
+ * Throws events about clicks on it, so someone may catch them and process
+ * Tree knows nothing about DnD stuff, covered in TreeDragAndDrop and (if enabled) attached by controller
+*/
+
+/**
+ * TODO: use domNode.cloneNode instead of createElement for grid
+ * Should be faster (lyxsus)
+ */
 dojo.provide("dojo.widget.Tree");
-dojo.provide("dojo.widget.HtmlTree");
-dojo.provide("dojo.widget.TreeNode");
-dojo.provide("dojo.widget.HtmlTreeNode");
 
+dojo.require("dojo.widget.*");
 dojo.require("dojo.event.*");
-dojo.require("dojo.fx.html");
-dojo.require("dojo.widget.Container");
-
-// make it a tag
-dojo.widget.tags.addParseTreeHandler("dojo:Tree");
-dojo.widget.tags.addParseTreeHandler("dojo:TreeNode");
-
-dojo.widget.HtmlTree = function() {
-	dojo.widget.html.Container.call(this);
-}
-dojo.inherits(dojo.widget.HtmlTree, dojo.widget.html.Container);
+dojo.require("dojo.io.*");
+dojo.require("dojo.widget.HtmlWidget");
+dojo.require("dojo.widget.TreeNode");
+dojo.require("dojo.html.common");
+dojo.require("dojo.html.selection");
+
+
+dojo.widget.defineWidget("dojo.widget.Tree", dojo.widget.HtmlWidget, function() {
+	this.eventNames = {};
+
+	this.tree = this;
+	this.DNDAcceptTypes = [];
+	this.actionsDisabled = [];
 
-dojo.lang.extend(dojo.widget.HtmlTree, {
+},
+{
 	widgetType: "Tree",
 
-	domNode: null,
+	eventNamesDefault: {
+		// new child does not get domNode filled in (only template draft)
+		// until addChild->createDOMNode is called(program way) OR createDOMNode (html-way)
+		// hook events to operate on new DOMNode, create dropTargets etc
+		createDOMNode: "createDOMNode",
+		// tree created.. Perform tree-wide actions if needed
+		treeCreate: "treeCreate",
+		treeDestroy: "treeDestroy",
+		// expand icon clicked
+		treeClick: "treeClick",
+		// node icon clicked
+		iconClick: "iconClick",
+		// node title clicked
+		titleClick: "titleClick",
+
+		moveFrom: "moveFrom",
+		moveTo: "moveTo",
+		addChild: "addChild",
+		removeNode: "removeNode",
+		expand: "expand",
+		collapse: "collapse"
+	},
+
+	isContainer: true,
+
+	DNDMode: "off",
+
+	lockLevel: 0, // lock ++ unlock --, so nested locking works fine
+
+	strictFolders: true,
+
+	DNDModes: {
+		BETWEEN: 1,
+		ONTO: 2
+	},
+
+	DNDAcceptTypes: "",
+
+	templateCssPath: dojo.uri.dojoUri("src/widget/templates/images/Tree/Tree.css"),
 
-	templateCssPath: dojo.uri.dojoUri("src/widget/templates/Tree.css"),
 	templateString: '<div class="dojoTree"></div>',
 
-	selectedNode: null,
-	toggler: null,
+	isExpanded: true, // consider this "root node" to be always expanded
+
+	isTree: true,
+
+	objectId: "",
+
+	// autoCreate if not "off"
+	// used to get the autocreated controller ONLY.
+	// generally, tree DOES NOT KNOW about its CONTROLLER, it just doesn't care
+	// controller gets messages via dojo.event
+	controller: "",
+
+	// autoCreate if not "off"
+	// used to get the autocreated selector ONLY.
+	// generally, tree DOES NOT KNOW its SELECTOR
+	// binding is made with dojo.event
+	selector: "",
 
+	// used ONLY at initialization time
+	menu: "", // autobind menu if menu's widgetId is set here
+
+	expandLevel: "", // expand to level automatically
 
 	//
 	// these icons control the grid and expando buttons for the whole tree
 	//
 
-	blankIconSrc: dojo.uri.dojoUri("src/widget/templates/images/treenode_blank.gif").toString(),
+	blankIconSrc: dojo.uri.dojoUri("src/widget/templates/images/Tree/treenode_blank.gif"),
 
-	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
+	gridIconSrcT: dojo.uri.dojoUri("src/widget/templates/images/Tree/treenode_grid_t.gif"), // for non-last child grid
+	gridIconSrcL: dojo.uri.dojoUri("src/widget/templates/images/Tree/treenode_grid_l.gif"), // for last child grid
+	gridIconSrcV: dojo.uri.dojoUri("src/widget/templates/images/Tree/treenode_grid_v.gif"), // vertical line
+	gridIconSrcP: dojo.uri.dojoUri("src/widget/templates/images/Tree/treenode_grid_p.gif"), // for under parent item child icons
+	gridIconSrcC: dojo.uri.dojoUri("src/widget/templates/images/Tree/treenode_grid_c.gif"), // for under child item child icons
+	gridIconSrcX: dojo.uri.dojoUri("src/widget/templates/images/Tree/treenode_grid_x.gif"), // grid for sole root item
+	gridIconSrcY: dojo.uri.dojoUri("src/widget/templates/images/Tree/treenode_grid_y.gif"), // grid for last rrot item
+	gridIconSrcZ: dojo.uri.dojoUri("src/widget/templates/images/Tree/treenode_grid_z.gif"), // for under root parent item child icon
+
+	expandIconSrcPlus: dojo.uri.dojoUri("src/widget/templates/images/Tree/treenode_expand_plus.gif"),
+	expandIconSrcMinus: dojo.uri.dojoUri("src/widget/templates/images/Tree/treenode_expand_minus.gif"),
+	expandIconSrcLoading: dojo.uri.dojoUri("src/widget/templates/images/Tree/treenode_loading.gif"),
 
-	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,
@@ -67,449 +136,428 @@
 	showGrid: true,
 	showRootGrid: true,
 
-	toggle: "default",
-	toggleDuration: 150,
-
+	actionIsDisabled: function(action) {
+		var _this = this;
+		return dojo.lang.inArray(_this.actionsDisabled, action)
+	},
 
-	//
-	// subscribable events
-	//
 
-	publishSelectionTopic: "",
-	publishExpandedTopic: "",
-	publishCollapsedTopic: "",
+	actions: {
+    	ADDCHILD: "ADDCHILD"
+	},
 
 
-	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();
+	getInfo: function() {
+		var info = {
+			widgetId: this.widgetId,
+			objectId: this.objectId
 		}
-	},
 
-	postCreate: function(){
-		this.buildTree();
+		return info;
 	},
 
-	buildTree: function(){
+	initializeController: function() {
+		if (this.controller != "off") {
+			if (this.controller) {
+				this.controller = dojo.widget.byId(this.controller);
+			}
+			else {
+				// create default controller here
+				dojo.require("dojo.widget.TreeBasicController");
+				this.controller = dojo.widget.createWidget("TreeBasicController",
+					{ DNDController: (this.DNDMode ? "create" : ""), dieWithTree: true }
+				 );
 
-		dojo.html.disableSelection(this.domNode);
+			}
+			this.controller.listenTree(this); // controller listens to my events
 
-		for(var i=0; i<this.children.length; i++){
+		} else {
+			this.controller = null;
+		}
+	},
 
-			this.children[i].isFirstNode = (i == 0) ? true : false;
-			this.children[i].isLastNode = (i == this.children.length-1) ? true : false;
+	initializeSelector: function() {
 
-			var node = this.children[i].buildNode(this, 0);
+		if (this.selector != "off") {
+			if (this.selector) {
+				this.selector = dojo.widget.byId(this.selector);
+			}
+			else {
+				// create default controller here
+				dojo.require("dojo.widget.TreeSelector");
+				this.selector = dojo.widget.createWidget("TreeSelector", {dieWithTree: true});
+			}
 
-			this.domNode.appendChild(node);
+			this.selector.listenTree(this);
+
+		} else {
+			this.selector = null;
 		}
+	},
 
+	initialize: function(args, frag){
 
-		//
-		// when we don't show root toggles, we need to auto-expand root nodes
-		//
+		var _this = this;
 
-		if (!this.showRootGrid){
-			for(var i=0; i<this.children.length; i++){
-				this.children[i].expand();
+		for(name in this.eventNamesDefault) {
+			if (dojo.lang.isUndefined(this.eventNames[name])) {
+				this.eventNames[name] = this.widgetId+"/"+this.eventNamesDefault[name];
 			}
 		}
 
-		for(var i=0; i<this.children.length; i++){
-			this.children[i].startMe();
+		for(var i=0; i<this.actionsDisabled.length; i++) {
+			this.actionsDisabled[i] = this.actionsDisabled[i].toUpperCase();
 		}
-	},
-
-	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.DNDMode == "off") {
+			this.DNDMode = 0;
+		} else if (this.DNDMode == "between") {
+			this.DNDMode = this.DNDModes.ONTO | this.DNDModes.BETWEEN;
+		} else if (this.DNDMode == "onto") {
+			this.DNDMode = this.DNDModes.ONTO;
 		}
 
-		if (this.children.length){
+		this.expandLevel = parseInt(this.expandLevel);
 
-			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();
-			}
+		this.initializeSelector();
+		this.initializeController();
 
-			child.isFirstNode = true;
+		if (this.menu) {
+			this.menu = dojo.widget.byId(this.menu);
+			this.menu.listenTree(this);
 		}
 
 
+		this.containerNode = this.domNode;
 
-		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;
+	postCreate: function() {
+		this.createDOMNode();
+	},
 
-			child.isLastNode = true;
-		}
 
-		this.children.push(child);
-		var node = child.buildNode(childTree, childDepth);
+	createDOMNode: function() {
 
-		if (this.widgetType == 'Tree'){
-			this.domNode.appendChild(node);
-		}else{
-			this.containerNode.appendChild(node);
-		}
+		dojo.html.disableSelection(this.domNode);
 
-		child.startMe();
-	}
-});
+		for(var i=0; i<this.children.length; i++){
+			this.children[i].parent = this; // root nodes have tree as parent
 
+			var node = this.children[i].createDOMNode(this, 0);
 
-dojo.widget.HtmlTreeNode = function() {
-	dojo.widget.HtmlWidget.call(this);
-}
 
-dojo.inherits(dojo.widget.HtmlTreeNode, dojo.widget.HtmlWidget);
+			this.domNode.appendChild(node);
+		}
 
-dojo.lang.extend(dojo.widget.HtmlTreeNode, {
-	widgetType: "TreeNode",
-	isContainer: true,
-	messWithMyChildren: true,
 
-	domNode: null,
-	continerNode: null,
+		if (!this.showRootGrid){
+			for(var i=0; i<this.children.length; i++){
+				this.children[i].expand();
+			}
+		}
 
-	templateString: '<div class="dojoTreeNode"><div dojoAttachPoint="containerNode"></div></div>',
+		dojo.event.topic.publish(this.eventNames.treeCreate, { source: this } );
 
-	childIconSrc: '',
+	},
 
-	childIcon: null,
-	underChildIcon: null,
-	expandIcon: null,
 
-	title: "",
+	destroy: function() {
+		dojo.event.topic.publish(this.tree.eventNames.treeDestroy, { source: this } );
 
-	labelNode: null, // the item label
-	imgs: null, // an array of icons imgs
-	rowNode: null, // the tr
+		return dojo.widget.HtmlWidget.prototype.destroy.apply(this, arguments);
+	},
 
-	tree: null,
-	parentNode: null,
-	depth: 0,
 
-	isFirstNode: false,
-	isLastNode: false,
-	isExpanded: false,
-	isParent: false,
-	booted: false,
+	addChild: function(child, index) {
 
-	buildNode: function(tree, depth){
+//		dojo.debug("doAddChild "+index+" called for "+child);
 
-		this.tree = tree;
-		this.depth = depth;
+		var message = {
+			child: child,
+			index: index,
+			parent: this,
+			// remember if dom was already initialized
+			// initialized => no createDOMNode => no createDOMNode event
+			domNodeInitialized: child.domNodeInitialized
+		}
 
+		this.doAddChild.apply(this, arguments);
 
-		//
-		// add the tree icons
-		//
+		dojo.event.topic.publish(this.tree.eventNames.addChild, message);
+	},
 
-		this.imgs = [];
 
-		for(var i=0; i<this.depth+2; i++){
+	// not called for initial tree building. See createDOMNode instead.
+	// builds child html node if needed
+	// index is "last node" by default
+	/**
+	 * FIXME: Is it possible that removeNode from the tree will cause leaks cause of attached events ?
+	 * if yes, then only attach events in addChild and detach in remove.. Seems all ok yet.
+	*/
+	doAddChild: function(child, index){
 
-			var img = document.createElement('img');
+		if (dojo.lang.isUndefined(index)) {
+			index = this.children.length;
+		}
 
-			img.style.width = this.tree.iconWidth + 'px';
-			img.style.height = this.tree.iconHeight + 'px';
-			img.src = this.tree.blankIconSrc;
-			img.style.verticalAlign = 'middle';
+		if (!child.isTreeNode){
+			dojo.raise("You can only add TreeNode widgets to a "+this.widgetType+" widget!");
+			return;
+		}
 
-			this.domNode.insertBefore(img, this.containerNode);
+		// usually it is impossible to change "isFolder" state, but if anyone wants to add a child to leaf,
+		// it is possible program-way.
+		if (this.isTreeNode){
+			if (!this.isFolder) { // just became a folder.
+				//dojo.debug("becoming folder "+this);
+				this.setFolder();
+			}
+		}
 
-			this.imgs.push(img);
+		// adjust tree
+		var _this = this;
+		dojo.lang.forEach(child.getDescendants(), function(elem) { elem.tree = _this.tree; });
+
+		// fix parent
+		child.parent = this;
+
+
+		// no dynamic loading for those who become parents
+		if (this.isTreeNode) {
+			this.state = this.loadStates.LOADED;
+		}
+
+		// add new child into DOM after it was added into children
+		if (index < this.children.length) { // children[] already has child
+			//dojo.debug("Inserting before "+this.children[index].title);
+			dojo.html.insertBefore(child.domNode, this.children[index].domNode);
+		} else {
+			this.containerNode.appendChild(child.domNode);
+			if (this.isExpanded && this.isTreeNode) {
+				/* When I add children to hidden containerNode => show container w/ them */
+				this.showChildren();
+			}
 		}
 
-		this.expandIcon = this.imgs[this.imgs.length-2];
-		this.childIcon = this.imgs[this.imgs.length-1];
 
+		this.children.splice(index, 0, child);
 
-		//
-		// add the cell label
-		//
+		//dojo.debugShallow(this.children);
 
 
-		this.labelNode = document.createElement('span');
+		// if node exists - adjust its depth, otherwise build it
+		if (child.domNodeInitialized) {
+			var d = this.isTreeNode ? this.depth : -1;
+			child.adjustDepth( d - child.depth + 1 );
 
-		this.labelNode.appendChild(document.createTextNode(this.title));
 
-		this.domNode.insertBefore(this.labelNode, this.containerNode);
+			// update icons to link generated dom with Tree => updateParentGrid
+			// if I moved child from LastNode inside the tree => need to link it up'n'down =>
+			// updateExpandGridColumn
+			// if I change depth => need to update all grid..
+			child.updateIconTree();
+		} else {
+			//dojo.debug("Create domnode ");
+			child.depth = this.isTreeNode ? this.depth+1 : 0;
+			child.createDOMNode(child.tree, child.depth);
+		}
 
-		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');
+		// Use-case:
+		// When previous sibling was created => it was last, no children after it
+		// so it did not create link down => let's add it for all descendants
+		// Use-case:
+		// a child was moved down under the last node so last node should be updated
+		var prevSibling = child.getPreviousSibling();
+		if (child.isLastChild() && prevSibling) {
+			prevSibling.updateExpandGridColumn();
+		}
 
 
-		//
-		// create the child rows
-		//
+		//dojo.debug("Added child "+child);
 
-		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){
+	makeBlankImg: function() {
+		var img = document.createElement('img');
 
-		if (this.isExpanded){
-			this.collapse();
-		}else{
-			this.expand();
-		}
-	},
+		img.style.width = this.iconWidth + 'px';
+		img.style.height = this.iconHeight + 'px';
+		img.src = this.blankIconSrc;
+		img.style.verticalAlign = 'middle';
 
-	onIconClick: function(){
-		this.onLabelClick();
+		return img;
 	},
 
-	onLabelClick: function(){
 
-		if (this.tree.selectedNode == this){
+	updateIconTree: function(){
+
+		//dojo.debug("Update icons for "+this)
+		if (!this.isTree) {
+			this.updateIcons();
+		}
 
-			//this.editInline();
-			dojo.debug('TODO: start inline edit here!');
-			return;
+		for(var i=0; i<this.children.length; i++){
+			this.children[i].updateIconTree();
 		}
 
-		if (this.tree.selectedNode){ this.tree.selectedNode.deselect(); }
+	},
 
-		this.tree.selectedNode = this;
-		this.tree.selectedNode.select();
+	toString: function() {
+		return "["+this.widgetType+" ID:"+this.widgetId+"]"
 	},
 
-	select: function(){
 
-		dojo.html.addClass(this.labelNode, 'dojoTreeNodeLabelSelected');
 
-		dojo.event.topic.publish(this.tree.publishSelectionTopic, this.widgetId);
-	},
 
-	deselect: function(){
+	/**
+	 * Move child to newParent as last child
+	 * redraw tree and update icons.
+	 *
+	 * Called by target, saves source in event.
+	 * events are published for BOTH trees AFTER update.
+	*/
+	move: function(child, newParent, index) {
 
-		dojo.html.removeClass(this.labelNode, 'dojoTreeNodeLabelSelected');
-	},
+		//dojo.debug(child+" "+newParent+" at "+index);
 
-	updateIcons: function(){
+		var oldParent = child.parent;
+		var oldTree = child.tree;
 
-		this.imgs[0].style.display = this.tree.showRootGrid ? 'inline' : 'none';
+		this.doMove.apply(this, arguments);
 
+		var newParent = child.parent;
+		var newTree = child.tree;
 
-		//
-		// set the expand icon
-		//
+		var message = {
+				oldParent: oldParent, oldTree: oldTree,
+				newParent: newParent, newTree: newTree,
+				child: child
+		};
 
-		if (this.isParent){
-			this.expandIcon.src = this.isExpanded ? this.tree.expandIconSrcMinus : this.tree.expandIconSrcPlus;
-		}else{
-			this.expandIcon.src = this.tree.blankIconSrc;
-		}
+		/* publish events here about structural changes for both source and target trees */
+		dojo.event.topic.publish(oldTree.eventNames.moveFrom, message);
+		dojo.event.topic.publish(newTree.eventNames.moveTo, message);
 
+	},
 
-		//
-		// set the grid under the expand icon
-		//
 
-		if (this.tree.showGrid){
-			if (this.depth){
+	/* do actual parent change here. Write remove child first */
+	doMove: function(child, newParent, index) {
+		//var parent = child.parent;
+		child.parent.doRemoveNode(child);
 
-				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);
-		}
+		newParent.doAddChild(child, index);
+	},
 
 
-		//
-		// set the child icon
-		//
 
-		if (this.childIconSrc){
-			this.childIcon.style.display = 'inline';
-			this.childIcon.src = this.childIconSrc;
-		}else{
-			this.childIcon.style.display = 'none';
-		}
+// ================================ removeNode ===================================
 
+	removeNode: function(child) {
+		if (!child.parent) return;
 
-		//
-		// set the grid under the child icon
-		//
+		var oldTree = child.tree;
+		var oldParent = child.parent;
 
-		if ((this.depth || this.tree.showRootGrid) && this.tree.showGrid){
+		var removedChild = this.doRemoveNode.apply(this, arguments);
 
-			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);
-			}
-		}
+		dojo.event.topic.publish(this.tree.eventNames.removeNode,
+			{ child: removedChild, tree: oldTree, parent: oldParent }
+		);
 
+		return removedChild;
+	},
 
-		//
-		// set the vertical grid icons
-		//
 
-		var parent = this.parentNode;
+	doRemoveNode: function(child) {
+		if (!child.parent) return;
 
-		for(var i=0; i<this.depth; i++){
+		var parent = child.parent;
 
-			var idx = this.imgs.length-(3+i);
+		var children = parent.children;
 
-			this.setGridImage(idx, (this.tree.showGrid && !parent.isLastNode) ? this.tree.gridIconSrcV : this.tree.blankIconSrc);
 
-			parent = parent.parentNode;
+		var index = child.getParentIndex();
+		if (index < 0) {
+			dojo.raise("Couldn't find node "+child+" for removal");
 		}
 
-	},
 
-	setGridImage: function(idx, src){
+		children.splice(index,1);
+		dojo.html.removeNode(child.domNode);
 
-		if (idx < 0){
-			idx = this.imgs.length + idx;
+		if (parent.children.length == 0 && !parent.isTree) {
+			parent.containerNode.style.display = "none";
 		}
 
-		this.imgs[idx].style.backgroundImage = 'url(' + src + ')';
-	},
+		// if WAS last node (children.length decreased already) and has prevSibling
+		if (index == children.length && index>0) {
+			children[index-1].updateExpandGridColumn();
+		}
+		// if it WAS first node in WHOLE TREE -
+		// update link up of its former lower neighbour(if exists still)
+		if (parent instanceof dojo.widget.Tree && index == 0 && children.length>0) {
+			children[0].updateExpandGrid();
+		}
 
-	updateIconTree: function(){
+		//parent.updateIconTree();
 
-		this.updateIcons();
 
-		for(var i=0; i<this.children.length; i++){
-			this.children[i].updateIconTree();
-		}
-	},
+		child.parent = child.tree = null;
 
-	expand: function(){
-		this.showChildren();
-		this.isExpanded = true;
-		this.updateIcons();
+		return child;
 	},
 
-	collapse: function(){
-		this.hideChildren();
-		this.isExpanded = false;
-		this.updateIcons();
+	markLoading: function() {
+		// no way to mark tree loading
 	},
 
-	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);
+	unMarkLoading: function() {
+		// no way to show that tree finished loading
 	},
 
-	showChildren: function(){
 
-		if (this.booted){
-			this.tree.toggler.show(this.containerNode);
-		}else{
-			this.containerNode.style.display = 'block';
+	lock: function() {
+		!this.lockLevel && this.markLoading();
+		this.lockLevel++;
+	},
+	unlock: function() {
+		if (!this.lockLevel) {
+			dojo.raise("unlock: not locked");
 		}
-		dojo.event.topic.publish(this.tree.publishExpandedTopic, this.widgetId);
+		this.lockLevel--;
+		!this.lockLevel && this.unMarkLoading();
 	},
 
-	startMe: function(){
-
-		this.booted = true;
-		for(var i=0; i<this.children.length; i++){
-			this.children[i].startMe();
+	isLocked: function() {
+		var node = this;
+		while (true) {
+			if (node.lockLevel) {
+				return true;
+			}
+			if (node instanceof dojo.widget.Tree) {
+				break;
+			}
+			node = node.parent;
 		}
-	},
 
-	addChild: function(child){
+		return false;
+	},
 
-		this.tree.addChild.call(this, child);
+	flushLock: function() {
+		this.lockLevel = 0;
+		this.unMarkLoading();
 	}
-
 });
-
-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'; });
-	}
-}